blob: 50109a6fbe03658326329a9c73430d090e8d7da4 [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}
Harald Welteaf7c3182019-08-22 12:40:22 +0200296function f_gen_3G_subs() runs on test_CT return HlrSubscriberList {
297 var HlrSubscriber sub;
298 var HlrSubscriberList sl := {};
299
300 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", false));
301 sl := sl & { sub };
302
303 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", true));
304 sl := sl & { sub };
305
306 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
307 "comp128v1", "milenage", false));
308 sl := sl & { sub };
309
310 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
311 "comp128v2", "milenage", false));
312 sl := sl & { sub };
313
314 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
315 "comp128v3", "milenage", false));
316 sl := sl & { sub };
317
318 return sl;
319}
Harald Weltec2c52552018-03-01 21:20:39 +0100320
Harald Welteed380d12018-06-14 13:42:11 +0200321function f_vty_transceive_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
322 var charstring ret := f_vty_transceive_ret(pt, cmd);
323 if (not match(ret, exp_ret)) {
324 setverdict(fail, "Non-matching VTY response: ", ret);
Daniel Willmannafce8662018-07-06 23:11:32 +0200325 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100326 }
327}
328
Oliver Smith141620d2019-06-07 12:27:33 +0200329function f_vty_transceive_nomatch(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
330 var charstring ret := f_vty_transceive_ret(pt, cmd);
331 if (match(ret, exp_ret)) {
332 setverdict(fail, "Matching VTY response: ", ret, ", should *not* have matched: ", exp_ret);
333 mtc.stop;
334 }
335}
336
Harald Welte70296062018-03-01 22:42:03 +0100337private template (value) charstring t_subscr_prefix(hexstring imsi) :=
338 "subscriber imsi " & hex2str(imsi) & " ";
339
Harald Weltec2c52552018-03-01 21:20:39 +0100340/* create a given subscriber using the VTY */
Harald Welteed380d12018-06-14 13:42:11 +0200341function f_vty_subscr_create(TELNETasp_PT VTY, HlrSubscriber sub) {
Harald Welte70296062018-03-01 22:42:03 +0100342 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100343 f_vty_transceive_match(VTY, prefix & "create", pattern "% Created subscriber *");
344 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(sub.msisdn),
345 pattern "% Updated subscriber *");
346 if (ispresent(sub.aud2g)) {
347 f_vty_transceive_match(VTY, prefix & "update aud2g " & sub.aud2g.algo &
348 " ki " & oct2str(sub.aud2g.ki),
349 pattern "");
350 } else {
351 f_vty_transceive_match(VTY, prefix & "update aud2g none", pattern "");
352 }
353
354 if (ispresent(sub.aud3g)) {
355 var charstring op_mode := "op";
356 if (sub.aud3g.op_is_opc) {
357 op_mode := "opc";
358 }
359 f_vty_transceive_match(VTY, prefix & "update aud3g " & sub.aud3g.algo &
360 " k " & oct2str(sub.aud3g.k) & " " & op_mode & " " &
361 oct2str(sub.aud3g.op), pattern "");
362 } else {
363 f_vty_transceive_match(VTY, prefix & "update aud3g none", pattern "");
364 }
365}
366
Harald Welteed380d12018-06-14 13:42:11 +0200367function f_vty_subscr_update_msisdn(TELNETasp_PT VTY, HlrSubscriber sub, hexstring new_msisdn) {
Harald Welte09b3c502018-03-01 22:42:22 +0100368 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
369 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(new_msisdn),
370 pattern "% Updated subscriber *");
371}
372
Harald Weltec2c52552018-03-01 21:20:39 +0100373/* perform 'delete' on subscriber */
Harald Welteed380d12018-06-14 13:42:11 +0200374function f_vty_subscr_delete(TELNETasp_PT VTY, HlrSubscriber sub) {
Harald Welte70296062018-03-01 22:42:03 +0100375 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100376 f_vty_transceive_match(VTY, prefix & "delete",
377 pattern "% Deleted subscriber for IMSI *");
378}
379
380/* perform 'show' on subscriber; match result with pattern 'exp' */
Harald Welteed380d12018-06-14 13:42:11 +0200381function f_vty_subscr_show(TELNETasp_PT VTY, HlrSubscriber sub, template charstring exp) {
Harald Welte70296062018-03-01 22:42:03 +0100382 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100383 f_vty_transceive_match(VTY, prefix & "show", exp);
384}
385
Oliver Smith141620d2019-06-07 12:27:33 +0200386/* perform 'show' on subscriber; result must not match with pattern 'exp' */
387function f_vty_subscr_show_nomatch(TELNETasp_PT VTY, HlrSubscriber sub, template charstring exp) {
388 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
389 f_vty_transceive_nomatch(VTY, prefix & "show", exp);
390}
Harald Weltec2c52552018-03-01 21:20:39 +0100391
Harald Welteed380d12018-06-14 13:42:11 +0200392/***********************************************************************
393 * Helper functions for ConnHdlr
394 ***********************************************************************/
395
Harald Weltec2c52552018-03-01 21:20:39 +0100396/* perform SendAuthInfo for given imsi, return the GSUP response/error */
Harald Welteaf7c3182019-08-22 12:40:22 +0200397function f_perform_SAI(hexstring imsi, template (omit) integer exp_err_cause := omit,
398 boolean is_eps := false)
Harald Welteed380d12018-06-14 13:42:11 +0200399runs on HLR_ConnHdlr return GSUP_PDU {
Harald Weltec2c52552018-03-01 21:20:39 +0100400 var GSUP_PDU ret;
401 timer T := 3.0;
402 var boolean exp_fail := false;
403 if (not istemplatekind(exp_err_cause, "omit")) {
404 exp_fail := true;
405 }
406
Harald Welteaf7c3182019-08-22 12:40:22 +0200407 if (is_eps) {
408 GSUP.send(ts_GSUP_SAI_REQ_EPS(imsi));
409 } else {
410 GSUP.send(valueof(ts_GSUP_SAI_REQ(imsi)));
411 }
Harald Weltec2c52552018-03-01 21:20:39 +0100412 T.start;
413 alt {
414 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, exp_err_cause)) -> value ret {
415 setverdict(pass);
416 }
417 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
418 setverdict(fail, "Unexpected SAI ERROR Cause");
419 }
420 [exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
421 setverdict(fail, "Unexpected SAI.res for unknown IMSI");
422 }
423 [not exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
424 setverdict(fail, "Unexpected SAI ERROR");
425 }
426 [not exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
427 setverdict(pass);
428 }
429 [] GSUP.receive { repeat; }
430 [] T.timeout {
431 setverdict(fail, "Timeout waiting for SAI response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200432 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100433 }
434 }
435 return ret;
436}
437
438function f_perform_UL(hexstring imsi, template hexstring msisdn,
439 template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200440runs on HLR_ConnHdlr return GSUP_PDU {
Harald Weltec2c52552018-03-01 21:20:39 +0100441 var GSUP_PDU ret;
442 timer T := 3.0;
443 var boolean exp_fail := false;
444 var boolean isd_done := false;
445 if (not istemplatekind(exp_err_cause, "omit")) {
446 exp_fail := true;
447 }
448
449 GSUP.send(valueof(ts_GSUP_UL_REQ(imsi)));
450 T.start;
451 alt {
452 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, exp_err_cause)) -> value ret {
453 setverdict(pass);
454 }
455 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
456 setverdict(fail, "Unexpected UL ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100457 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100458 }
459 [exp_fail] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
460 setverdict(fail, "Unexpected UL.res for unknown IMSI");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100461 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100462 }
463 [exp_fail] GSUP.receive(tr_GSUP_ISD_REQ(imsi)) -> value ret {
464 setverdict(fail, "Unexpected ISD.req in error case");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100465 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100466 }
467 [not exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
468 setverdict(fail, "Unexpected UL ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100469 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100470 }
471 [not exp_fail and not isd_done] GSUP.receive(tr_GSUP_ISD_REQ(imsi, msisdn)) -> value ret {
472 GSUP.send(ts_GSUP_ISD_RES(imsi));
473 isd_done := true;
Harald Welte8f0c9332018-03-01 23:38:40 +0100474 repeat;
Harald Weltec2c52552018-03-01 21:20:39 +0100475 }
476 [not exp_fail and isd_done] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
477 setverdict(pass);
478 }
479 [] GSUP.receive { repeat; }
480 [] T.timeout {
481 setverdict(fail, "Timeout waiting for UL response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200482 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100483 }
484 }
485 return ret;
486}
487
Harald Welte958f8b42018-03-01 23:40:17 +0100488/* perform PurgeMS for given imsi, return the GSUP response/error */
489function f_perform_PURGE(hexstring imsi, GSUP_CnDomain cn_dom,
490 template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200491runs on HLR_ConnHdlr return GSUP_PDU {
Harald Welte958f8b42018-03-01 23:40:17 +0100492 var GSUP_PDU ret;
493 timer T := 3.0;
494 var boolean exp_fail := false;
495 if (not istemplatekind(exp_err_cause, "omit")) {
496 exp_fail := true;
497 }
498
499 GSUP.send(valueof(ts_GSUP_PURGE_MS_REQ(imsi, cn_dom)));
500 T.start;
501 alt {
502 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, exp_err_cause)) -> value ret {
503 setverdict(pass);
504 }
505 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
506 setverdict(fail, "Unexpected PURGE ERROR Cause");
507 }
508 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
509 setverdict(fail, "Unexpected PURGE.res for unknown IMSI");
510 }
511 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
512 setverdict(fail, "Unexpected PURGE ERROR");
513 }
514 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
515 setverdict(pass);
516 }
517 [] GSUP.receive { repeat; }
518 [] T.timeout {
519 setverdict(fail, "Timeout waiting for PURGE response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200520 mtc.stop;
Harald Welte958f8b42018-03-01 23:40:17 +0100521 }
522 }
523 return ret;
524}
525
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200526function f_SS_xceive(hexstring imsi, OCT4 sid, GSUP_SessionState state, octetstring ss,
527 template (omit) integer exp_err_cause := omit)
528runs on HLR_ConnHdlr return GSUP_PDU {
529 var GSUP_PDU ret;
530 timer T := 3.0;
531 var boolean exp_fail := false;
532 if (not istemplatekind(exp_err_cause, "omit")) {
533 exp_fail := true;
534 }
535
536 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(imsi, sid, state, ss)));
537 T.start;
538 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700539 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, exp_err_cause)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200540 setverdict(pass);
541 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700542 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200543 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
544 }
545 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
546 setverdict(fail, "Unexpected PROC_SS.res for unknown IMSI");
547 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700548 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200549 setverdict(fail, "Unexpected PROC_SS ERROR");
550 }
551 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
552 setverdict(pass);
553 }
554 [] GSUP.receive { repeat; }
555 [] T.timeout {
556 setverdict(fail, "Timeout waiting for PROC_SS response");
557 self.stop;
558 }
559 }
560 return ret;
561}
562
563private function f_SS_expect(hexstring imsi, OCT4 sid, GSUP_SessionState state,
564 template SS_FacilityInformation facility := *)
565runs on HLR_ConnHdlr return GSUP_PDU {
566 var GSUP_PDU ret;
567 timer T := 3.0;
568 var boolean exp_ss := true;
569 if (istemplatekind(facility, "omit")) {
570 exp_ss := false;
571 }
572 T.start;
573 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700574 [] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200575 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100576 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200577 }
578 [not exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
579 setverdict(pass);
580 }
581 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
582 setverdict(fail, "Unexpected PROC_SS.res without SS IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100583 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200584 }
585/*
586 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, decmatch facility)) -> value ret {
587 setverdict(pass);
588 }
589*/
590
591 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, ?)) -> value ret {
592 var GSUP_IeValue ss_ie;
593 f_gsup_find_ie(ret, OSMO_GSUP_SS_INFO_IE, ss_ie);
594 var SS_FacilityInformation dec_fac := dec_SS_FacilityInformation(ss_ie.ss_info);
595 log("pattern: ", facility);
596 if (match(dec_fac, facility)) {
597 setverdict(pass);
598 } else {
599 setverdict(fail, "Unexpected PROC_SS.res with non-matching facility IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100600 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200601 }
602 }
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100603 [] GSUP.receive {
604 setverdict(fail, "Unexpected GSUP");
605 mtc.stop;
606 }
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200607 [] T.timeout {
608 setverdict(fail, "Timeout waiting for PROC_SS response");
609 self.stop;
610 }
611 }
612
613 return ret;
614}
615
Oliver Smith936dbe62019-06-04 15:54:17 +0200616function f_perform_CHECK_IMEI(hexstring imsi, hexstring imei,
617 template (omit) integer exp_err_cause := omit,
618 template (omit) GSUP_IMEIResult result := omit)
619runs on HLR_ConnHdlr {
620 var GSUP_PDU pdu;
621 timer T := 3.0;
622 var boolean exp_fail := false;
623 if (not istemplatekind(exp_err_cause, "omit")) {
624 exp_fail := true;
625 }
626
627 GSUP.send(valueof(ts_GSUP_CHECK_IMEI_REQ(imsi, imei)));
628 T.start;
629 alt {
630 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, exp_err_cause)) -> value pdu {
631 setverdict(pass);
632 }
633 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?)) -> value pdu {
634 setverdict(fail, "Unexpected CHECK IMEI ERROR Cause: ", pdu);
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100635 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200636 }
637 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?)) -> value pdu {
638 setverdict(fail, "Unexpected CHECK IMEI RES instead of ERR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100639 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200640 }
641 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?)) -> value pdu {
642 setverdict(fail, "Unexpected CHECK IMEI ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100643 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200644 }
645 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, result)) -> value pdu {
646 setverdict(pass);
647 }
648 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?)) -> value pdu {
649 setverdict(fail, "Unexpected CHECK IMEI RES");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100650 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200651 }
652 [] GSUP.receive { repeat; }
653 [] T.timeout {
654 setverdict(fail, "Timeout waiting for CHECK IMEI response");
655 mtc.stop;
656 }
657 }
658}
659
660
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200661
Harald Welte958f8b42018-03-01 23:40:17 +0100662
Harald Welteed380d12018-06-14 13:42:11 +0200663/***********************************************************************
664 * Testcases
665 ***********************************************************************/
666
667/* 23.003 Section 2.2 clearly states that an IMSI with less
668 * than 5 digits is impossible. Even 5 digits is still questionable */
669private function f_TC_gsup_sai_err_invalid_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100670 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200671 res := f_perform_SAI(g_pars.sub.imsi, 96); /* Invalid Mandatory information */
672 setverdict(pass);
673}
674testcase TC_gsup_sai_err_invalid_imsi() runs on test_CT {
675 var HLR_ConnHdlr vc_conn;
676 var HLR_ConnHdlrPars pars := valueof(t_Pars('0123'H));
677 f_init(false);
678 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_invalid_imsi), pars);
679 vc_conn.done;
680}
Harald Weltec2c52552018-03-01 21:20:39 +0100681
Harald Weltec2c52552018-03-01 21:20:39 +0100682
Harald Welteed380d12018-06-14 13:42:11 +0200683private function f_TC_gsup_sai_err_unknown_imsi() runs on HLR_ConnHdlr {
684 var GSUP_PDU res;
685 res := f_perform_SAI(g_pars.sub.imsi, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100686 setverdict(pass);
687}
688
Harald Welte3f662762018-03-02 10:48:20 +0100689testcase TC_gsup_sai_err_unknown_imsi() runs on test_CT {
Harald Welteed380d12018-06-14 13:42:11 +0200690 var HLR_ConnHdlr vc_conn;
691 var HLR_ConnHdlrPars pars := valueof(t_Pars(f_rnd_imsi('26242'H)));
692 f_init(false);
693 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_unknown_imsi), pars);
694 vc_conn.done;
Harald Welte3f662762018-03-02 10:48:20 +0100695}
696
Harald Welteed380d12018-06-14 13:42:11 +0200697function f_start_handler_per_sub(void_fn fn, HlrSubscriberList sl) runs on test_CT {
698 for (var integer i := 0; i < sizeof(sl); i := i+1) {
699 var HlrSubscriber sub := sl[i];
700 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sub));
701 var HLR_ConnHdlr vc_conn;
702
703 f_vty_subscr_create(VTY, sub);
704 vc_conn := f_start_handler(fn, pars);
705 vc_conn.done;
706 f_vty_subscr_delete(VTY, sub);
707 }
708}
Harald Welte3f662762018-03-02 10:48:20 +0100709
Harald Weltec2c52552018-03-01 21:20:39 +0100710/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
Harald Welteed380d12018-06-14 13:42:11 +0200711private function f_TC_gsup_sai() runs on HLR_ConnHdlr {
712 var GSUP_PDU res;
713 res := f_perform_SAI(g_pars.sub.imsi);
Harald Welte4b612042019-12-03 20:08:57 +0100714 if (ispresent(g_pars.sub.aud3g)) {
715 f_ensure_amf_separation_bit(res, '0'B);
716 }
Harald Welteed380d12018-06-14 13:42:11 +0200717 /* TODO: match if tuple[s] matches expectation */
718 setverdict(pass);
719}
Harald Weltec2c52552018-03-01 21:20:39 +0100720testcase TC_gsup_sai() runs on test_CT {
721 var HlrSubscriberList sl;
722 var GSUP_PDU res;
723
Harald Welteed380d12018-06-14 13:42:11 +0200724 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100725
726 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200727 f_start_handler_per_sub(refers(f_TC_gsup_sai), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100728
729 setverdict(pass);
730}
731
Harald Welteaf7c3182019-08-22 12:40:22 +0200732private function f_ensure_amf_separation_bit(GSUP_PDU res, BIT1 sep_bit)
733{
734 for (var integer i := 0; i < lengthof(res.ies); i := i+1) {
735 var GSUP_IE tuple := res.ies[i];
736 if (tuple.tag != OSMO_GSUP_AUTH_TUPLE_IE) {
737 continue;
738 }
739 var GSUP_IeValue autn;
740 if (f_gsup_find_nested_ie(tuple.val.auth_tuple, OSMO_GSUP_AUTN_IE, autn) == false) {
741 setverdict(fail, "Couldn't find AUTN IE in tuple ", i);
742 mtc.stop;
743 }
744 var bitstring amf := oct2bit(substr(autn.autn, 6, 2));
745 if (amf[0] != sep_bit) {
746 setverdict(fail, "AMF bit 0 (separation bit) must be ", sep_bit," but was not");
747 mtc.stop;
748 }
749 }
750}
751
752/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
753private function f_TC_gsup_sai_eps() runs on HLR_ConnHdlr {
754 var GSUP_PDU res;
755 res := f_perform_SAI(g_pars.sub.imsi, is_eps := true);
756 f_ensure_amf_separation_bit(res, '1'B);
757
758 /* TODO: match if tuple[s] matches expectation */
759 setverdict(pass);
760}
761testcase TC_gsup_sai_eps() runs on test_CT {
762 var HlrSubscriberList sl;
763 var GSUP_PDU res;
764
765 f_init(false);
766
767 sl := f_gen_3G_subs();
768 f_start_handler_per_sub(refers(f_TC_gsup_sai_eps), sl);
769
770 setverdict(pass);
771}
772
773
Harald Weltec2c52552018-03-01 21:20:39 +0100774/* test UL for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200775private function f_TC_ul_unknown_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100776 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200777 res := f_perform_UL(g_pars.sub.imsi, ?, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100778 setverdict(pass);
779}
Harald Welteed380d12018-06-14 13:42:11 +0200780testcase TC_gsup_ul_unknown_imsi() runs on test_CT {
781 var hexstring imsi := f_rnd_imsi('26242'H);
782 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
783 var HLR_ConnHdlr vc_conn;
Harald Weltec2c52552018-03-01 21:20:39 +0100784
Harald Welteed380d12018-06-14 13:42:11 +0200785 f_init(false);
786 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
787 vc_conn.done;
788}
789
790/* test UL for a number of different subscriber cases (algo, 2g/3g, ...) */
791private function f_TC_gsup_ul() runs on HLR_ConnHdlr {
792 var GSUP_PDU res;
793 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
794 setverdict(pass);
795}
Harald Weltec2c52552018-03-01 21:20:39 +0100796testcase TC_gsup_ul() runs on test_CT {
797 var HlrSubscriberList sl;
798 var GSUP_PDU res;
799
Harald Welteed380d12018-06-14 13:42:11 +0200800 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100801 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200802 f_start_handler_per_sub(refers(f_TC_gsup_ul), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100803
804 setverdict(pass);
805}
806
807/* Test only the VTY commands */
808testcase TC_vty() runs on test_CT {
809 var HlrSubscriber sub;
810
811 f_init();
812
813 /* we're not using f_gen_subs() here as the expect pattern for the 'show' are different
814 * from case to case */
815 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
Harald Welteed380d12018-06-14 13:42:11 +0200816 f_vty_subscr_create(VTY, sub);
817 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*");
818 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100819
820 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
821 "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +0200822 f_vty_subscr_create(VTY, sub);
823 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *3G auth: MILENAGE*");
824 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100825
826 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
827 "comp128v1", "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +0200828 f_vty_subscr_create(VTY, sub);
829 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*3G auth: MILENAGE*");
830 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100831
832 setverdict(pass);
833}
834
Harald Welte09b3c502018-03-01 22:42:22 +0100835/* VTY changes to MSISDN should result in ISD to current VLR */
Harald Welteed380d12018-06-14 13:42:11 +0200836private function f_TC_vty_msisdn_isd() runs on HLR_ConnHdlr {
Harald Welte09b3c502018-03-01 22:42:22 +0100837 var hexstring new_msisdn;
838 var GSUP_PDU res;
839 timer T := 5.0;
840
Harald Welte09b3c502018-03-01 22:42:22 +0100841 /* Create Subscriber */
Harald Welteed380d12018-06-14 13:42:11 +0200842 f_vty_subscr_create(VTY, g_pars.sub);
Harald Welte09b3c502018-03-01 22:42:22 +0100843
844 /* Perform UpdateLocation (VLR now known to HLR) */
Harald Welteed380d12018-06-14 13:42:11 +0200845 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +0100846
847 /* Then change IMSI via VTY */
848 new_msisdn := '49161'H & f_rnd_hexstring(7, 9);
Harald Welteed380d12018-06-14 13:42:11 +0200849 f_vty_subscr_update_msisdn(VTY, g_pars.sub, new_msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +0100850 /* And expect InsertSubscriberData as result */
851 T.start;
852 alt {
Harald Welteed380d12018-06-14 13:42:11 +0200853 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, new_msisdn)) {
854 GSUP.send(ts_GSUP_ISD_RES(g_pars.sub.imsi));
855 g_pars.sub.msisdn := new_msisdn;
Harald Welte09b3c502018-03-01 22:42:22 +0100856 setverdict(pass);
857 }
Harald Welteed380d12018-06-14 13:42:11 +0200858 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, g_pars.sub.msisdn)) {
Stefan Sperling7c096872018-04-09 11:24:22 +0200859 log("received ISD req with old MSISDN");
860 setverdict(fail);
861 }
Harald Welte09b3c502018-03-01 22:42:22 +0100862 [] GSUP.receive { repeat; }
863 [] T.timeout {
864 setverdict(fail, "Timeout waiting for ISD.req");
865 }
866 }
867}
Harald Welteed380d12018-06-14 13:42:11 +0200868testcase TC_vty_msisdn_isd() runs on test_CT {
869 var HlrSubscriber sub;
870 var HLR_ConnHdlr vc_conn;
871
872 f_init(false);
873
874 /* Create Subscriber */
875 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
876
877 vc_conn := f_start_handler(refers(f_TC_vty_msisdn_isd), valueof(t_Pars_sub(sub)));
878 vc_conn.done;
879}
Harald Welte09b3c502018-03-01 22:42:22 +0100880
Harald Welte958f8b42018-03-01 23:40:17 +0100881/* Test PURGE MS for CS services */
Harald Welteed380d12018-06-14 13:42:11 +0200882private function f_TC_gsup_purge_cs() runs on HLR_ConnHdlr {
883 var GSUP_PDU res;
884 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
885 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS);
886}
Harald Welte958f8b42018-03-01 23:40:17 +0100887testcase TC_gsup_purge_cs() runs on test_CT {
888 var HlrSubscriberList sl;
889 var GSUP_PDU res;
890
Harald Welteed380d12018-06-14 13:42:11 +0200891 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +0100892 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200893 f_start_handler_per_sub(refers(f_TC_gsup_purge_cs), sl);
Harald Welte958f8b42018-03-01 23:40:17 +0100894
895 setverdict(pass);
896}
897
898/* Test PURGE MS for PS services */
Harald Welteed380d12018-06-14 13:42:11 +0200899private function f_TC_gsup_purge_ps() runs on HLR_ConnHdlr {
900 var GSUP_PDU res;
901 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
902 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_PS);
903}
Harald Welte958f8b42018-03-01 23:40:17 +0100904testcase TC_gsup_purge_ps() runs on test_CT {
905 var HlrSubscriberList sl;
Harald Welte958f8b42018-03-01 23:40:17 +0100906
Harald Welteed380d12018-06-14 13:42:11 +0200907 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +0100908 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200909 f_start_handler_per_sub(refers(f_TC_gsup_purge_ps), sl);
Harald Welte958f8b42018-03-01 23:40:17 +0100910
911 setverdict(pass);
912}
913
914/* Test PURGEG MS procedure for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200915
916private function f_TC_gsup_purge_unknown() runs on HLR_ConnHdlr {
917 var GSUP_PDU res;
918 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS, 2);
919}
Harald Welte958f8b42018-03-01 23:40:17 +0100920testcase TC_gsup_purge_unknown() runs on test_CT {
921 var hexstring imsi := '2345743413463'H;
Harald Welteed380d12018-06-14 13:42:11 +0200922 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
923 var HLR_ConnHdlr vc_conn;
Harald Welte958f8b42018-03-01 23:40:17 +0100924
Harald Welteed380d12018-06-14 13:42:11 +0200925 f_init(false);
926 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
927 vc_conn.done;
Harald Welte958f8b42018-03-01 23:40:17 +0100928
929 setverdict(pass);
930}
931
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200932import from HLR_EUSE all;
933
934/* Test for USSD request to undefined/unrouted short-code. Expect ss-NotAvailable(18) */
935private function f_TC_mo_ussd_unknown() runs on HLR_ConnHdlr {
936 var GSUP_PDU res;
937 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
938 op_code := SS_OP_CODE_PROCESS_USS_REQ,
939 ussd_string := "*#200#");
940 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
941 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +0700942 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
943 OSMO_GSUP_SESSION_STATE_END,
944 tr_SS_FACILITY_RETURN_ERROR(1, 18));
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200945}
946testcase TC_mo_ussd_unknown() runs on test_CT {
947 var HlrSubscriberList sl;
948 var HLR_ConnHdlr vc_conn;
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_unknown), pars);
957 vc_conn.done;
958 }
959}
960
961/* Test for USSD request to currently disconnected EUSE. Expect ss-SystemFailure(34) */
962private function f_TC_mo_ussd_euse_disc() runs on HLR_ConnHdlr {
963 var GSUP_PDU res;
964 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
965 op_code := SS_OP_CODE_PROCESS_USS_REQ,
966 ussd_string := "*100#");
967 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
968 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +0700969 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
970 OSMO_GSUP_SESSION_STATE_END,
971 tr_SS_FACILITY_RETURN_ERROR(1, 34));
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200972}
973testcase TC_mo_ussd_euse_disc() runs on test_CT {
974 var HlrSubscriberList sl;
975 var HLR_ConnHdlr vc_conn;
976
977 f_init(false);
978 sl := f_gen_subs();
979 for (var integer i := 0; i < sizeof(sl); i := i+1) {
980 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
981 pars.ussd.sid := f_rnd_octstring(4);
982 f_vty_subscr_create(VTY, pars.sub);
983 vc_conn := f_start_handler(refers(f_TC_mo_ussd_euse_disc), pars);
984 vc_conn.done;
985 }
986}
987
988/* Test for USSD request to internal own-imsi IUSE. */
989private function f_TC_mo_ussd_iuse_imsi() runs on HLR_ConnHdlr {
990 var GSUP_PDU res;
991 var charstring resp_str;
992 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
993 op_code := SS_OP_CODE_PROCESS_USS_REQ,
994 ussd_string := "*#101#");
995 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
996 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
997 resp_str := "Your IMSI is " & hex2str(g_pars.sub.imsi);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +0700998 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
999 OSMO_GSUP_SESSION_STATE_END,
1000 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1001 f_encGSM7bit(resp_str)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001002}
1003testcase TC_mo_ussd_iuse_imsi() runs on test_CT {
1004 var HlrSubscriberList sl;
1005 var HLR_ConnHdlr vc_conn;
1006
1007 f_init(false);
1008 sl := f_gen_subs();
1009 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1010 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1011 pars.ussd.sid := f_rnd_octstring(4);
1012 f_vty_subscr_create(VTY, pars.sub);
1013 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_imsi), pars);
1014 vc_conn.done;
1015 }
1016}
1017
1018/* Test for USSD request to internal own-msisdn IUSE. */
1019private function f_TC_mo_ussd_iuse_msisdn() runs on HLR_ConnHdlr {
1020 var GSUP_PDU res;
1021 var charstring resp_str;
1022 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1023 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1024 ussd_string := "*#100#");
1025 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1026 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1027 resp_str := "Your extension is " & hex2str(g_pars.sub.msisdn);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001028 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1029 OSMO_GSUP_SESSION_STATE_END,
1030 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1031 f_encGSM7bit(resp_str)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001032}
1033testcase TC_mo_ussd_iuse_msisdn() runs on test_CT {
1034 var HlrSubscriberList sl;
1035 var HLR_ConnHdlr vc_conn;
1036
1037 f_init(false);
1038 sl := f_gen_subs();
1039 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1040 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1041 pars.ussd.sid := f_rnd_octstring(4);
1042 f_vty_subscr_create(VTY, pars.sub);
1043 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_msisdn), pars);
1044 vc_conn.done;
1045 }
1046}
1047
1048/* Test routing of USSD to EUSE by a specific route */
1049private function f_TC_mo_ussd_100() runs on HLR_ConnHdlr {
1050 var GSUP_PDU res;
1051 /* invoke / invoke id 1 / processUSS-req */
1052 //var octetstring ss := 'a11202010102013b300a04010f0405aa180c3602'O;
1053 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1054 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1055 ussd_string := "*100#");
1056 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1057 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001058 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1059 OSMO_GSUP_SESSION_STATE_END,
1060 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1061 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001062}
1063testcase TC_mo_ussd_euse() runs on test_CT {
1064 var HlrSubscriberList sl;
1065 var HLR_ConnHdlr vc_conn;
1066
1067 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1068 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
1069
1070 f_init(false);
1071 sl := f_gen_subs();
1072 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1073 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1074 pars.ussd.sid := f_rnd_octstring(4);
1075 f_vty_subscr_create(VTY, pars.sub);
1076 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100), pars);
1077 vc_conn.done;
1078 }
1079
1080 vc_EUSE.stop;
1081}
1082
1083/* Test routing of USSD to EUSE by a specific route, with CONTINUE */
1084private function f_TC_mo_ussd_100_continue() runs on HLR_ConnHdlr {
1085 var GSUP_PDU res;
1086 /* Simulate BEGIN from MS/MSC */
1087 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1088 ussd_string := "*100#");
1089 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1090 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1091 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001092 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1093 OSMO_GSUP_SESSION_STATE_CONTINUE,
1094 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1095 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001096
1097 /* Simulate CONTINUE from MS/MSC */
1098 ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1099 ussd_string := "mahlzeit");
1100 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1101 OSMO_GSUP_SESSION_STATE_CONTINUE, ss)));
1102
1103 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001104 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1105 OSMO_GSUP_SESSION_STATE_END,
1106 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1107 f_encGSM7bit("mahlzeit")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001108}
1109testcase TC_mo_ussd_euse_continue() runs on test_CT {
1110 var HlrSubscriberList sl;
1111 var HLR_ConnHdlr vc_conn;
1112
1113 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1114 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar",
1115 refers(f_ss_echo_continue)));
1116
1117 f_init(false);
1118 sl := f_gen_subs();
1119 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1120 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1121 pars.ussd.sid := f_rnd_octstring(4);
1122 f_vty_subscr_create(VTY, pars.sub);
1123 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100_continue), pars);
1124 vc_conn.done;
1125 }
1126
1127 vc_EUSE.stop;
1128}
1129
1130
1131/* Test routing of USSD to EUSE by default-route */
1132private function f_TC_mo_ussd_999() runs on HLR_ConnHdlr {
1133 var GSUP_PDU res;
1134 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1135 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1136 ussd_string := "*999#");
1137 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1138 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001139 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1140 OSMO_GSUP_SESSION_STATE_END,
1141 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1142 f_encGSM7bit("*999#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001143}
1144testcase TC_mo_ussd_euse_defaultroute() runs on test_CT {
1145 var HlrSubscriberList sl;
1146 var HLR_ConnHdlr vc_conn;
1147
1148 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1149 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
1150
1151 f_init(false);
1152 f_vty_config(VTY, "hlr", "ussd default-route external foobar");
1153
1154 sl := f_gen_subs();
1155 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1156 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1157 pars.ussd.sid := f_rnd_octstring(4);
1158 f_vty_subscr_create(VTY, pars.sub);
1159 vc_conn := f_start_handler(refers(f_TC_mo_ussd_999), pars);
1160 vc_conn.done;
1161 }
1162
1163 f_vty_config(VTY, "hlr", "no ussd default-route");
1164 vc_EUSE.stop;
1165}
1166
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001167/**
1168 * Test "Structured" Supplementary Services
1169 *
1170 * NOTE: at the moment, OsmoHLR doesn't support "structured" SS,
1171 * so such requests are being rejected (actually ReturnError
1172 * with GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED).
1173 */
1174private function f_TC_mo_sss_reject() runs on HLR_ConnHdlr {
1175 var SS_FacilityInformation ss_req;
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001176 var GSUP_PDU res;
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001177
1178 /* Prepare '*#21#' SS request */
1179 ss_req := valueof(ts_SS_FACILITY_INVOKE(
1180 invoke_id := 0,
1181 op_code := SS_OP_CODE_INTERROGATE_SS,
1182 ss_code := '21'O));
1183
1184 /* Send it towards HLR */
1185 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(
1186 g_pars.sub.imsi,
1187 g_pars.ussd.sid,
1188 OSMO_GSUP_SESSION_STATE_BEGIN,
1189 enc_SS_FacilityInformation(ss_req))));
1190
1191 /* Expect ReturnError with FACILITY_NOT_SUPPORTED */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001192 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1193 OSMO_GSUP_SESSION_STATE_END,
1194 tr_SS_FACILITY_RETURN_ERROR(0, 21));
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001195}
1196testcase TC_mo_sss_reject() runs on test_CT {
1197 var HLR_ConnHdlrPars pars;
1198 var HLR_ConnHdlr vc_conn;
1199 var HlrSubscriber sub;
1200
1201 f_init(false);
1202
1203 /* Create a random subscriber */
1204 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H),
1205 '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
1206 pars := valueof(t_Pars_sub(sub));
1207 pars.ussd.sid := f_rnd_octstring(4);
1208
1209 f_vty_subscr_create(VTY, sub);
1210 vc_conn := f_start_handler(refers(f_TC_mo_sss_reject), pars);
1211 vc_conn.done;
1212 f_vty_subscr_delete(VTY, sub);
1213}
1214
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001215
1216/* TODO USSD:
1217 * MO USSD for IMSI of non-existant subscriber
1218 * MT USSD from EUSE
1219 * timeout cases
1220 */
1221
Oliver Smith936dbe62019-06-04 15:54:17 +02001222
1223/* Test Check IMEI */
1224private function f_TC_gsup_check_imei() runs on HLR_ConnHdlr {
1225 /* store-imei disabled */
1226 f_vty_config(VTY, "hlr", "no store-imei");
1227 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1228 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1229
1230 /* store-imei enabled */
1231 f_vty_config(VTY, "hlr", "store-imei");
1232 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1233 f_vty_subscr_show(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1234}
1235testcase TC_gsup_check_imei() runs on test_CT {
1236 var HlrSubscriberList sl;
1237
1238 f_init(false);
1239 sl := f_gen_subs();
1240 f_start_handler_per_sub(refers(f_TC_gsup_check_imei), sl);
1241
1242 setverdict(pass);
1243}
1244
1245/* Test Check IMEI with invalid IMEI length */
1246private function f_TC_gsup_check_imei_invalid_len() runs on HLR_ConnHdlr {
1247 /* IMEI too long */
1248 f_perform_CHECK_IMEI(g_pars.sub.imsi, '111456789012345F'H, 96 /* Invalid Mandatory Information */);
1249 f_perform_CHECK_IMEI(g_pars.sub.imsi, '2224567890123456'H, 96 /* Invalid Mandatory Information */);
1250
1251 /* IMEI too short */
1252 f_perform_CHECK_IMEI(g_pars.sub.imsi, '3334567890123F'H, 96 /* Invalid Mandatory Information */);
1253 f_perform_CHECK_IMEI(g_pars.sub.imsi, '444456789012'H, 96 /* Invalid Mandatory Information */);
1254 f_perform_CHECK_IMEI(g_pars.sub.imsi, ''H, 96 /* Invalid Mandatory Information */);
1255}
1256testcase TC_gsup_check_imei_invalid_len() runs on test_CT {
1257 var HlrSubscriberList sl;
1258
1259 f_init(false);
1260 sl := f_gen_subs();
1261 f_start_handler_per_sub(refers(f_TC_gsup_check_imei_invalid_len), sl);
1262
1263 setverdict(pass);
1264}
1265
1266/* Test Check IMEI with unknown IMSI */
1267private function f_TC_gsup_check_imei_unknown_imsi() runs on HLR_ConnHdlr {
1268 f_vty_config(VTY, "hlr", "no store-imei");
1269 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1270
1271 /* Check again with store-imei set (different code path) */
1272 f_vty_config(VTY, "hlr", "store-imei");
1273 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1274
1275 setverdict(pass);
1276}
1277testcase TC_gsup_check_imei_unknown_imsi() runs on test_CT {
1278 var hexstring imsi := f_rnd_imsi('26242'H);
1279 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1280 var HLR_ConnHdlr vc_conn;
1281
1282 f_init(false);
1283 vc_conn := f_start_handler(refers(f_TC_gsup_check_imei_unknown_imsi), pars);
1284 vc_conn.done;
1285}
1286
Oliver Smith1b257802019-06-11 09:43:42 +02001287/* Test create-subscriber-on-demand during Check IMEI (OsmoMSC would be set to "check-imei-rqd early") */
1288private function f_TC_subscr_create_on_demand_check_imei_early() runs on HLR_ConnHdlr {
1289 var GSUP_PDU res; /* save various return values to prevent ttcn3 compiler warnings */
1290 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1291
1292 /* Random MSISDN and CS+PS NAM (LU must pass) */
1293 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1294 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1295 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1296 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1297 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1298 res := f_perform_UL(g_pars.sub.imsi, ?);
1299 f_vty_subscr_delete(VTY, g_pars.sub);
1300
1301 /* Random MSISDN and PS NAM (LU must pass) */
1302 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1303 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1304 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1305 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1306 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1307 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1308 res := f_perform_UL(g_pars.sub.imsi, ?);
1309 f_vty_subscr_delete(VTY, g_pars.sub);
1310
1311 /* Random MSISDN and CS NAM (LU must fail) */
1312 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1313 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1314 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1315 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1316 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1317 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1318 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1319 f_vty_subscr_delete(VTY, g_pars.sub);
1320
1321 /* Random MSISDN and no NAM (LU must fail) */
1322 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1323 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1324 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1325 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1326 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1327 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1328 f_vty_subscr_delete(VTY, g_pars.sub);
1329
1330 /* No MSISDN and no NAM (LU must fail) */
1331 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1332 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1333 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1334 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1335 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1336 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1337 f_vty_subscr_delete(VTY, g_pars.sub);
1338
1339 /* No MSISDN and CS+PS NAM (LU must pass) */
1340 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1341 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1342 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1343 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1344 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1345 res := f_perform_UL(g_pars.sub.imsi, omit);
1346 f_vty_subscr_delete(VTY, g_pars.sub);
1347
1348 setverdict(pass);
1349}
1350testcase TC_subscr_create_on_demand_check_imei_early() runs on test_CT {
1351 var hexstring imsi := f_rnd_imsi('26242'H);
1352 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1353 var HLR_ConnHdlr vc_conn;
1354
1355 f_init(false);
1356 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_check_imei_early), pars);
1357 vc_conn.done;
1358}
1359
1360/* Test create-subscriber-on-demand during LU (Location Update) */
1361private function f_TC_subscr_create_on_demand_ul() runs on HLR_ConnHdlr {
1362 var GSUP_PDU res;
1363 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1364
1365 /* Random MSISDN and CS+PS NAM (LU must pass) */
1366 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1367 res := f_perform_UL(g_pars.sub.imsi, ?);
1368 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1369 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1370 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1371 f_vty_subscr_delete(VTY, g_pars.sub);
1372
1373 /* Random MSISDN and PS NAM (LU must pass) */
1374 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1375 res := f_perform_UL(g_pars.sub.imsi, ?);
1376 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1377 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1378 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1379 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1380 f_vty_subscr_delete(VTY, g_pars.sub);
1381
1382 /* Random MSISDN and CS NAM (LU must fail) */
1383 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1384 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1385 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1386 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1387 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1388 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1389 f_vty_subscr_delete(VTY, g_pars.sub);
1390
1391 /* Random MSISDN and no NAM (LU must fail) */
1392 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1393 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1394 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1395 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1396 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1397 f_vty_subscr_delete(VTY, g_pars.sub);
1398
1399 /* No MSISDN and no NAM (LU must fail) */
1400 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1401 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1402 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1403 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1404 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1405 f_vty_subscr_delete(VTY, g_pars.sub);
1406
1407 /* No MSISDN and CS+PS NAM (LU must pass) */
1408 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1409 res := f_perform_UL(g_pars.sub.imsi, omit);
1410 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1411 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1412 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1413 f_vty_subscr_delete(VTY, g_pars.sub);
1414
1415 setverdict(pass);
1416}
1417testcase TC_subscr_create_on_demand_ul() runs on test_CT {
1418 var hexstring imsi := f_rnd_imsi('26242'H);
1419 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1420 var HLR_ConnHdlr vc_conn;
1421
1422 f_init(false);
1423 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_ul), pars);
1424 vc_conn.done;
1425}
1426
1427/* Test create-subscriber-on-demand during SAI (SendAuthInfo) */
1428private function f_TC_subscr_create_on_demand_sai() runs on HLR_ConnHdlr {
1429 var GSUP_PDU res;
1430 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1431
1432 /* HLR creates the subscriber on demand. Then the IMSI is known, but there is no auth data, so the HLR returns
1433 * the "slightly inaccurate cause 'IMSI Unknown' via GSUP". The MS is able to do a LU afterwards. */
1434 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1435 res := f_perform_SAI(g_pars.sub.imsi, 2 /* IMSI Unknown */ );
1436
1437 /* Verify that it was created before the LU */
1438 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1439 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1440 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1441
1442 /* Location update */
1443 res := f_perform_UL(g_pars.sub.imsi, ?);
1444 f_vty_subscr_delete(VTY, g_pars.sub);
1445 setverdict(pass);
1446}
1447testcase TC_subscr_create_on_demand_sai() runs on test_CT {
1448 var hexstring imsi := f_rnd_imsi('26242'H);
1449 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1450 var HLR_ConnHdlr vc_conn;
1451
1452 f_init(false);
1453 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_sai), pars);
1454 vc_conn.done;
1455}
1456
Harald Weltec2c52552018-03-01 21:20:39 +01001457/* TODO:
1458 * UL with ISD error
1459 * UL with ISD timeout
Harald Weltec2c52552018-03-01 21:20:39 +01001460 * LOCATION CANCEL
1461 * AUTH FAIL REP
1462 * DELETE DATA after hlr_subscr_nam() change
1463 * correctness
1464 ** wrong message type
1465 ** wrong length of PDU
1466 ** too short message
1467 ** missing IMSI IE
1468
1469 */
1470
Harald Weltedf327232017-12-28 22:51:51 +01001471control {
1472 execute( TC_gsup_sai_err_invalid_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001473 execute( TC_gsup_sai() );
Harald Welteaf7c3182019-08-22 12:40:22 +02001474 execute( TC_gsup_sai_eps() );
Harald Weltec2c52552018-03-01 21:20:39 +01001475 execute( TC_gsup_ul_unknown_imsi() );
Harald Welte3f662762018-03-02 10:48:20 +01001476 execute( TC_gsup_sai_err_unknown_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001477 execute( TC_gsup_ul() );
1478 execute( TC_vty() );
Harald Welte09b3c502018-03-01 22:42:22 +01001479 execute( TC_vty_msisdn_isd() );
Harald Welte958f8b42018-03-01 23:40:17 +01001480 execute( TC_gsup_purge_cs() );
1481 execute( TC_gsup_purge_ps() );
1482 execute( TC_gsup_purge_unknown() );
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001483
1484 execute( TC_mo_ussd_unknown() );
1485 execute( TC_mo_ussd_euse_disc() );
1486 execute( TC_mo_ussd_iuse_imsi() );
1487 execute( TC_mo_ussd_iuse_msisdn() );
1488 execute( TC_mo_ussd_euse() );
1489 execute( TC_mo_ussd_euse_continue() );
1490 execute( TC_mo_ussd_euse_defaultroute() );
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001491
1492 /* "Structured" Supplementary Services */
1493 execute( TC_mo_sss_reject() );
Oliver Smith936dbe62019-06-04 15:54:17 +02001494
1495 execute( TC_gsup_check_imei() );
1496 execute( TC_gsup_check_imei_invalid_len() );
1497 execute( TC_gsup_check_imei_unknown_imsi() );
Oliver Smith1b257802019-06-11 09:43:42 +02001498 execute( TC_subscr_create_on_demand_check_imei_early() );
1499 execute( TC_subscr_create_on_demand_ul() );
1500 execute( TC_subscr_create_on_demand_sai() );
Harald Weltedf327232017-12-28 22:51:51 +01001501};
1502
1503};