blob: e32fa68fb26ec8b53b2b48ea0a1b6fb06e35987f [file] [log] [blame]
Harald Welte78cae922018-03-01 10:12:56 +01001module HLR_Tests {
Harald Weltedf327232017-12-28 22:51:51 +01002
3import from GSUP_Types all;
Harald Welteed380d12018-06-14 13:42:11 +02004import from GSUP_Emulation all;
Harald Weltedf327232017-12-28 22:51:51 +01005import from IPA_Emulation all;
6
Harald Weltec2c52552018-03-01 21:20:39 +01007import from General_Types all;
8import from Osmocom_Types all;
Harald Welte39b82d32018-03-01 10:21:29 +01009import from Osmocom_CTRL_Adapter all;
10
Harald Welte4ea1f8a2018-06-12 09:26:10 +020011import from TCCEncoding_Functions all;
12import from SS_Types all;
13import from SS_Templates all;
14import from MAP_Errors all;
15import from USSD_Helpers all;
16
Harald Welte39b82d32018-03-01 10:21:29 +010017import from Osmocom_VTY_Functions all;
18import from TELNETasp_PortType all;
19
20type component test_CT extends CTRL_Adapter_CT {
Harald Weltedf327232017-12-28 22:51:51 +010021 var IPA_Emulation_CT vc_IPA;
22 var IPA_CCM_Parameters ccm_pars;
Harald Welteed380d12018-06-14 13:42:11 +020023 /* legacy tests without ConnHdlr */
Harald Weltedf327232017-12-28 22:51:51 +010024 port IPA_GSUP_PT GSUP;
Harald Welteed380d12018-06-14 13:42:11 +020025 /* new tests using ConnHdlr + GSUP_Emulation */
26 var GSUP_Emulation_CT vc_GSUP;
27 /* only to get events from IPA underneath GSUP */
28 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte39b82d32018-03-01 10:21:29 +010029
30 port TELNETasp_PT VTY;
Harald Weltec2c52552018-03-01 21:20:39 +010031
32 timer g_Tguard := 10.0;
Harald Weltedf327232017-12-28 22:51:51 +010033};
34
35modulepar {
36 charstring mp_hlr_ip := "127.0.0.1";
37 integer mp_hlr_gsup_port := 4222;
38 integer mp_hlr_ctrl_port := 4259;
39};
40
Harald Weltec2c52552018-03-01 21:20:39 +010041type record HlrSubscrAud2G {
42 charstring algo,
43 OCT16 ki
44}
45
46type record HlrSubscrAud3G {
47 charstring algo,
48 OCT16 k,
49 OCT16 op,
50 boolean op_is_opc
51}
52
53type record HlrSubscriber {
54 hexstring imsi,
55 hexstring msisdn,
56 HlrSubscrAud2G aud2g optional,
57 HlrSubscrAud3G aud3g optional
58}
59
60type record of HlrSubscriber HlrSubscriberList;
61
Harald Welteed380d12018-06-14 13:42:11 +020062type component HLR_ConnHdlr extends GSUP_ConnHdlr {
63 timer g_Tguard := 10.0;
64 var HLR_ConnHdlrPars g_pars;
65 port TELNETasp_PT VTY;
66}
67
68type record HLR_ConnHdlrPars {
Harald Welte4ea1f8a2018-06-12 09:26:10 +020069 HlrSubscriber sub,
70 HLR_ConnHdlrParsUssd ussd optional
71}
72
73type record HLR_ConnHdlrParsUssd {
74 OCT4 sid
Harald Welteed380d12018-06-14 13:42:11 +020075}
76
77template (value) HLR_ConnHdlrPars t_Pars(hexstring imsi, hexstring msisdn := ''H) := {
78 sub := {
79 imsi := imsi,
80 msisdn := msisdn,
81 aud2g := omit,
82 aud3g := omit
Harald Welte4ea1f8a2018-06-12 09:26:10 +020083 },
84 ussd := omit
Harald Welteed380d12018-06-14 13:42:11 +020085}
86
87template (value) HLR_ConnHdlrPars t_Pars_sub(HlrSubscriber sub) := {
Harald Welte4ea1f8a2018-06-12 09:26:10 +020088 sub := sub,
89 ussd := omit
Harald Welteed380d12018-06-14 13:42:11 +020090}
91
92type function void_fn() runs on HLR_ConnHdlr;
93
94/***********************************************************************
95 * Main Component
96 ***********************************************************************/
97
98function f_init_vty() runs on test_CT {
99 map(self:VTY, system:VTY);
100 f_vty_set_prompts(VTY);
101 f_vty_transceive(VTY, "enable");
102}
103
104private altstep as_Tguard() runs on test_CT {
105 [] g_Tguard.timeout {
106 setverdict(fail, "g_Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200107 mtc.stop;
Harald Welteed380d12018-06-14 13:42:11 +0200108 }
109}
110
111function f_init_gsup(charstring id, boolean legacy) runs on test_CT {
112 id := id & "-GSUP";
113 var GsupOps ops := {
114 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
115 }
116
117 ccm_pars := c_IPA_default_ccm_pars;
118 ccm_pars.name := "Osmocom TTCN-3 GSUP Simulator";
Harald Welte4a3242e2018-06-24 22:28:53 +0200119 ccm_pars.ser_nr := "MSC-00-00-00-00-00-00";
Harald Welteed380d12018-06-14 13:42:11 +0200120
121 vc_IPA := IPA_Emulation_CT.create(id & "-IPA");
122 log("legacy= ", legacy);
123 if (not legacy) {
124 log("in not legacy case 1");
125 vc_GSUP := GSUP_Emulation_CT.create(id);
126 }
127
128 map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
129 if (not legacy) {
130 log("in not legacy case 2");
131 connect(vc_GSUP:GSUP, vc_IPA:IPA_GSUP_PORT);
132 connect(vc_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
133 vc_GSUP.start(GSUP_Emulation.main(ops, id));
134 } else {
135 connect(vc_IPA:IPA_GSUP_PORT, self:GSUP);
136 }
137
138 vc_IPA.start(IPA_Emulation.main_client(mp_hlr_ip, mp_hlr_gsup_port, "", -1, ccm_pars));
139
140 /* wait for incoming connection to GSUP port before proceeding */
141 timer T := 10.0;
142 T.start;
143 alt {
144 [not legacy] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
145 [legacy] GSUP.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP}) { }
146 [] T.timeout {
147 setverdict(fail, "No connection to GSUP Port");
Daniel Willmannafce8662018-07-06 23:11:32 +0200148 mtc.stop;
Harald Welteed380d12018-06-14 13:42:11 +0200149 }
150 }
151}
152
153function f_init(boolean legacy := true) runs on test_CT {
154
155 /* activate default guard timer to ensure all tests eventually terminate */
156 g_Tguard.start;
157 activate(as_Tguard());
158
159 f_init_gsup("HLR_Test", legacy);
160 f_init_vty();
161
162 f_ipa_ctrl_start(mp_hlr_ip, mp_hlr_ctrl_port);
163}
164
165function f_start_handler(void_fn fn, HLR_ConnHdlrPars pars) runs on test_CT return HLR_ConnHdlr {
166 var HLR_ConnHdlr vc_conn;
167 var charstring id := testcasename();
168
169 vc_conn := HLR_ConnHdlr.create(id);
170 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
171 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
172
173 vc_conn.start(f_handler_init(fn, id, pars));
174 return vc_conn;
175}
176
177private function f_handler_init_vty() runs on HLR_ConnHdlr {
178 map(self:VTY, system:VTY);
179 f_vty_set_prompts(VTY);
180 f_vty_transceive(VTY, "enable");
181}
182
183/* first function inside ConnHdlr component; sets g_pars + starts function */
184function f_handler_init(void_fn fn, charstring id, template (omit) HLR_ConnHdlrPars pars := omit)
185runs on HLR_ConnHdlr
186{
187 if (isvalue(pars)) {
188 g_pars := valueof(pars);
189 f_create_gsup_expect(hex2str(g_pars.sub.imsi));
190 }
191 f_handler_init_vty();
192 fn.apply();
193}
194
195/***********************************************************************
196 * Subscriber creation via VTY
197 ***********************************************************************/
198
Harald Weltec2c52552018-03-01 21:20:39 +0100199template (value) HlrSubscriber t_SubNoAuth(hexstring imsi, hexstring msisdn) := {
200 imsi := imsi,
201 msisdn := msisdn,
202 aud2g := omit,
203 aud3g := omit
204}
205
206const OCT16 c_KI_DEFAULT := '000102030405060708090a0b0c0d0e0f'O;
207const OCT16 c_K_DEFAULT := '101112131415161718191a1b1c1d1e1f'O;
208const OCT16 c_OP_DEFAULT := '202122232425262728292a2b2c2d2e2f'O;
209//const OCT16 c_OPC_DEFAULT := '303132333435363738393a3b3c3d3f'O;
210
211template (value) HlrSubscriber t_Sub2G(hexstring imsi, hexstring msisdn, charstring algo) := {
212 imsi := imsi,
213 msisdn := msisdn,
214 aud2g := {
215 algo := algo,
216 ki := c_KI_DEFAULT
217 },
218 aud3g := omit
219}
220
221template (value) HlrSubscriber t_Sub3G(hexstring imsi, hexstring msisdn, charstring algo, boolean is_opc) := {
222 imsi := imsi,
223 msisdn := msisdn,
224 aud2g := omit,
225 aud3g := {
226 algo := algo,
227 k := c_K_DEFAULT,
228 op := c_OP_DEFAULT,
229 op_is_opc := is_opc
230 }
231}
232
233template (value) HlrSubscriber t_Sub2G3G(hexstring imsi, hexstring msisdn, charstring algo2g, charstring algo3g, boolean is_opc) := {
234 imsi := imsi,
235 msisdn := msisdn,
236 aud2g := {
237 algo := algo2g,
238 ki := c_KI_DEFAULT
239 },
240 aud3g := {
241 algo := algo3g,
242 k := c_K_DEFAULT,
243 op := c_OP_DEFAULT,
244 op_is_opc := is_opc
245 }
246}
247
248/* generate a variety of subscribers with different parameters */
249function f_gen_subs() runs on test_CT return HlrSubscriberList {
250 var HlrSubscriber sub;
251 var HlrSubscriberList sl := {};
252
253 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
254 sl := sl & { sub };
255
256 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v2"));
257 sl := sl & { sub };
258
259 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v3"));
260 sl := sl & { sub };
261
262 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", false));
263 sl := sl & { sub };
264
265 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", true));
266 sl := sl & { sub };
267
268 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
269 "comp128v1", "milenage", false));
270 sl := sl & { sub };
271
272 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
273 "comp128v2", "milenage", false));
274 sl := sl & { sub };
275
276 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
277 "comp128v3", "milenage", false));
278 sl := sl & { sub };
279
280 return sl;
281}
282
Harald Welteed380d12018-06-14 13:42:11 +0200283function f_vty_transceive_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
284 var charstring ret := f_vty_transceive_ret(pt, cmd);
285 if (not match(ret, exp_ret)) {
286 setverdict(fail, "Non-matching VTY response: ", ret);
Daniel Willmannafce8662018-07-06 23:11:32 +0200287 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100288 }
289}
290
Harald Welte70296062018-03-01 22:42:03 +0100291private template (value) charstring t_subscr_prefix(hexstring imsi) :=
292 "subscriber imsi " & hex2str(imsi) & " ";
293
Harald Weltec2c52552018-03-01 21:20:39 +0100294/* create a given subscriber using the VTY */
Harald Welteed380d12018-06-14 13:42:11 +0200295function f_vty_subscr_create(TELNETasp_PT VTY, HlrSubscriber sub) {
Harald Welte70296062018-03-01 22:42:03 +0100296 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100297 f_vty_transceive_match(VTY, prefix & "create", pattern "% Created subscriber *");
298 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(sub.msisdn),
299 pattern "% Updated subscriber *");
300 if (ispresent(sub.aud2g)) {
301 f_vty_transceive_match(VTY, prefix & "update aud2g " & sub.aud2g.algo &
302 " ki " & oct2str(sub.aud2g.ki),
303 pattern "");
304 } else {
305 f_vty_transceive_match(VTY, prefix & "update aud2g none", pattern "");
306 }
307
308 if (ispresent(sub.aud3g)) {
309 var charstring op_mode := "op";
310 if (sub.aud3g.op_is_opc) {
311 op_mode := "opc";
312 }
313 f_vty_transceive_match(VTY, prefix & "update aud3g " & sub.aud3g.algo &
314 " k " & oct2str(sub.aud3g.k) & " " & op_mode & " " &
315 oct2str(sub.aud3g.op), pattern "");
316 } else {
317 f_vty_transceive_match(VTY, prefix & "update aud3g none", pattern "");
318 }
319}
320
Harald Welteed380d12018-06-14 13:42:11 +0200321function f_vty_subscr_update_msisdn(TELNETasp_PT VTY, HlrSubscriber sub, hexstring new_msisdn) {
Harald Welte09b3c502018-03-01 22:42:22 +0100322 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
323 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(new_msisdn),
324 pattern "% Updated subscriber *");
325}
326
Harald Weltec2c52552018-03-01 21:20:39 +0100327/* perform 'delete' on subscriber */
Harald Welteed380d12018-06-14 13:42:11 +0200328function f_vty_subscr_delete(TELNETasp_PT VTY, HlrSubscriber sub) {
Harald Welte70296062018-03-01 22:42:03 +0100329 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100330 f_vty_transceive_match(VTY, prefix & "delete",
331 pattern "% Deleted subscriber for IMSI *");
332}
333
334/* perform 'show' on subscriber; match result with pattern 'exp' */
Harald Welteed380d12018-06-14 13:42:11 +0200335function f_vty_subscr_show(TELNETasp_PT VTY, HlrSubscriber sub, template charstring exp) {
Harald Welte70296062018-03-01 22:42:03 +0100336 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100337 f_vty_transceive_match(VTY, prefix & "show", exp);
338}
339
340
Harald Welteed380d12018-06-14 13:42:11 +0200341/***********************************************************************
342 * Helper functions for ConnHdlr
343 ***********************************************************************/
344
Harald Weltec2c52552018-03-01 21:20:39 +0100345/* perform SendAuthInfo for given imsi, return the GSUP response/error */
346function f_perform_SAI(hexstring imsi, template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200347runs on HLR_ConnHdlr return GSUP_PDU {
Harald Weltec2c52552018-03-01 21:20:39 +0100348 var GSUP_PDU ret;
349 timer T := 3.0;
350 var boolean exp_fail := false;
351 if (not istemplatekind(exp_err_cause, "omit")) {
352 exp_fail := true;
353 }
354
355 GSUP.send(valueof(ts_GSUP_SAI_REQ(imsi)));
356 T.start;
357 alt {
358 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, exp_err_cause)) -> value ret {
359 setverdict(pass);
360 }
361 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
362 setverdict(fail, "Unexpected SAI ERROR Cause");
363 }
364 [exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
365 setverdict(fail, "Unexpected SAI.res for unknown IMSI");
366 }
367 [not exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
368 setverdict(fail, "Unexpected SAI ERROR");
369 }
370 [not exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
371 setverdict(pass);
372 }
373 [] GSUP.receive { repeat; }
374 [] T.timeout {
375 setverdict(fail, "Timeout waiting for SAI response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200376 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100377 }
378 }
379 return ret;
380}
381
382function f_perform_UL(hexstring imsi, template hexstring msisdn,
383 template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200384runs on HLR_ConnHdlr return GSUP_PDU {
Harald Weltec2c52552018-03-01 21:20:39 +0100385 var GSUP_PDU ret;
386 timer T := 3.0;
387 var boolean exp_fail := false;
388 var boolean isd_done := false;
389 if (not istemplatekind(exp_err_cause, "omit")) {
390 exp_fail := true;
391 }
392
393 GSUP.send(valueof(ts_GSUP_UL_REQ(imsi)));
394 T.start;
395 alt {
396 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, exp_err_cause)) -> value ret {
397 setverdict(pass);
398 }
399 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
400 setverdict(fail, "Unexpected UL ERROR Cause");
401 }
402 [exp_fail] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
403 setverdict(fail, "Unexpected UL.res for unknown IMSI");
404 }
405 [exp_fail] GSUP.receive(tr_GSUP_ISD_REQ(imsi)) -> value ret {
406 setverdict(fail, "Unexpected ISD.req in error case");
407 }
408 [not exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
409 setverdict(fail, "Unexpected UL ERROR");
410 }
411 [not exp_fail and not isd_done] GSUP.receive(tr_GSUP_ISD_REQ(imsi, msisdn)) -> value ret {
412 GSUP.send(ts_GSUP_ISD_RES(imsi));
413 isd_done := true;
Harald Welte8f0c9332018-03-01 23:38:40 +0100414 repeat;
Harald Weltec2c52552018-03-01 21:20:39 +0100415 }
416 [not exp_fail and isd_done] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
417 setverdict(pass);
418 }
419 [] GSUP.receive { repeat; }
420 [] T.timeout {
421 setverdict(fail, "Timeout waiting for UL response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200422 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100423 }
424 }
425 return ret;
426}
427
Harald Welte958f8b42018-03-01 23:40:17 +0100428/* perform PurgeMS for given imsi, return the GSUP response/error */
429function f_perform_PURGE(hexstring imsi, GSUP_CnDomain cn_dom,
430 template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200431runs on HLR_ConnHdlr return GSUP_PDU {
Harald Welte958f8b42018-03-01 23:40:17 +0100432 var GSUP_PDU ret;
433 timer T := 3.0;
434 var boolean exp_fail := false;
435 if (not istemplatekind(exp_err_cause, "omit")) {
436 exp_fail := true;
437 }
438
439 GSUP.send(valueof(ts_GSUP_PURGE_MS_REQ(imsi, cn_dom)));
440 T.start;
441 alt {
442 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, exp_err_cause)) -> value ret {
443 setverdict(pass);
444 }
445 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
446 setverdict(fail, "Unexpected PURGE ERROR Cause");
447 }
448 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
449 setverdict(fail, "Unexpected PURGE.res for unknown IMSI");
450 }
451 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
452 setverdict(fail, "Unexpected PURGE ERROR");
453 }
454 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
455 setverdict(pass);
456 }
457 [] GSUP.receive { repeat; }
458 [] T.timeout {
459 setverdict(fail, "Timeout waiting for PURGE response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200460 mtc.stop;
Harald Welte958f8b42018-03-01 23:40:17 +0100461 }
462 }
463 return ret;
464}
465
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200466function f_SS_xceive(hexstring imsi, OCT4 sid, GSUP_SessionState state, octetstring ss,
467 template (omit) integer exp_err_cause := omit)
468runs on HLR_ConnHdlr return GSUP_PDU {
469 var GSUP_PDU ret;
470 timer T := 3.0;
471 var boolean exp_fail := false;
472 if (not istemplatekind(exp_err_cause, "omit")) {
473 exp_fail := true;
474 }
475
476 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(imsi, sid, state, ss)));
477 T.start;
478 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700479 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, exp_err_cause)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200480 setverdict(pass);
481 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700482 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200483 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
484 }
485 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
486 setverdict(fail, "Unexpected PROC_SS.res for unknown IMSI");
487 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700488 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200489 setverdict(fail, "Unexpected PROC_SS ERROR");
490 }
491 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
492 setverdict(pass);
493 }
494 [] GSUP.receive { repeat; }
495 [] T.timeout {
496 setverdict(fail, "Timeout waiting for PROC_SS response");
497 self.stop;
498 }
499 }
500 return ret;
501}
502
503private function f_SS_expect(hexstring imsi, OCT4 sid, GSUP_SessionState state,
504 template SS_FacilityInformation facility := *)
505runs on HLR_ConnHdlr return GSUP_PDU {
506 var GSUP_PDU ret;
507 timer T := 3.0;
508 var boolean exp_ss := true;
509 if (istemplatekind(facility, "omit")) {
510 exp_ss := false;
511 }
512 T.start;
513 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700514 [] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200515 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
516 }
517 [not exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
518 setverdict(pass);
519 }
520 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
521 setverdict(fail, "Unexpected PROC_SS.res without SS IE");
522 }
523/*
524 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, decmatch facility)) -> value ret {
525 setverdict(pass);
526 }
527*/
528
529 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, ?)) -> value ret {
530 var GSUP_IeValue ss_ie;
531 f_gsup_find_ie(ret, OSMO_GSUP_SS_INFO_IE, ss_ie);
532 var SS_FacilityInformation dec_fac := dec_SS_FacilityInformation(ss_ie.ss_info);
533 log("pattern: ", facility);
534 if (match(dec_fac, facility)) {
535 setverdict(pass);
536 } else {
537 setverdict(fail, "Unexpected PROC_SS.res with non-matching facility IE");
538 }
539 }
540 [] GSUP.receive { repeat; }
541 [] T.timeout {
542 setverdict(fail, "Timeout waiting for PROC_SS response");
543 self.stop;
544 }
545 }
546
547 return ret;
548}
549
550
Harald Welte958f8b42018-03-01 23:40:17 +0100551
Harald Welteed380d12018-06-14 13:42:11 +0200552/***********************************************************************
553 * Testcases
554 ***********************************************************************/
555
556/* 23.003 Section 2.2 clearly states that an IMSI with less
557 * than 5 digits is impossible. Even 5 digits is still questionable */
558private function f_TC_gsup_sai_err_invalid_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100559 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200560 res := f_perform_SAI(g_pars.sub.imsi, 96); /* Invalid Mandatory information */
561 setverdict(pass);
562}
563testcase TC_gsup_sai_err_invalid_imsi() runs on test_CT {
564 var HLR_ConnHdlr vc_conn;
565 var HLR_ConnHdlrPars pars := valueof(t_Pars('0123'H));
566 f_init(false);
567 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_invalid_imsi), pars);
568 vc_conn.done;
569}
Harald Weltec2c52552018-03-01 21:20:39 +0100570
Harald Weltec2c52552018-03-01 21:20:39 +0100571
Harald Welteed380d12018-06-14 13:42:11 +0200572private function f_TC_gsup_sai_err_unknown_imsi() runs on HLR_ConnHdlr {
573 var GSUP_PDU res;
574 res := f_perform_SAI(g_pars.sub.imsi, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100575 setverdict(pass);
576}
577
Harald Welte3f662762018-03-02 10:48:20 +0100578testcase TC_gsup_sai_err_unknown_imsi() runs on test_CT {
Harald Welteed380d12018-06-14 13:42:11 +0200579 var HLR_ConnHdlr vc_conn;
580 var HLR_ConnHdlrPars pars := valueof(t_Pars(f_rnd_imsi('26242'H)));
581 f_init(false);
582 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_unknown_imsi), pars);
583 vc_conn.done;
Harald Welte3f662762018-03-02 10:48:20 +0100584}
585
Harald Welteed380d12018-06-14 13:42:11 +0200586function f_start_handler_per_sub(void_fn fn, HlrSubscriberList sl) runs on test_CT {
587 for (var integer i := 0; i < sizeof(sl); i := i+1) {
588 var HlrSubscriber sub := sl[i];
589 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sub));
590 var HLR_ConnHdlr vc_conn;
591
592 f_vty_subscr_create(VTY, sub);
593 vc_conn := f_start_handler(fn, pars);
594 vc_conn.done;
595 f_vty_subscr_delete(VTY, sub);
596 }
597}
Harald Welte3f662762018-03-02 10:48:20 +0100598
Harald Weltec2c52552018-03-01 21:20:39 +0100599/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
Harald Welteed380d12018-06-14 13:42:11 +0200600private function f_TC_gsup_sai() runs on HLR_ConnHdlr {
601 var GSUP_PDU res;
602 res := f_perform_SAI(g_pars.sub.imsi);
603 /* TODO: match if tuple[s] matches expectation */
604 setverdict(pass);
605}
Harald Weltec2c52552018-03-01 21:20:39 +0100606testcase TC_gsup_sai() runs on test_CT {
607 var HlrSubscriberList sl;
608 var GSUP_PDU res;
609
Harald Welteed380d12018-06-14 13:42:11 +0200610 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100611
612 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200613 f_start_handler_per_sub(refers(f_TC_gsup_sai), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100614
615 setverdict(pass);
616}
617
618/* test UL for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200619private function f_TC_ul_unknown_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100620 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200621 res := f_perform_UL(g_pars.sub.imsi, ?, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100622 setverdict(pass);
623}
Harald Welteed380d12018-06-14 13:42:11 +0200624testcase TC_gsup_ul_unknown_imsi() runs on test_CT {
625 var hexstring imsi := f_rnd_imsi('26242'H);
626 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
627 var HLR_ConnHdlr vc_conn;
Harald Weltec2c52552018-03-01 21:20:39 +0100628
Harald Welteed380d12018-06-14 13:42:11 +0200629 f_init(false);
630 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
631 vc_conn.done;
632}
633
634/* test UL for a number of different subscriber cases (algo, 2g/3g, ...) */
635private function f_TC_gsup_ul() runs on HLR_ConnHdlr {
636 var GSUP_PDU res;
637 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
638 setverdict(pass);
639}
Harald Weltec2c52552018-03-01 21:20:39 +0100640testcase TC_gsup_ul() runs on test_CT {
641 var HlrSubscriberList sl;
642 var GSUP_PDU res;
643
Harald Welteed380d12018-06-14 13:42:11 +0200644 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100645 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200646 f_start_handler_per_sub(refers(f_TC_gsup_ul), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100647
648 setverdict(pass);
649}
650
651/* Test only the VTY commands */
652testcase TC_vty() runs on test_CT {
653 var HlrSubscriber sub;
654
655 f_init();
656
657 /* we're not using f_gen_subs() here as the expect pattern for the 'show' are different
658 * from case to case */
659 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
Harald Welteed380d12018-06-14 13:42:11 +0200660 f_vty_subscr_create(VTY, sub);
661 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*");
662 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100663
664 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
665 "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +0200666 f_vty_subscr_create(VTY, sub);
667 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *3G auth: MILENAGE*");
668 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100669
670 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
671 "comp128v1", "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +0200672 f_vty_subscr_create(VTY, sub);
673 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*3G auth: MILENAGE*");
674 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100675
676 setverdict(pass);
677}
678
Harald Welte09b3c502018-03-01 22:42:22 +0100679/* VTY changes to MSISDN should result in ISD to current VLR */
Harald Welteed380d12018-06-14 13:42:11 +0200680private function f_TC_vty_msisdn_isd() runs on HLR_ConnHdlr {
Harald Welte09b3c502018-03-01 22:42:22 +0100681 var hexstring new_msisdn;
682 var GSUP_PDU res;
683 timer T := 5.0;
684
Harald Welte09b3c502018-03-01 22:42:22 +0100685 /* Create Subscriber */
Harald Welteed380d12018-06-14 13:42:11 +0200686 f_vty_subscr_create(VTY, g_pars.sub);
Harald Welte09b3c502018-03-01 22:42:22 +0100687
688 /* Perform UpdateLocation (VLR now known to HLR) */
Harald Welteed380d12018-06-14 13:42:11 +0200689 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +0100690
691 /* Then change IMSI via VTY */
692 new_msisdn := '49161'H & f_rnd_hexstring(7, 9);
Harald Welteed380d12018-06-14 13:42:11 +0200693 f_vty_subscr_update_msisdn(VTY, g_pars.sub, new_msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +0100694 /* And expect InsertSubscriberData as result */
695 T.start;
696 alt {
Harald Welteed380d12018-06-14 13:42:11 +0200697 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, new_msisdn)) {
698 GSUP.send(ts_GSUP_ISD_RES(g_pars.sub.imsi));
699 g_pars.sub.msisdn := new_msisdn;
Harald Welte09b3c502018-03-01 22:42:22 +0100700 setverdict(pass);
701 }
Harald Welteed380d12018-06-14 13:42:11 +0200702 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, g_pars.sub.msisdn)) {
Stefan Sperling7c096872018-04-09 11:24:22 +0200703 log("received ISD req with old MSISDN");
704 setverdict(fail);
705 }
Harald Welte09b3c502018-03-01 22:42:22 +0100706 [] GSUP.receive { repeat; }
707 [] T.timeout {
708 setverdict(fail, "Timeout waiting for ISD.req");
709 }
710 }
711}
Harald Welteed380d12018-06-14 13:42:11 +0200712testcase TC_vty_msisdn_isd() runs on test_CT {
713 var HlrSubscriber sub;
714 var HLR_ConnHdlr vc_conn;
715
716 f_init(false);
717
718 /* Create Subscriber */
719 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
720
721 vc_conn := f_start_handler(refers(f_TC_vty_msisdn_isd), valueof(t_Pars_sub(sub)));
722 vc_conn.done;
723}
Harald Welte09b3c502018-03-01 22:42:22 +0100724
Harald Welte958f8b42018-03-01 23:40:17 +0100725/* Test PURGE MS for CS services */
Harald Welteed380d12018-06-14 13:42:11 +0200726private function f_TC_gsup_purge_cs() runs on HLR_ConnHdlr {
727 var GSUP_PDU res;
728 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
729 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS);
730}
Harald Welte958f8b42018-03-01 23:40:17 +0100731testcase TC_gsup_purge_cs() runs on test_CT {
732 var HlrSubscriberList sl;
733 var GSUP_PDU res;
734
Harald Welteed380d12018-06-14 13:42:11 +0200735 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +0100736 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200737 f_start_handler_per_sub(refers(f_TC_gsup_purge_cs), sl);
Harald Welte958f8b42018-03-01 23:40:17 +0100738
739 setverdict(pass);
740}
741
742/* Test PURGE MS for PS services */
Harald Welteed380d12018-06-14 13:42:11 +0200743private function f_TC_gsup_purge_ps() runs on HLR_ConnHdlr {
744 var GSUP_PDU res;
745 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
746 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_PS);
747}
Harald Welte958f8b42018-03-01 23:40:17 +0100748testcase TC_gsup_purge_ps() runs on test_CT {
749 var HlrSubscriberList sl;
Harald Welte958f8b42018-03-01 23:40:17 +0100750
Harald Welteed380d12018-06-14 13:42:11 +0200751 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +0100752 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200753 f_start_handler_per_sub(refers(f_TC_gsup_purge_ps), sl);
Harald Welte958f8b42018-03-01 23:40:17 +0100754
755 setverdict(pass);
756}
757
758/* Test PURGEG MS procedure for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200759
760private function f_TC_gsup_purge_unknown() runs on HLR_ConnHdlr {
761 var GSUP_PDU res;
762 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS, 2);
763}
Harald Welte958f8b42018-03-01 23:40:17 +0100764testcase TC_gsup_purge_unknown() runs on test_CT {
765 var hexstring imsi := '2345743413463'H;
Harald Welteed380d12018-06-14 13:42:11 +0200766 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
767 var HLR_ConnHdlr vc_conn;
Harald Welte958f8b42018-03-01 23:40:17 +0100768
Harald Welteed380d12018-06-14 13:42:11 +0200769 f_init(false);
770 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
771 vc_conn.done;
Harald Welte958f8b42018-03-01 23:40:17 +0100772
773 setverdict(pass);
774}
775
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200776import from HLR_EUSE all;
777
778/* Test for USSD request to undefined/unrouted short-code. Expect ss-NotAvailable(18) */
779private function f_TC_mo_ussd_unknown() runs on HLR_ConnHdlr {
780 var GSUP_PDU res;
781 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
782 op_code := SS_OP_CODE_PROCESS_USS_REQ,
783 ussd_string := "*#200#");
784 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
785 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
786 f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid, OSMO_GSUP_SESSION_STATE_END,
787 tr_SS_FACILITY_RETURN_ERROR(1, 18));
788}
789testcase TC_mo_ussd_unknown() runs on test_CT {
790 var HlrSubscriberList sl;
791 var HLR_ConnHdlr vc_conn;
792
793 f_init(false);
794 sl := f_gen_subs();
795 for (var integer i := 0; i < sizeof(sl); i := i+1) {
796 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
797 pars.ussd.sid := f_rnd_octstring(4);
798 f_vty_subscr_create(VTY, pars.sub);
799 vc_conn := f_start_handler(refers(f_TC_mo_ussd_unknown), pars);
800 vc_conn.done;
801 }
802}
803
804/* Test for USSD request to currently disconnected EUSE. Expect ss-SystemFailure(34) */
805private function f_TC_mo_ussd_euse_disc() runs on HLR_ConnHdlr {
806 var GSUP_PDU res;
807 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
808 op_code := SS_OP_CODE_PROCESS_USS_REQ,
809 ussd_string := "*100#");
810 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
811 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
812 f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid, OSMO_GSUP_SESSION_STATE_END,
813 tr_SS_FACILITY_RETURN_ERROR(1, 34));
814}
815testcase TC_mo_ussd_euse_disc() runs on test_CT {
816 var HlrSubscriberList sl;
817 var HLR_ConnHdlr vc_conn;
818
819 f_init(false);
820 sl := f_gen_subs();
821 for (var integer i := 0; i < sizeof(sl); i := i+1) {
822 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
823 pars.ussd.sid := f_rnd_octstring(4);
824 f_vty_subscr_create(VTY, pars.sub);
825 vc_conn := f_start_handler(refers(f_TC_mo_ussd_euse_disc), pars);
826 vc_conn.done;
827 }
828}
829
830/* Test for USSD request to internal own-imsi IUSE. */
831private function f_TC_mo_ussd_iuse_imsi() runs on HLR_ConnHdlr {
832 var GSUP_PDU res;
833 var charstring resp_str;
834 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
835 op_code := SS_OP_CODE_PROCESS_USS_REQ,
836 ussd_string := "*#101#");
837 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
838 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
839 resp_str := "Your IMSI is " & hex2str(g_pars.sub.imsi);
840 f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid, OSMO_GSUP_SESSION_STATE_END,
841 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS, f_encGSM7bit(resp_str)));
842}
843testcase TC_mo_ussd_iuse_imsi() runs on test_CT {
844 var HlrSubscriberList sl;
845 var HLR_ConnHdlr vc_conn;
846
847 f_init(false);
848 sl := f_gen_subs();
849 for (var integer i := 0; i < sizeof(sl); i := i+1) {
850 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
851 pars.ussd.sid := f_rnd_octstring(4);
852 f_vty_subscr_create(VTY, pars.sub);
853 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_imsi), pars);
854 vc_conn.done;
855 }
856}
857
858/* Test for USSD request to internal own-msisdn IUSE. */
859private function f_TC_mo_ussd_iuse_msisdn() runs on HLR_ConnHdlr {
860 var GSUP_PDU res;
861 var charstring resp_str;
862 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
863 op_code := SS_OP_CODE_PROCESS_USS_REQ,
864 ussd_string := "*#100#");
865 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
866 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
867 resp_str := "Your extension is " & hex2str(g_pars.sub.msisdn);
868 f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid, OSMO_GSUP_SESSION_STATE_END,
869 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS, f_encGSM7bit(resp_str)));
870}
871testcase TC_mo_ussd_iuse_msisdn() runs on test_CT {
872 var HlrSubscriberList sl;
873 var HLR_ConnHdlr vc_conn;
874
875 f_init(false);
876 sl := f_gen_subs();
877 for (var integer i := 0; i < sizeof(sl); i := i+1) {
878 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
879 pars.ussd.sid := f_rnd_octstring(4);
880 f_vty_subscr_create(VTY, pars.sub);
881 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_msisdn), pars);
882 vc_conn.done;
883 }
884}
885
886/* Test routing of USSD to EUSE by a specific route */
887private function f_TC_mo_ussd_100() runs on HLR_ConnHdlr {
888 var GSUP_PDU res;
889 /* invoke / invoke id 1 / processUSS-req */
890 //var octetstring ss := 'a11202010102013b300a04010f0405aa180c3602'O;
891 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
892 op_code := SS_OP_CODE_PROCESS_USS_REQ,
893 ussd_string := "*100#");
894 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
895 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
896 f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid, OSMO_GSUP_SESSION_STATE_END,
897 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS, f_encGSM7bit("*100#")));
898}
899testcase TC_mo_ussd_euse() runs on test_CT {
900 var HlrSubscriberList sl;
901 var HLR_ConnHdlr vc_conn;
902
903 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
904 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
905
906 f_init(false);
907 sl := f_gen_subs();
908 for (var integer i := 0; i < sizeof(sl); i := i+1) {
909 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
910 pars.ussd.sid := f_rnd_octstring(4);
911 f_vty_subscr_create(VTY, pars.sub);
912 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100), pars);
913 vc_conn.done;
914 }
915
916 vc_EUSE.stop;
917}
918
919/* Test routing of USSD to EUSE by a specific route, with CONTINUE */
920private function f_TC_mo_ussd_100_continue() runs on HLR_ConnHdlr {
921 var GSUP_PDU res;
922 /* Simulate BEGIN from MS/MSC */
923 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
924 ussd_string := "*100#");
925 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
926 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
927 /* expect echo response from EUSE */
928 f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid, OSMO_GSUP_SESSION_STATE_CONTINUE,
929 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS, f_encGSM7bit("*100#")));
930
931 /* Simulate CONTINUE from MS/MSC */
932 ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
933 ussd_string := "mahlzeit");
934 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
935 OSMO_GSUP_SESSION_STATE_CONTINUE, ss)));
936
937 /* expect echo response from EUSE */
938 f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid, OSMO_GSUP_SESSION_STATE_END,
939 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
940 f_encGSM7bit("mahlzeit")));
941}
942testcase TC_mo_ussd_euse_continue() runs on test_CT {
943 var HlrSubscriberList sl;
944 var HLR_ConnHdlr vc_conn;
945
946 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
947 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar",
948 refers(f_ss_echo_continue)));
949
950 f_init(false);
951 sl := f_gen_subs();
952 for (var integer i := 0; i < sizeof(sl); i := i+1) {
953 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
954 pars.ussd.sid := f_rnd_octstring(4);
955 f_vty_subscr_create(VTY, pars.sub);
956 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100_continue), pars);
957 vc_conn.done;
958 }
959
960 vc_EUSE.stop;
961}
962
963
964/* Test routing of USSD to EUSE by default-route */
965private function f_TC_mo_ussd_999() runs on HLR_ConnHdlr {
966 var GSUP_PDU res;
967 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
968 op_code := SS_OP_CODE_PROCESS_USS_REQ,
969 ussd_string := "*999#");
970 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
971 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
972 f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid, OSMO_GSUP_SESSION_STATE_END,
973 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS, f_encGSM7bit("*999#")));
974}
975testcase TC_mo_ussd_euse_defaultroute() runs on test_CT {
976 var HlrSubscriberList sl;
977 var HLR_ConnHdlr vc_conn;
978
979 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
980 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
981
982 f_init(false);
983 f_vty_config(VTY, "hlr", "ussd default-route external foobar");
984
985 sl := f_gen_subs();
986 for (var integer i := 0; i < sizeof(sl); i := i+1) {
987 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
988 pars.ussd.sid := f_rnd_octstring(4);
989 f_vty_subscr_create(VTY, pars.sub);
990 vc_conn := f_start_handler(refers(f_TC_mo_ussd_999), pars);
991 vc_conn.done;
992 }
993
994 f_vty_config(VTY, "hlr", "no ussd default-route");
995 vc_EUSE.stop;
996}
997
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +0700998/**
999 * Test "Structured" Supplementary Services
1000 *
1001 * NOTE: at the moment, OsmoHLR doesn't support "structured" SS,
1002 * so such requests are being rejected (actually ReturnError
1003 * with GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED).
1004 */
1005private function f_TC_mo_sss_reject() runs on HLR_ConnHdlr {
1006 var SS_FacilityInformation ss_req;
1007
1008 /* Prepare '*#21#' SS request */
1009 ss_req := valueof(ts_SS_FACILITY_INVOKE(
1010 invoke_id := 0,
1011 op_code := SS_OP_CODE_INTERROGATE_SS,
1012 ss_code := '21'O));
1013
1014 /* Send it towards HLR */
1015 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(
1016 g_pars.sub.imsi,
1017 g_pars.ussd.sid,
1018 OSMO_GSUP_SESSION_STATE_BEGIN,
1019 enc_SS_FacilityInformation(ss_req))));
1020
1021 /* Expect ReturnError with FACILITY_NOT_SUPPORTED */
1022 f_SS_expect(g_pars.sub.imsi,
1023 g_pars.ussd.sid, OSMO_GSUP_SESSION_STATE_END,
1024 tr_SS_FACILITY_RETURN_ERROR(0, 21));
1025}
1026testcase TC_mo_sss_reject() runs on test_CT {
1027 var HLR_ConnHdlrPars pars;
1028 var HLR_ConnHdlr vc_conn;
1029 var HlrSubscriber sub;
1030
1031 f_init(false);
1032
1033 /* Create a random subscriber */
1034 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H),
1035 '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
1036 pars := valueof(t_Pars_sub(sub));
1037 pars.ussd.sid := f_rnd_octstring(4);
1038
1039 f_vty_subscr_create(VTY, sub);
1040 vc_conn := f_start_handler(refers(f_TC_mo_sss_reject), pars);
1041 vc_conn.done;
1042 f_vty_subscr_delete(VTY, sub);
1043}
1044
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001045
1046/* TODO USSD:
1047 * MO USSD for IMSI of non-existant subscriber
1048 * MT USSD from EUSE
1049 * timeout cases
1050 */
1051
Harald Weltec2c52552018-03-01 21:20:39 +01001052/* TODO:
1053 * UL with ISD error
1054 * UL with ISD timeout
Harald Weltec2c52552018-03-01 21:20:39 +01001055 * LOCATION CANCEL
1056 * AUTH FAIL REP
1057 * DELETE DATA after hlr_subscr_nam() change
1058 * correctness
1059 ** wrong message type
1060 ** wrong length of PDU
1061 ** too short message
1062 ** missing IMSI IE
1063
1064 */
1065
Harald Weltedf327232017-12-28 22:51:51 +01001066control {
1067 execute( TC_gsup_sai_err_invalid_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001068 execute( TC_gsup_sai() );
1069 execute( TC_gsup_ul_unknown_imsi() );
Harald Welte3f662762018-03-02 10:48:20 +01001070 execute( TC_gsup_sai_err_unknown_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001071 execute( TC_gsup_ul() );
1072 execute( TC_vty() );
Harald Welte09b3c502018-03-01 22:42:22 +01001073 execute( TC_vty_msisdn_isd() );
Harald Welte958f8b42018-03-01 23:40:17 +01001074 execute( TC_gsup_purge_cs() );
1075 execute( TC_gsup_purge_ps() );
1076 execute( TC_gsup_purge_unknown() );
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001077
1078 execute( TC_mo_ussd_unknown() );
1079 execute( TC_mo_ussd_euse_disc() );
1080 execute( TC_mo_ussd_iuse_imsi() );
1081 execute( TC_mo_ussd_iuse_msisdn() );
1082 execute( TC_mo_ussd_euse() );
1083 execute( TC_mo_ussd_euse_continue() );
1084 execute( TC_mo_ussd_euse_defaultroute() );
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001085
1086 /* "Structured" Supplementary Services */
1087 execute( TC_mo_sss_reject() );
Harald Weltedf327232017-12-28 22:51:51 +01001088};
1089
1090};