blob: f8d7483ca22decf1fc2a1ac4bfa3a7239b92378a [file] [log] [blame]
Harald Welte78cae922018-03-01 10:12:56 +01001module HLR_Tests {
Harald Weltedf327232017-12-28 22:51:51 +01002
Harald Welte34b5a952019-05-27 11:54:11 +02003/* HLR test suite in TTCN-3
4 * (C) 2017-2018 Harald Welte <laforge@gnumonks.org>
5 * (C) 2018 sysmocom - s.f.m.c. GmbH
6 * (C) 2018 Vadim Yanitskiy <axilirator@gmail.com>
7 * All rights reserved.
8 *
9 * Released under the terms of GNU General Public License, Version 2 or
10 * (at your option) any later version.
11 *
12 * SPDX-License-Identifier: GPL-2.0-or-later
13 */
14
15
16
Harald Weltedf327232017-12-28 22:51:51 +010017import from GSUP_Types all;
Harald Welteed380d12018-06-14 13:42:11 +020018import from GSUP_Emulation all;
Harald Weltedf327232017-12-28 22:51:51 +010019import from IPA_Emulation all;
20
Harald Weltec2c52552018-03-01 21:20:39 +010021import from General_Types all;
22import from Osmocom_Types all;
Harald Welte39b82d32018-03-01 10:21:29 +010023import from Osmocom_CTRL_Adapter all;
24
Harald Welte4ea1f8a2018-06-12 09:26:10 +020025import from TCCEncoding_Functions all;
26import from SS_Types all;
27import from SS_Templates all;
28import from MAP_Errors all;
29import from USSD_Helpers all;
30
Harald Welte39b82d32018-03-01 10:21:29 +010031import from Osmocom_VTY_Functions all;
32import from TELNETasp_PortType all;
33
34type component test_CT extends CTRL_Adapter_CT {
Harald Weltedf327232017-12-28 22:51:51 +010035 var IPA_Emulation_CT vc_IPA;
36 var IPA_CCM_Parameters ccm_pars;
Harald Welteed380d12018-06-14 13:42:11 +020037 /* legacy tests without ConnHdlr */
Harald Weltedf327232017-12-28 22:51:51 +010038 port IPA_GSUP_PT GSUP;
Harald Welteed380d12018-06-14 13:42:11 +020039 /* new tests using ConnHdlr + GSUP_Emulation */
40 var GSUP_Emulation_CT vc_GSUP;
41 /* only to get events from IPA underneath GSUP */
42 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte39b82d32018-03-01 10:21:29 +010043
44 port TELNETasp_PT VTY;
Harald Weltec2c52552018-03-01 21:20:39 +010045
46 timer g_Tguard := 10.0;
Harald Weltedf327232017-12-28 22:51:51 +010047};
48
49modulepar {
50 charstring mp_hlr_ip := "127.0.0.1";
51 integer mp_hlr_gsup_port := 4222;
52 integer mp_hlr_ctrl_port := 4259;
53};
54
Harald Weltec2c52552018-03-01 21:20:39 +010055type record HlrSubscrAud2G {
56 charstring algo,
57 OCT16 ki
58}
59
60type record HlrSubscrAud3G {
61 charstring algo,
62 OCT16 k,
63 OCT16 op,
64 boolean op_is_opc
65}
66
67type record HlrSubscriber {
68 hexstring imsi,
69 hexstring msisdn,
70 HlrSubscrAud2G aud2g optional,
71 HlrSubscrAud3G aud3g optional
72}
73
74type record of HlrSubscriber HlrSubscriberList;
75
Harald Welteed380d12018-06-14 13:42:11 +020076type component HLR_ConnHdlr extends GSUP_ConnHdlr {
77 timer g_Tguard := 10.0;
78 var HLR_ConnHdlrPars g_pars;
79 port TELNETasp_PT VTY;
80}
81
82type record HLR_ConnHdlrPars {
Harald Welte4ea1f8a2018-06-12 09:26:10 +020083 HlrSubscriber sub,
84 HLR_ConnHdlrParsUssd ussd optional
85}
86
87type record HLR_ConnHdlrParsUssd {
88 OCT4 sid
Harald Welteed380d12018-06-14 13:42:11 +020089}
90
91template (value) HLR_ConnHdlrPars t_Pars(hexstring imsi, hexstring msisdn := ''H) := {
92 sub := {
93 imsi := imsi,
94 msisdn := msisdn,
95 aud2g := omit,
96 aud3g := omit
Harald Welte4ea1f8a2018-06-12 09:26:10 +020097 },
98 ussd := omit
Harald Welteed380d12018-06-14 13:42:11 +020099}
100
101template (value) HLR_ConnHdlrPars t_Pars_sub(HlrSubscriber sub) := {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200102 sub := sub,
103 ussd := omit
Harald Welteed380d12018-06-14 13:42:11 +0200104}
105
106type function void_fn() runs on HLR_ConnHdlr;
107
108/***********************************************************************
109 * Main Component
110 ***********************************************************************/
111
112function f_init_vty() runs on test_CT {
113 map(self:VTY, system:VTY);
114 f_vty_set_prompts(VTY);
115 f_vty_transceive(VTY, "enable");
116}
117
118private altstep as_Tguard() runs on test_CT {
119 [] g_Tguard.timeout {
120 setverdict(fail, "g_Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200121 mtc.stop;
Harald Welteed380d12018-06-14 13:42:11 +0200122 }
123}
124
125function f_init_gsup(charstring id, boolean legacy) runs on test_CT {
126 id := id & "-GSUP";
127 var GsupOps ops := {
128 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
129 }
130
131 ccm_pars := c_IPA_default_ccm_pars;
132 ccm_pars.name := "Osmocom TTCN-3 GSUP Simulator";
Harald Welte4a3242e2018-06-24 22:28:53 +0200133 ccm_pars.ser_nr := "MSC-00-00-00-00-00-00";
Harald Welteed380d12018-06-14 13:42:11 +0200134
135 vc_IPA := IPA_Emulation_CT.create(id & "-IPA");
136 log("legacy= ", legacy);
137 if (not legacy) {
138 log("in not legacy case 1");
139 vc_GSUP := GSUP_Emulation_CT.create(id);
140 }
141
142 map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
143 if (not legacy) {
144 log("in not legacy case 2");
145 connect(vc_GSUP:GSUP, vc_IPA:IPA_GSUP_PORT);
146 connect(vc_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
147 vc_GSUP.start(GSUP_Emulation.main(ops, id));
148 } else {
149 connect(vc_IPA:IPA_GSUP_PORT, self:GSUP);
150 }
151
152 vc_IPA.start(IPA_Emulation.main_client(mp_hlr_ip, mp_hlr_gsup_port, "", -1, ccm_pars));
153
154 /* wait for incoming connection to GSUP port before proceeding */
155 timer T := 10.0;
156 T.start;
157 alt {
158 [not legacy] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
159 [legacy] GSUP.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP}) { }
160 [] T.timeout {
161 setverdict(fail, "No connection to GSUP Port");
Daniel Willmannafce8662018-07-06 23:11:32 +0200162 mtc.stop;
Harald Welteed380d12018-06-14 13:42:11 +0200163 }
164 }
165}
166
167function f_init(boolean legacy := true) runs on test_CT {
168
169 /* activate default guard timer to ensure all tests eventually terminate */
170 g_Tguard.start;
171 activate(as_Tguard());
172
173 f_init_gsup("HLR_Test", legacy);
174 f_init_vty();
175
176 f_ipa_ctrl_start(mp_hlr_ip, mp_hlr_ctrl_port);
177}
178
179function f_start_handler(void_fn fn, HLR_ConnHdlrPars pars) runs on test_CT return HLR_ConnHdlr {
180 var HLR_ConnHdlr vc_conn;
181 var charstring id := testcasename();
182
183 vc_conn := HLR_ConnHdlr.create(id);
184 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
185 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
186
187 vc_conn.start(f_handler_init(fn, id, pars));
188 return vc_conn;
189}
190
191private function f_handler_init_vty() runs on HLR_ConnHdlr {
192 map(self:VTY, system:VTY);
193 f_vty_set_prompts(VTY);
194 f_vty_transceive(VTY, "enable");
195}
196
197/* first function inside ConnHdlr component; sets g_pars + starts function */
198function f_handler_init(void_fn fn, charstring id, template (omit) HLR_ConnHdlrPars pars := omit)
199runs on HLR_ConnHdlr
200{
201 if (isvalue(pars)) {
202 g_pars := valueof(pars);
203 f_create_gsup_expect(hex2str(g_pars.sub.imsi));
204 }
205 f_handler_init_vty();
206 fn.apply();
207}
208
209/***********************************************************************
210 * Subscriber creation via VTY
211 ***********************************************************************/
212
Harald Weltec2c52552018-03-01 21:20:39 +0100213template (value) HlrSubscriber t_SubNoAuth(hexstring imsi, hexstring msisdn) := {
214 imsi := imsi,
215 msisdn := msisdn,
216 aud2g := omit,
217 aud3g := omit
218}
219
220const OCT16 c_KI_DEFAULT := '000102030405060708090a0b0c0d0e0f'O;
221const OCT16 c_K_DEFAULT := '101112131415161718191a1b1c1d1e1f'O;
222const OCT16 c_OP_DEFAULT := '202122232425262728292a2b2c2d2e2f'O;
223//const OCT16 c_OPC_DEFAULT := '303132333435363738393a3b3c3d3f'O;
224
225template (value) HlrSubscriber t_Sub2G(hexstring imsi, hexstring msisdn, charstring algo) := {
226 imsi := imsi,
227 msisdn := msisdn,
228 aud2g := {
229 algo := algo,
230 ki := c_KI_DEFAULT
231 },
232 aud3g := omit
233}
234
235template (value) HlrSubscriber t_Sub3G(hexstring imsi, hexstring msisdn, charstring algo, boolean is_opc) := {
236 imsi := imsi,
237 msisdn := msisdn,
238 aud2g := omit,
239 aud3g := {
240 algo := algo,
241 k := c_K_DEFAULT,
242 op := c_OP_DEFAULT,
243 op_is_opc := is_opc
244 }
245}
246
247template (value) HlrSubscriber t_Sub2G3G(hexstring imsi, hexstring msisdn, charstring algo2g, charstring algo3g, boolean is_opc) := {
248 imsi := imsi,
249 msisdn := msisdn,
250 aud2g := {
251 algo := algo2g,
252 ki := c_KI_DEFAULT
253 },
254 aud3g := {
255 algo := algo3g,
256 k := c_K_DEFAULT,
257 op := c_OP_DEFAULT,
258 op_is_opc := is_opc
259 }
260}
261
262/* generate a variety of subscribers with different parameters */
263function f_gen_subs() runs on test_CT return HlrSubscriberList {
264 var HlrSubscriber sub;
265 var HlrSubscriberList sl := {};
266
267 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
268 sl := sl & { sub };
269
270 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v2"));
271 sl := sl & { sub };
272
273 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v3"));
274 sl := sl & { sub };
275
276 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", false));
277 sl := sl & { sub };
278
279 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", true));
280 sl := sl & { sub };
281
282 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
283 "comp128v1", "milenage", false));
284 sl := sl & { sub };
285
286 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
287 "comp128v2", "milenage", false));
288 sl := sl & { sub };
289
290 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
291 "comp128v3", "milenage", false));
292 sl := sl & { sub };
293
294 return sl;
295}
296
Harald Welteed380d12018-06-14 13:42:11 +0200297function f_vty_transceive_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
298 var charstring ret := f_vty_transceive_ret(pt, cmd);
299 if (not match(ret, exp_ret)) {
300 setverdict(fail, "Non-matching VTY response: ", ret);
Daniel Willmannafce8662018-07-06 23:11:32 +0200301 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100302 }
303}
304
Oliver Smith141620d2019-06-07 12:27:33 +0200305function f_vty_transceive_nomatch(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
306 var charstring ret := f_vty_transceive_ret(pt, cmd);
307 if (match(ret, exp_ret)) {
308 setverdict(fail, "Matching VTY response: ", ret, ", should *not* have matched: ", exp_ret);
309 mtc.stop;
310 }
311}
312
Harald Welte70296062018-03-01 22:42:03 +0100313private template (value) charstring t_subscr_prefix(hexstring imsi) :=
314 "subscriber imsi " & hex2str(imsi) & " ";
315
Harald Weltec2c52552018-03-01 21:20:39 +0100316/* create a given subscriber using the VTY */
Harald Welteed380d12018-06-14 13:42:11 +0200317function f_vty_subscr_create(TELNETasp_PT VTY, HlrSubscriber sub) {
Harald Welte70296062018-03-01 22:42:03 +0100318 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100319 f_vty_transceive_match(VTY, prefix & "create", pattern "% Created subscriber *");
320 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(sub.msisdn),
321 pattern "% Updated subscriber *");
322 if (ispresent(sub.aud2g)) {
323 f_vty_transceive_match(VTY, prefix & "update aud2g " & sub.aud2g.algo &
324 " ki " & oct2str(sub.aud2g.ki),
325 pattern "");
326 } else {
327 f_vty_transceive_match(VTY, prefix & "update aud2g none", pattern "");
328 }
329
330 if (ispresent(sub.aud3g)) {
331 var charstring op_mode := "op";
332 if (sub.aud3g.op_is_opc) {
333 op_mode := "opc";
334 }
335 f_vty_transceive_match(VTY, prefix & "update aud3g " & sub.aud3g.algo &
336 " k " & oct2str(sub.aud3g.k) & " " & op_mode & " " &
337 oct2str(sub.aud3g.op), pattern "");
338 } else {
339 f_vty_transceive_match(VTY, prefix & "update aud3g none", pattern "");
340 }
341}
342
Harald Welteed380d12018-06-14 13:42:11 +0200343function f_vty_subscr_update_msisdn(TELNETasp_PT VTY, HlrSubscriber sub, hexstring new_msisdn) {
Harald Welte09b3c502018-03-01 22:42:22 +0100344 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
345 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(new_msisdn),
346 pattern "% Updated subscriber *");
347}
348
Harald Weltec2c52552018-03-01 21:20:39 +0100349/* perform 'delete' on subscriber */
Harald Welteed380d12018-06-14 13:42:11 +0200350function f_vty_subscr_delete(TELNETasp_PT VTY, HlrSubscriber sub) {
Harald Welte70296062018-03-01 22:42:03 +0100351 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100352 f_vty_transceive_match(VTY, prefix & "delete",
353 pattern "% Deleted subscriber for IMSI *");
354}
355
356/* perform 'show' on subscriber; match result with pattern 'exp' */
Harald Welteed380d12018-06-14 13:42:11 +0200357function f_vty_subscr_show(TELNETasp_PT VTY, HlrSubscriber sub, template charstring exp) {
Harald Welte70296062018-03-01 22:42:03 +0100358 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100359 f_vty_transceive_match(VTY, prefix & "show", exp);
360}
361
Oliver Smith141620d2019-06-07 12:27:33 +0200362/* perform 'show' on subscriber; result must not match with pattern 'exp' */
363function f_vty_subscr_show_nomatch(TELNETasp_PT VTY, HlrSubscriber sub, template charstring exp) {
364 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
365 f_vty_transceive_nomatch(VTY, prefix & "show", exp);
366}
Harald Weltec2c52552018-03-01 21:20:39 +0100367
Harald Welteed380d12018-06-14 13:42:11 +0200368/***********************************************************************
369 * Helper functions for ConnHdlr
370 ***********************************************************************/
371
Harald Weltec2c52552018-03-01 21:20:39 +0100372/* perform SendAuthInfo for given imsi, return the GSUP response/error */
373function f_perform_SAI(hexstring imsi, template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200374runs on HLR_ConnHdlr return GSUP_PDU {
Harald Weltec2c52552018-03-01 21:20:39 +0100375 var GSUP_PDU ret;
376 timer T := 3.0;
377 var boolean exp_fail := false;
378 if (not istemplatekind(exp_err_cause, "omit")) {
379 exp_fail := true;
380 }
381
382 GSUP.send(valueof(ts_GSUP_SAI_REQ(imsi)));
383 T.start;
384 alt {
385 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, exp_err_cause)) -> value ret {
386 setverdict(pass);
387 }
388 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
389 setverdict(fail, "Unexpected SAI ERROR Cause");
390 }
391 [exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
392 setverdict(fail, "Unexpected SAI.res for unknown IMSI");
393 }
394 [not exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
395 setverdict(fail, "Unexpected SAI ERROR");
396 }
397 [not exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
398 setverdict(pass);
399 }
400 [] GSUP.receive { repeat; }
401 [] T.timeout {
402 setverdict(fail, "Timeout waiting for SAI response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200403 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100404 }
405 }
406 return ret;
407}
408
409function f_perform_UL(hexstring imsi, template hexstring msisdn,
410 template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200411runs on HLR_ConnHdlr return GSUP_PDU {
Harald Weltec2c52552018-03-01 21:20:39 +0100412 var GSUP_PDU ret;
413 timer T := 3.0;
414 var boolean exp_fail := false;
415 var boolean isd_done := false;
416 if (not istemplatekind(exp_err_cause, "omit")) {
417 exp_fail := true;
418 }
419
420 GSUP.send(valueof(ts_GSUP_UL_REQ(imsi)));
421 T.start;
422 alt {
423 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, exp_err_cause)) -> value ret {
424 setverdict(pass);
425 }
426 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
427 setverdict(fail, "Unexpected UL ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100428 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100429 }
430 [exp_fail] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
431 setverdict(fail, "Unexpected UL.res for unknown IMSI");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100432 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100433 }
434 [exp_fail] GSUP.receive(tr_GSUP_ISD_REQ(imsi)) -> value ret {
435 setverdict(fail, "Unexpected ISD.req in error case");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100436 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100437 }
438 [not exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
439 setverdict(fail, "Unexpected UL ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100440 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100441 }
442 [not exp_fail and not isd_done] GSUP.receive(tr_GSUP_ISD_REQ(imsi, msisdn)) -> value ret {
443 GSUP.send(ts_GSUP_ISD_RES(imsi));
444 isd_done := true;
Harald Welte8f0c9332018-03-01 23:38:40 +0100445 repeat;
Harald Weltec2c52552018-03-01 21:20:39 +0100446 }
447 [not exp_fail and isd_done] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
448 setverdict(pass);
449 }
450 [] GSUP.receive { repeat; }
451 [] T.timeout {
452 setverdict(fail, "Timeout waiting for UL response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200453 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100454 }
455 }
456 return ret;
457}
458
Harald Welte958f8b42018-03-01 23:40:17 +0100459/* perform PurgeMS for given imsi, return the GSUP response/error */
460function f_perform_PURGE(hexstring imsi, GSUP_CnDomain cn_dom,
461 template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200462runs on HLR_ConnHdlr return GSUP_PDU {
Harald Welte958f8b42018-03-01 23:40:17 +0100463 var GSUP_PDU ret;
464 timer T := 3.0;
465 var boolean exp_fail := false;
466 if (not istemplatekind(exp_err_cause, "omit")) {
467 exp_fail := true;
468 }
469
470 GSUP.send(valueof(ts_GSUP_PURGE_MS_REQ(imsi, cn_dom)));
471 T.start;
472 alt {
473 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, exp_err_cause)) -> value ret {
474 setverdict(pass);
475 }
476 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
477 setverdict(fail, "Unexpected PURGE ERROR Cause");
478 }
479 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
480 setverdict(fail, "Unexpected PURGE.res for unknown IMSI");
481 }
482 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
483 setverdict(fail, "Unexpected PURGE ERROR");
484 }
485 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
486 setverdict(pass);
487 }
488 [] GSUP.receive { repeat; }
489 [] T.timeout {
490 setverdict(fail, "Timeout waiting for PURGE response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200491 mtc.stop;
Harald Welte958f8b42018-03-01 23:40:17 +0100492 }
493 }
494 return ret;
495}
496
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200497function f_SS_xceive(hexstring imsi, OCT4 sid, GSUP_SessionState state, octetstring ss,
498 template (omit) integer exp_err_cause := omit)
499runs on HLR_ConnHdlr return GSUP_PDU {
500 var GSUP_PDU ret;
501 timer T := 3.0;
502 var boolean exp_fail := false;
503 if (not istemplatekind(exp_err_cause, "omit")) {
504 exp_fail := true;
505 }
506
507 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(imsi, sid, state, ss)));
508 T.start;
509 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700510 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, exp_err_cause)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200511 setverdict(pass);
512 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700513 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200514 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
515 }
516 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
517 setverdict(fail, "Unexpected PROC_SS.res for unknown IMSI");
518 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700519 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200520 setverdict(fail, "Unexpected PROC_SS ERROR");
521 }
522 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
523 setverdict(pass);
524 }
525 [] GSUP.receive { repeat; }
526 [] T.timeout {
527 setverdict(fail, "Timeout waiting for PROC_SS response");
528 self.stop;
529 }
530 }
531 return ret;
532}
533
534private function f_SS_expect(hexstring imsi, OCT4 sid, GSUP_SessionState state,
535 template SS_FacilityInformation facility := *)
536runs on HLR_ConnHdlr return GSUP_PDU {
537 var GSUP_PDU ret;
538 timer T := 3.0;
539 var boolean exp_ss := true;
540 if (istemplatekind(facility, "omit")) {
541 exp_ss := false;
542 }
543 T.start;
544 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700545 [] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200546 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100547 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200548 }
549 [not exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
550 setverdict(pass);
551 }
552 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
553 setverdict(fail, "Unexpected PROC_SS.res without SS IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100554 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200555 }
556/*
557 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, decmatch facility)) -> value ret {
558 setverdict(pass);
559 }
560*/
561
562 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, ?)) -> value ret {
563 var GSUP_IeValue ss_ie;
564 f_gsup_find_ie(ret, OSMO_GSUP_SS_INFO_IE, ss_ie);
565 var SS_FacilityInformation dec_fac := dec_SS_FacilityInformation(ss_ie.ss_info);
566 log("pattern: ", facility);
567 if (match(dec_fac, facility)) {
568 setverdict(pass);
569 } else {
570 setverdict(fail, "Unexpected PROC_SS.res with non-matching facility IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100571 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200572 }
573 }
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100574 [] GSUP.receive {
575 setverdict(fail, "Unexpected GSUP");
576 mtc.stop;
577 }
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200578 [] T.timeout {
579 setverdict(fail, "Timeout waiting for PROC_SS response");
580 self.stop;
581 }
582 }
583
584 return ret;
585}
586
Oliver Smith936dbe62019-06-04 15:54:17 +0200587function f_perform_CHECK_IMEI(hexstring imsi, hexstring imei,
588 template (omit) integer exp_err_cause := omit,
589 template (omit) GSUP_IMEIResult result := omit)
590runs on HLR_ConnHdlr {
591 var GSUP_PDU pdu;
592 timer T := 3.0;
593 var boolean exp_fail := false;
594 if (not istemplatekind(exp_err_cause, "omit")) {
595 exp_fail := true;
596 }
597
598 GSUP.send(valueof(ts_GSUP_CHECK_IMEI_REQ(imsi, imei)));
599 T.start;
600 alt {
601 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, exp_err_cause)) -> value pdu {
602 setverdict(pass);
603 }
604 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?)) -> value pdu {
605 setverdict(fail, "Unexpected CHECK IMEI ERROR Cause: ", pdu);
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100606 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200607 }
608 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?)) -> value pdu {
609 setverdict(fail, "Unexpected CHECK IMEI RES instead of ERR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100610 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200611 }
612 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?)) -> value pdu {
613 setverdict(fail, "Unexpected CHECK IMEI ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100614 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200615 }
616 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, result)) -> value pdu {
617 setverdict(pass);
618 }
619 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?)) -> value pdu {
620 setverdict(fail, "Unexpected CHECK IMEI RES");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100621 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200622 }
623 [] GSUP.receive { repeat; }
624 [] T.timeout {
625 setverdict(fail, "Timeout waiting for CHECK IMEI response");
626 mtc.stop;
627 }
628 }
629}
630
631
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200632
Harald Welte958f8b42018-03-01 23:40:17 +0100633
Harald Welteed380d12018-06-14 13:42:11 +0200634/***********************************************************************
635 * Testcases
636 ***********************************************************************/
637
638/* 23.003 Section 2.2 clearly states that an IMSI with less
639 * than 5 digits is impossible. Even 5 digits is still questionable */
640private function f_TC_gsup_sai_err_invalid_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100641 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200642 res := f_perform_SAI(g_pars.sub.imsi, 96); /* Invalid Mandatory information */
643 setverdict(pass);
644}
645testcase TC_gsup_sai_err_invalid_imsi() runs on test_CT {
646 var HLR_ConnHdlr vc_conn;
647 var HLR_ConnHdlrPars pars := valueof(t_Pars('0123'H));
648 f_init(false);
649 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_invalid_imsi), pars);
650 vc_conn.done;
651}
Harald Weltec2c52552018-03-01 21:20:39 +0100652
Harald Weltec2c52552018-03-01 21:20:39 +0100653
Harald Welteed380d12018-06-14 13:42:11 +0200654private function f_TC_gsup_sai_err_unknown_imsi() runs on HLR_ConnHdlr {
655 var GSUP_PDU res;
656 res := f_perform_SAI(g_pars.sub.imsi, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100657 setverdict(pass);
658}
659
Harald Welte3f662762018-03-02 10:48:20 +0100660testcase TC_gsup_sai_err_unknown_imsi() runs on test_CT {
Harald Welteed380d12018-06-14 13:42:11 +0200661 var HLR_ConnHdlr vc_conn;
662 var HLR_ConnHdlrPars pars := valueof(t_Pars(f_rnd_imsi('26242'H)));
663 f_init(false);
664 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_unknown_imsi), pars);
665 vc_conn.done;
Harald Welte3f662762018-03-02 10:48:20 +0100666}
667
Harald Welteed380d12018-06-14 13:42:11 +0200668function f_start_handler_per_sub(void_fn fn, HlrSubscriberList sl) runs on test_CT {
669 for (var integer i := 0; i < sizeof(sl); i := i+1) {
670 var HlrSubscriber sub := sl[i];
671 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sub));
672 var HLR_ConnHdlr vc_conn;
673
674 f_vty_subscr_create(VTY, sub);
675 vc_conn := f_start_handler(fn, pars);
676 vc_conn.done;
677 f_vty_subscr_delete(VTY, sub);
678 }
679}
Harald Welte3f662762018-03-02 10:48:20 +0100680
Harald Weltec2c52552018-03-01 21:20:39 +0100681/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
Harald Welteed380d12018-06-14 13:42:11 +0200682private function f_TC_gsup_sai() runs on HLR_ConnHdlr {
683 var GSUP_PDU res;
684 res := f_perform_SAI(g_pars.sub.imsi);
685 /* TODO: match if tuple[s] matches expectation */
686 setverdict(pass);
687}
Harald Weltec2c52552018-03-01 21:20:39 +0100688testcase TC_gsup_sai() runs on test_CT {
689 var HlrSubscriberList sl;
690 var GSUP_PDU res;
691
Harald Welteed380d12018-06-14 13:42:11 +0200692 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100693
694 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200695 f_start_handler_per_sub(refers(f_TC_gsup_sai), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100696
697 setverdict(pass);
698}
699
700/* test UL for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200701private function f_TC_ul_unknown_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100702 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200703 res := f_perform_UL(g_pars.sub.imsi, ?, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100704 setverdict(pass);
705}
Harald Welteed380d12018-06-14 13:42:11 +0200706testcase TC_gsup_ul_unknown_imsi() runs on test_CT {
707 var hexstring imsi := f_rnd_imsi('26242'H);
708 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
709 var HLR_ConnHdlr vc_conn;
Harald Weltec2c52552018-03-01 21:20:39 +0100710
Harald Welteed380d12018-06-14 13:42:11 +0200711 f_init(false);
712 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
713 vc_conn.done;
714}
715
716/* test UL for a number of different subscriber cases (algo, 2g/3g, ...) */
717private function f_TC_gsup_ul() runs on HLR_ConnHdlr {
718 var GSUP_PDU res;
719 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
720 setverdict(pass);
721}
Harald Weltec2c52552018-03-01 21:20:39 +0100722testcase TC_gsup_ul() runs on test_CT {
723 var HlrSubscriberList sl;
724 var GSUP_PDU res;
725
Harald Welteed380d12018-06-14 13:42:11 +0200726 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100727 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200728 f_start_handler_per_sub(refers(f_TC_gsup_ul), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100729
730 setverdict(pass);
731}
732
733/* Test only the VTY commands */
734testcase TC_vty() runs on test_CT {
735 var HlrSubscriber sub;
736
737 f_init();
738
739 /* we're not using f_gen_subs() here as the expect pattern for the 'show' are different
740 * from case to case */
741 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
Harald Welteed380d12018-06-14 13:42:11 +0200742 f_vty_subscr_create(VTY, sub);
743 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*");
744 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100745
746 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
747 "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +0200748 f_vty_subscr_create(VTY, sub);
749 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *3G auth: MILENAGE*");
750 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100751
752 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
753 "comp128v1", "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +0200754 f_vty_subscr_create(VTY, sub);
755 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*3G auth: MILENAGE*");
756 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100757
758 setverdict(pass);
759}
760
Harald Welte09b3c502018-03-01 22:42:22 +0100761/* VTY changes to MSISDN should result in ISD to current VLR */
Harald Welteed380d12018-06-14 13:42:11 +0200762private function f_TC_vty_msisdn_isd() runs on HLR_ConnHdlr {
Harald Welte09b3c502018-03-01 22:42:22 +0100763 var hexstring new_msisdn;
764 var GSUP_PDU res;
765 timer T := 5.0;
766
Harald Welte09b3c502018-03-01 22:42:22 +0100767 /* Create Subscriber */
Harald Welteed380d12018-06-14 13:42:11 +0200768 f_vty_subscr_create(VTY, g_pars.sub);
Harald Welte09b3c502018-03-01 22:42:22 +0100769
770 /* Perform UpdateLocation (VLR now known to HLR) */
Harald Welteed380d12018-06-14 13:42:11 +0200771 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +0100772
773 /* Then change IMSI via VTY */
774 new_msisdn := '49161'H & f_rnd_hexstring(7, 9);
Harald Welteed380d12018-06-14 13:42:11 +0200775 f_vty_subscr_update_msisdn(VTY, g_pars.sub, new_msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +0100776 /* And expect InsertSubscriberData as result */
777 T.start;
778 alt {
Harald Welteed380d12018-06-14 13:42:11 +0200779 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, new_msisdn)) {
780 GSUP.send(ts_GSUP_ISD_RES(g_pars.sub.imsi));
781 g_pars.sub.msisdn := new_msisdn;
Harald Welte09b3c502018-03-01 22:42:22 +0100782 setverdict(pass);
783 }
Harald Welteed380d12018-06-14 13:42:11 +0200784 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, g_pars.sub.msisdn)) {
Stefan Sperling7c096872018-04-09 11:24:22 +0200785 log("received ISD req with old MSISDN");
786 setverdict(fail);
787 }
Harald Welte09b3c502018-03-01 22:42:22 +0100788 [] GSUP.receive { repeat; }
789 [] T.timeout {
790 setverdict(fail, "Timeout waiting for ISD.req");
791 }
792 }
793}
Harald Welteed380d12018-06-14 13:42:11 +0200794testcase TC_vty_msisdn_isd() runs on test_CT {
795 var HlrSubscriber sub;
796 var HLR_ConnHdlr vc_conn;
797
798 f_init(false);
799
800 /* Create Subscriber */
801 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
802
803 vc_conn := f_start_handler(refers(f_TC_vty_msisdn_isd), valueof(t_Pars_sub(sub)));
804 vc_conn.done;
805}
Harald Welte09b3c502018-03-01 22:42:22 +0100806
Harald Welte958f8b42018-03-01 23:40:17 +0100807/* Test PURGE MS for CS services */
Harald Welteed380d12018-06-14 13:42:11 +0200808private function f_TC_gsup_purge_cs() runs on HLR_ConnHdlr {
809 var GSUP_PDU res;
810 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
811 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS);
812}
Harald Welte958f8b42018-03-01 23:40:17 +0100813testcase TC_gsup_purge_cs() runs on test_CT {
814 var HlrSubscriberList sl;
815 var GSUP_PDU res;
816
Harald Welteed380d12018-06-14 13:42:11 +0200817 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +0100818 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200819 f_start_handler_per_sub(refers(f_TC_gsup_purge_cs), sl);
Harald Welte958f8b42018-03-01 23:40:17 +0100820
821 setverdict(pass);
822}
823
824/* Test PURGE MS for PS services */
Harald Welteed380d12018-06-14 13:42:11 +0200825private function f_TC_gsup_purge_ps() runs on HLR_ConnHdlr {
826 var GSUP_PDU res;
827 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
828 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_PS);
829}
Harald Welte958f8b42018-03-01 23:40:17 +0100830testcase TC_gsup_purge_ps() runs on test_CT {
831 var HlrSubscriberList sl;
Harald Welte958f8b42018-03-01 23:40:17 +0100832
Harald Welteed380d12018-06-14 13:42:11 +0200833 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +0100834 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200835 f_start_handler_per_sub(refers(f_TC_gsup_purge_ps), sl);
Harald Welte958f8b42018-03-01 23:40:17 +0100836
837 setverdict(pass);
838}
839
840/* Test PURGEG MS procedure for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200841
842private function f_TC_gsup_purge_unknown() runs on HLR_ConnHdlr {
843 var GSUP_PDU res;
844 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS, 2);
845}
Harald Welte958f8b42018-03-01 23:40:17 +0100846testcase TC_gsup_purge_unknown() runs on test_CT {
847 var hexstring imsi := '2345743413463'H;
Harald Welteed380d12018-06-14 13:42:11 +0200848 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
849 var HLR_ConnHdlr vc_conn;
Harald Welte958f8b42018-03-01 23:40:17 +0100850
Harald Welteed380d12018-06-14 13:42:11 +0200851 f_init(false);
852 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
853 vc_conn.done;
Harald Welte958f8b42018-03-01 23:40:17 +0100854
855 setverdict(pass);
856}
857
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200858import from HLR_EUSE all;
859
860/* Test for USSD request to undefined/unrouted short-code. Expect ss-NotAvailable(18) */
861private function f_TC_mo_ussd_unknown() runs on HLR_ConnHdlr {
862 var GSUP_PDU res;
863 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
864 op_code := SS_OP_CODE_PROCESS_USS_REQ,
865 ussd_string := "*#200#");
866 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
867 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +0700868 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
869 OSMO_GSUP_SESSION_STATE_END,
870 tr_SS_FACILITY_RETURN_ERROR(1, 18));
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200871}
872testcase TC_mo_ussd_unknown() runs on test_CT {
873 var HlrSubscriberList sl;
874 var HLR_ConnHdlr vc_conn;
875
876 f_init(false);
877 sl := f_gen_subs();
878 for (var integer i := 0; i < sizeof(sl); i := i+1) {
879 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
880 pars.ussd.sid := f_rnd_octstring(4);
881 f_vty_subscr_create(VTY, pars.sub);
882 vc_conn := f_start_handler(refers(f_TC_mo_ussd_unknown), pars);
883 vc_conn.done;
884 }
885}
886
887/* Test for USSD request to currently disconnected EUSE. Expect ss-SystemFailure(34) */
888private function f_TC_mo_ussd_euse_disc() runs on HLR_ConnHdlr {
889 var GSUP_PDU res;
890 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
891 op_code := SS_OP_CODE_PROCESS_USS_REQ,
892 ussd_string := "*100#");
893 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
894 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +0700895 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
896 OSMO_GSUP_SESSION_STATE_END,
897 tr_SS_FACILITY_RETURN_ERROR(1, 34));
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200898}
899testcase TC_mo_ussd_euse_disc() runs on test_CT {
900 var HlrSubscriberList sl;
901 var HLR_ConnHdlr vc_conn;
902
903 f_init(false);
904 sl := f_gen_subs();
905 for (var integer i := 0; i < sizeof(sl); i := i+1) {
906 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
907 pars.ussd.sid := f_rnd_octstring(4);
908 f_vty_subscr_create(VTY, pars.sub);
909 vc_conn := f_start_handler(refers(f_TC_mo_ussd_euse_disc), pars);
910 vc_conn.done;
911 }
912}
913
914/* Test for USSD request to internal own-imsi IUSE. */
915private function f_TC_mo_ussd_iuse_imsi() runs on HLR_ConnHdlr {
916 var GSUP_PDU res;
917 var charstring resp_str;
918 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
919 op_code := SS_OP_CODE_PROCESS_USS_REQ,
920 ussd_string := "*#101#");
921 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
922 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
923 resp_str := "Your IMSI is " & hex2str(g_pars.sub.imsi);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +0700924 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
925 OSMO_GSUP_SESSION_STATE_END,
926 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
927 f_encGSM7bit(resp_str)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200928}
929testcase TC_mo_ussd_iuse_imsi() runs on test_CT {
930 var HlrSubscriberList sl;
931 var HLR_ConnHdlr vc_conn;
932
933 f_init(false);
934 sl := f_gen_subs();
935 for (var integer i := 0; i < sizeof(sl); i := i+1) {
936 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
937 pars.ussd.sid := f_rnd_octstring(4);
938 f_vty_subscr_create(VTY, pars.sub);
939 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_imsi), pars);
940 vc_conn.done;
941 }
942}
943
944/* Test for USSD request to internal own-msisdn IUSE. */
945private function f_TC_mo_ussd_iuse_msisdn() runs on HLR_ConnHdlr {
946 var GSUP_PDU res;
947 var charstring resp_str;
948 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
949 op_code := SS_OP_CODE_PROCESS_USS_REQ,
950 ussd_string := "*#100#");
951 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
952 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
953 resp_str := "Your extension is " & hex2str(g_pars.sub.msisdn);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +0700954 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
955 OSMO_GSUP_SESSION_STATE_END,
956 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
957 f_encGSM7bit(resp_str)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200958}
959testcase TC_mo_ussd_iuse_msisdn() runs on test_CT {
960 var HlrSubscriberList sl;
961 var HLR_ConnHdlr vc_conn;
962
963 f_init(false);
964 sl := f_gen_subs();
965 for (var integer i := 0; i < sizeof(sl); i := i+1) {
966 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
967 pars.ussd.sid := f_rnd_octstring(4);
968 f_vty_subscr_create(VTY, pars.sub);
969 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_msisdn), pars);
970 vc_conn.done;
971 }
972}
973
974/* Test routing of USSD to EUSE by a specific route */
975private function f_TC_mo_ussd_100() runs on HLR_ConnHdlr {
976 var GSUP_PDU res;
977 /* invoke / invoke id 1 / processUSS-req */
978 //var octetstring ss := 'a11202010102013b300a04010f0405aa180c3602'O;
979 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
980 op_code := SS_OP_CODE_PROCESS_USS_REQ,
981 ussd_string := "*100#");
982 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
983 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +0700984 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
985 OSMO_GSUP_SESSION_STATE_END,
986 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
987 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200988}
989testcase TC_mo_ussd_euse() runs on test_CT {
990 var HlrSubscriberList sl;
991 var HLR_ConnHdlr vc_conn;
992
993 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
994 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
995
996 f_init(false);
997 sl := f_gen_subs();
998 for (var integer i := 0; i < sizeof(sl); i := i+1) {
999 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1000 pars.ussd.sid := f_rnd_octstring(4);
1001 f_vty_subscr_create(VTY, pars.sub);
1002 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100), pars);
1003 vc_conn.done;
1004 }
1005
1006 vc_EUSE.stop;
1007}
1008
1009/* Test routing of USSD to EUSE by a specific route, with CONTINUE */
1010private function f_TC_mo_ussd_100_continue() runs on HLR_ConnHdlr {
1011 var GSUP_PDU res;
1012 /* Simulate BEGIN from MS/MSC */
1013 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1014 ussd_string := "*100#");
1015 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1016 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1017 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001018 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1019 OSMO_GSUP_SESSION_STATE_CONTINUE,
1020 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1021 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001022
1023 /* Simulate CONTINUE from MS/MSC */
1024 ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1025 ussd_string := "mahlzeit");
1026 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1027 OSMO_GSUP_SESSION_STATE_CONTINUE, ss)));
1028
1029 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001030 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1031 OSMO_GSUP_SESSION_STATE_END,
1032 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1033 f_encGSM7bit("mahlzeit")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001034}
1035testcase TC_mo_ussd_euse_continue() runs on test_CT {
1036 var HlrSubscriberList sl;
1037 var HLR_ConnHdlr vc_conn;
1038
1039 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1040 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar",
1041 refers(f_ss_echo_continue)));
1042
1043 f_init(false);
1044 sl := f_gen_subs();
1045 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1046 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1047 pars.ussd.sid := f_rnd_octstring(4);
1048 f_vty_subscr_create(VTY, pars.sub);
1049 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100_continue), pars);
1050 vc_conn.done;
1051 }
1052
1053 vc_EUSE.stop;
1054}
1055
1056
1057/* Test routing of USSD to EUSE by default-route */
1058private function f_TC_mo_ussd_999() runs on HLR_ConnHdlr {
1059 var GSUP_PDU res;
1060 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1061 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1062 ussd_string := "*999#");
1063 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1064 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001065 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1066 OSMO_GSUP_SESSION_STATE_END,
1067 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1068 f_encGSM7bit("*999#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001069}
1070testcase TC_mo_ussd_euse_defaultroute() runs on test_CT {
1071 var HlrSubscriberList sl;
1072 var HLR_ConnHdlr vc_conn;
1073
1074 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1075 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
1076
1077 f_init(false);
1078 f_vty_config(VTY, "hlr", "ussd default-route external foobar");
1079
1080 sl := f_gen_subs();
1081 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1082 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1083 pars.ussd.sid := f_rnd_octstring(4);
1084 f_vty_subscr_create(VTY, pars.sub);
1085 vc_conn := f_start_handler(refers(f_TC_mo_ussd_999), pars);
1086 vc_conn.done;
1087 }
1088
1089 f_vty_config(VTY, "hlr", "no ussd default-route");
1090 vc_EUSE.stop;
1091}
1092
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001093/**
1094 * Test "Structured" Supplementary Services
1095 *
1096 * NOTE: at the moment, OsmoHLR doesn't support "structured" SS,
1097 * so such requests are being rejected (actually ReturnError
1098 * with GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED).
1099 */
1100private function f_TC_mo_sss_reject() runs on HLR_ConnHdlr {
1101 var SS_FacilityInformation ss_req;
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001102 var GSUP_PDU res;
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001103
1104 /* Prepare '*#21#' SS request */
1105 ss_req := valueof(ts_SS_FACILITY_INVOKE(
1106 invoke_id := 0,
1107 op_code := SS_OP_CODE_INTERROGATE_SS,
1108 ss_code := '21'O));
1109
1110 /* Send it towards HLR */
1111 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(
1112 g_pars.sub.imsi,
1113 g_pars.ussd.sid,
1114 OSMO_GSUP_SESSION_STATE_BEGIN,
1115 enc_SS_FacilityInformation(ss_req))));
1116
1117 /* Expect ReturnError with FACILITY_NOT_SUPPORTED */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001118 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1119 OSMO_GSUP_SESSION_STATE_END,
1120 tr_SS_FACILITY_RETURN_ERROR(0, 21));
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001121}
1122testcase TC_mo_sss_reject() runs on test_CT {
1123 var HLR_ConnHdlrPars pars;
1124 var HLR_ConnHdlr vc_conn;
1125 var HlrSubscriber sub;
1126
1127 f_init(false);
1128
1129 /* Create a random subscriber */
1130 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H),
1131 '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
1132 pars := valueof(t_Pars_sub(sub));
1133 pars.ussd.sid := f_rnd_octstring(4);
1134
1135 f_vty_subscr_create(VTY, sub);
1136 vc_conn := f_start_handler(refers(f_TC_mo_sss_reject), pars);
1137 vc_conn.done;
1138 f_vty_subscr_delete(VTY, sub);
1139}
1140
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001141
1142/* TODO USSD:
1143 * MO USSD for IMSI of non-existant subscriber
1144 * MT USSD from EUSE
1145 * timeout cases
1146 */
1147
Oliver Smith936dbe62019-06-04 15:54:17 +02001148
1149/* Test Check IMEI */
1150private function f_TC_gsup_check_imei() runs on HLR_ConnHdlr {
1151 /* store-imei disabled */
1152 f_vty_config(VTY, "hlr", "no store-imei");
1153 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1154 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1155
1156 /* store-imei enabled */
1157 f_vty_config(VTY, "hlr", "store-imei");
1158 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1159 f_vty_subscr_show(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1160}
1161testcase TC_gsup_check_imei() runs on test_CT {
1162 var HlrSubscriberList sl;
1163
1164 f_init(false);
1165 sl := f_gen_subs();
1166 f_start_handler_per_sub(refers(f_TC_gsup_check_imei), sl);
1167
1168 setverdict(pass);
1169}
1170
1171/* Test Check IMEI with invalid IMEI length */
1172private function f_TC_gsup_check_imei_invalid_len() runs on HLR_ConnHdlr {
1173 /* IMEI too long */
1174 f_perform_CHECK_IMEI(g_pars.sub.imsi, '111456789012345F'H, 96 /* Invalid Mandatory Information */);
1175 f_perform_CHECK_IMEI(g_pars.sub.imsi, '2224567890123456'H, 96 /* Invalid Mandatory Information */);
1176
1177 /* IMEI too short */
1178 f_perform_CHECK_IMEI(g_pars.sub.imsi, '3334567890123F'H, 96 /* Invalid Mandatory Information */);
1179 f_perform_CHECK_IMEI(g_pars.sub.imsi, '444456789012'H, 96 /* Invalid Mandatory Information */);
1180 f_perform_CHECK_IMEI(g_pars.sub.imsi, ''H, 96 /* Invalid Mandatory Information */);
1181}
1182testcase TC_gsup_check_imei_invalid_len() runs on test_CT {
1183 var HlrSubscriberList sl;
1184
1185 f_init(false);
1186 sl := f_gen_subs();
1187 f_start_handler_per_sub(refers(f_TC_gsup_check_imei_invalid_len), sl);
1188
1189 setverdict(pass);
1190}
1191
1192/* Test Check IMEI with unknown IMSI */
1193private function f_TC_gsup_check_imei_unknown_imsi() runs on HLR_ConnHdlr {
1194 f_vty_config(VTY, "hlr", "no store-imei");
1195 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1196
1197 /* Check again with store-imei set (different code path) */
1198 f_vty_config(VTY, "hlr", "store-imei");
1199 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1200
1201 setverdict(pass);
1202}
1203testcase TC_gsup_check_imei_unknown_imsi() runs on test_CT {
1204 var hexstring imsi := f_rnd_imsi('26242'H);
1205 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1206 var HLR_ConnHdlr vc_conn;
1207
1208 f_init(false);
1209 vc_conn := f_start_handler(refers(f_TC_gsup_check_imei_unknown_imsi), pars);
1210 vc_conn.done;
1211}
1212
Oliver Smith1b257802019-06-11 09:43:42 +02001213/* Test create-subscriber-on-demand during Check IMEI (OsmoMSC would be set to "check-imei-rqd early") */
1214private function f_TC_subscr_create_on_demand_check_imei_early() runs on HLR_ConnHdlr {
1215 var GSUP_PDU res; /* save various return values to prevent ttcn3 compiler warnings */
1216 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1217
1218 /* Random MSISDN and CS+PS NAM (LU must pass) */
1219 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1220 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1221 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1222 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1223 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1224 res := f_perform_UL(g_pars.sub.imsi, ?);
1225 f_vty_subscr_delete(VTY, g_pars.sub);
1226
1227 /* Random MSISDN and PS NAM (LU must pass) */
1228 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1229 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1230 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1231 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1232 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1233 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1234 res := f_perform_UL(g_pars.sub.imsi, ?);
1235 f_vty_subscr_delete(VTY, g_pars.sub);
1236
1237 /* Random MSISDN and CS NAM (LU must fail) */
1238 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1239 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1240 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1241 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1242 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1243 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1244 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1245 f_vty_subscr_delete(VTY, g_pars.sub);
1246
1247 /* Random MSISDN and no NAM (LU must fail) */
1248 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1249 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1250 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1251 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1252 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1253 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1254 f_vty_subscr_delete(VTY, g_pars.sub);
1255
1256 /* No MSISDN and no NAM (LU must fail) */
1257 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1258 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1259 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1260 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1261 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1262 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1263 f_vty_subscr_delete(VTY, g_pars.sub);
1264
1265 /* No MSISDN and CS+PS NAM (LU must pass) */
1266 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1267 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1268 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1269 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1270 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1271 res := f_perform_UL(g_pars.sub.imsi, omit);
1272 f_vty_subscr_delete(VTY, g_pars.sub);
1273
1274 setverdict(pass);
1275}
1276testcase TC_subscr_create_on_demand_check_imei_early() runs on test_CT {
1277 var hexstring imsi := f_rnd_imsi('26242'H);
1278 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1279 var HLR_ConnHdlr vc_conn;
1280
1281 f_init(false);
1282 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_check_imei_early), pars);
1283 vc_conn.done;
1284}
1285
1286/* Test create-subscriber-on-demand during LU (Location Update) */
1287private function f_TC_subscr_create_on_demand_ul() runs on HLR_ConnHdlr {
1288 var GSUP_PDU res;
1289 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1290
1291 /* Random MSISDN and CS+PS NAM (LU must pass) */
1292 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1293 res := f_perform_UL(g_pars.sub.imsi, ?);
1294 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1295 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1296 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1297 f_vty_subscr_delete(VTY, g_pars.sub);
1298
1299 /* Random MSISDN and PS NAM (LU must pass) */
1300 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1301 res := f_perform_UL(g_pars.sub.imsi, ?);
1302 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1303 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1304 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1305 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1306 f_vty_subscr_delete(VTY, g_pars.sub);
1307
1308 /* Random MSISDN and CS NAM (LU must fail) */
1309 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1310 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1311 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1312 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1313 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1314 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1315 f_vty_subscr_delete(VTY, g_pars.sub);
1316
1317 /* Random MSISDN and no NAM (LU must fail) */
1318 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1319 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1320 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1321 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1322 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1323 f_vty_subscr_delete(VTY, g_pars.sub);
1324
1325 /* No MSISDN and no NAM (LU must fail) */
1326 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1327 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1328 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1329 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1330 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1331 f_vty_subscr_delete(VTY, g_pars.sub);
1332
1333 /* No MSISDN and CS+PS NAM (LU must pass) */
1334 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1335 res := f_perform_UL(g_pars.sub.imsi, omit);
1336 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1337 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1338 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1339 f_vty_subscr_delete(VTY, g_pars.sub);
1340
1341 setverdict(pass);
1342}
1343testcase TC_subscr_create_on_demand_ul() runs on test_CT {
1344 var hexstring imsi := f_rnd_imsi('26242'H);
1345 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1346 var HLR_ConnHdlr vc_conn;
1347
1348 f_init(false);
1349 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_ul), pars);
1350 vc_conn.done;
1351}
1352
1353/* Test create-subscriber-on-demand during SAI (SendAuthInfo) */
1354private function f_TC_subscr_create_on_demand_sai() runs on HLR_ConnHdlr {
1355 var GSUP_PDU res;
1356 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1357
1358 /* HLR creates the subscriber on demand. Then the IMSI is known, but there is no auth data, so the HLR returns
1359 * the "slightly inaccurate cause 'IMSI Unknown' via GSUP". The MS is able to do a LU afterwards. */
1360 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1361 res := f_perform_SAI(g_pars.sub.imsi, 2 /* IMSI Unknown */ );
1362
1363 /* Verify that it was created before the LU */
1364 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1365 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1366 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1367
1368 /* Location update */
1369 res := f_perform_UL(g_pars.sub.imsi, ?);
1370 f_vty_subscr_delete(VTY, g_pars.sub);
1371 setverdict(pass);
1372}
1373testcase TC_subscr_create_on_demand_sai() runs on test_CT {
1374 var hexstring imsi := f_rnd_imsi('26242'H);
1375 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1376 var HLR_ConnHdlr vc_conn;
1377
1378 f_init(false);
1379 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_sai), pars);
1380 vc_conn.done;
1381}
1382
Harald Weltec2c52552018-03-01 21:20:39 +01001383/* TODO:
1384 * UL with ISD error
1385 * UL with ISD timeout
Harald Weltec2c52552018-03-01 21:20:39 +01001386 * LOCATION CANCEL
1387 * AUTH FAIL REP
1388 * DELETE DATA after hlr_subscr_nam() change
1389 * correctness
1390 ** wrong message type
1391 ** wrong length of PDU
1392 ** too short message
1393 ** missing IMSI IE
1394
1395 */
1396
Harald Weltedf327232017-12-28 22:51:51 +01001397control {
1398 execute( TC_gsup_sai_err_invalid_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001399 execute( TC_gsup_sai() );
1400 execute( TC_gsup_ul_unknown_imsi() );
Harald Welte3f662762018-03-02 10:48:20 +01001401 execute( TC_gsup_sai_err_unknown_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001402 execute( TC_gsup_ul() );
1403 execute( TC_vty() );
Harald Welte09b3c502018-03-01 22:42:22 +01001404 execute( TC_vty_msisdn_isd() );
Harald Welte958f8b42018-03-01 23:40:17 +01001405 execute( TC_gsup_purge_cs() );
1406 execute( TC_gsup_purge_ps() );
1407 execute( TC_gsup_purge_unknown() );
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001408
1409 execute( TC_mo_ussd_unknown() );
1410 execute( TC_mo_ussd_euse_disc() );
1411 execute( TC_mo_ussd_iuse_imsi() );
1412 execute( TC_mo_ussd_iuse_msisdn() );
1413 execute( TC_mo_ussd_euse() );
1414 execute( TC_mo_ussd_euse_continue() );
1415 execute( TC_mo_ussd_euse_defaultroute() );
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001416
1417 /* "Structured" Supplementary Services */
1418 execute( TC_mo_sss_reject() );
Oliver Smith936dbe62019-06-04 15:54:17 +02001419
1420 execute( TC_gsup_check_imei() );
1421 execute( TC_gsup_check_imei_invalid_len() );
1422 execute( TC_gsup_check_imei_unknown_imsi() );
Oliver Smith1b257802019-06-11 09:43:42 +02001423 execute( TC_subscr_create_on_demand_check_imei_early() );
1424 execute( TC_subscr_create_on_demand_ul() );
1425 execute( TC_subscr_create_on_demand_sai() );
Harald Weltedf327232017-12-28 22:51:51 +01001426};
1427
1428};