blob: 4caa88e0ef15c2d45d8a0f9659cccf962f8f75b0 [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;
Alexander Couzens92696442020-01-10 07:57:16 +010053 /* how many auth tuples are expected
54 when IE ts_GSUP_IE_NUM_VECTORS_REQ is absent */
55 integer mp_default_num_auth_tuples := 5;
Harald Weltedf327232017-12-28 22:51:51 +010056};
57
Harald Weltec2c52552018-03-01 21:20:39 +010058type record HlrSubscrAud2G {
59 charstring algo,
60 OCT16 ki
61}
62
63type record HlrSubscrAud3G {
64 charstring algo,
65 OCT16 k,
66 OCT16 op,
67 boolean op_is_opc
68}
69
70type record HlrSubscriber {
71 hexstring imsi,
72 hexstring msisdn,
73 HlrSubscrAud2G aud2g optional,
74 HlrSubscrAud3G aud3g optional
75}
76
77type record of HlrSubscriber HlrSubscriberList;
78
Harald Welteed380d12018-06-14 13:42:11 +020079type component HLR_ConnHdlr extends GSUP_ConnHdlr {
80 timer g_Tguard := 10.0;
81 var HLR_ConnHdlrPars g_pars;
82 port TELNETasp_PT VTY;
83}
84
85type record HLR_ConnHdlrPars {
Harald Welte4ea1f8a2018-06-12 09:26:10 +020086 HlrSubscriber sub,
87 HLR_ConnHdlrParsUssd ussd optional
88}
89
90type record HLR_ConnHdlrParsUssd {
91 OCT4 sid
Harald Welteed380d12018-06-14 13:42:11 +020092}
93
94template (value) HLR_ConnHdlrPars t_Pars(hexstring imsi, hexstring msisdn := ''H) := {
95 sub := {
96 imsi := imsi,
97 msisdn := msisdn,
98 aud2g := omit,
99 aud3g := omit
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200100 },
101 ussd := omit
Harald Welteed380d12018-06-14 13:42:11 +0200102}
103
104template (value) HLR_ConnHdlrPars t_Pars_sub(HlrSubscriber sub) := {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200105 sub := sub,
106 ussd := omit
Harald Welteed380d12018-06-14 13:42:11 +0200107}
108
109type function void_fn() runs on HLR_ConnHdlr;
110
111/***********************************************************************
112 * Main Component
113 ***********************************************************************/
114
115function f_init_vty() runs on test_CT {
116 map(self:VTY, system:VTY);
117 f_vty_set_prompts(VTY);
118 f_vty_transceive(VTY, "enable");
119}
120
121private altstep as_Tguard() runs on test_CT {
122 [] g_Tguard.timeout {
123 setverdict(fail, "g_Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200124 mtc.stop;
Harald Welteed380d12018-06-14 13:42:11 +0200125 }
126}
127
128function f_init_gsup(charstring id, boolean legacy) runs on test_CT {
129 id := id & "-GSUP";
130 var GsupOps ops := {
131 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
132 }
133
134 ccm_pars := c_IPA_default_ccm_pars;
135 ccm_pars.name := "Osmocom TTCN-3 GSUP Simulator";
Harald Welte4a3242e2018-06-24 22:28:53 +0200136 ccm_pars.ser_nr := "MSC-00-00-00-00-00-00";
Harald Welteed380d12018-06-14 13:42:11 +0200137
138 vc_IPA := IPA_Emulation_CT.create(id & "-IPA");
139 log("legacy= ", legacy);
140 if (not legacy) {
141 log("in not legacy case 1");
142 vc_GSUP := GSUP_Emulation_CT.create(id);
143 }
144
145 map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
146 if (not legacy) {
147 log("in not legacy case 2");
148 connect(vc_GSUP:GSUP, vc_IPA:IPA_GSUP_PORT);
149 connect(vc_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
150 vc_GSUP.start(GSUP_Emulation.main(ops, id));
151 } else {
152 connect(vc_IPA:IPA_GSUP_PORT, self:GSUP);
153 }
154
155 vc_IPA.start(IPA_Emulation.main_client(mp_hlr_ip, mp_hlr_gsup_port, "", -1, ccm_pars));
156
157 /* wait for incoming connection to GSUP port before proceeding */
158 timer T := 10.0;
159 T.start;
160 alt {
161 [not legacy] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
162 [legacy] GSUP.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP}) { }
163 [] T.timeout {
164 setverdict(fail, "No connection to GSUP Port");
Daniel Willmannafce8662018-07-06 23:11:32 +0200165 mtc.stop;
Harald Welteed380d12018-06-14 13:42:11 +0200166 }
167 }
168}
169
170function f_init(boolean legacy := true) runs on test_CT {
171
172 /* activate default guard timer to ensure all tests eventually terminate */
173 g_Tguard.start;
174 activate(as_Tguard());
175
176 f_init_gsup("HLR_Test", legacy);
177 f_init_vty();
178
179 f_ipa_ctrl_start(mp_hlr_ip, mp_hlr_ctrl_port);
180}
181
182function f_start_handler(void_fn fn, HLR_ConnHdlrPars pars) runs on test_CT return HLR_ConnHdlr {
183 var HLR_ConnHdlr vc_conn;
184 var charstring id := testcasename();
185
186 vc_conn := HLR_ConnHdlr.create(id);
187 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
188 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
189
190 vc_conn.start(f_handler_init(fn, id, pars));
191 return vc_conn;
192}
193
194private function f_handler_init_vty() runs on HLR_ConnHdlr {
195 map(self:VTY, system:VTY);
196 f_vty_set_prompts(VTY);
197 f_vty_transceive(VTY, "enable");
198}
199
200/* first function inside ConnHdlr component; sets g_pars + starts function */
201function f_handler_init(void_fn fn, charstring id, template (omit) HLR_ConnHdlrPars pars := omit)
202runs on HLR_ConnHdlr
203{
204 if (isvalue(pars)) {
205 g_pars := valueof(pars);
206 f_create_gsup_expect(hex2str(g_pars.sub.imsi));
207 }
208 f_handler_init_vty();
209 fn.apply();
210}
211
212/***********************************************************************
213 * Subscriber creation via VTY
214 ***********************************************************************/
215
Harald Weltec2c52552018-03-01 21:20:39 +0100216template (value) HlrSubscriber t_SubNoAuth(hexstring imsi, hexstring msisdn) := {
217 imsi := imsi,
218 msisdn := msisdn,
219 aud2g := omit,
220 aud3g := omit
221}
222
223const OCT16 c_KI_DEFAULT := '000102030405060708090a0b0c0d0e0f'O;
224const OCT16 c_K_DEFAULT := '101112131415161718191a1b1c1d1e1f'O;
225const OCT16 c_OP_DEFAULT := '202122232425262728292a2b2c2d2e2f'O;
226//const OCT16 c_OPC_DEFAULT := '303132333435363738393a3b3c3d3f'O;
227
228template (value) HlrSubscriber t_Sub2G(hexstring imsi, hexstring msisdn, charstring algo) := {
229 imsi := imsi,
230 msisdn := msisdn,
231 aud2g := {
232 algo := algo,
233 ki := c_KI_DEFAULT
234 },
235 aud3g := omit
236}
237
238template (value) HlrSubscriber t_Sub3G(hexstring imsi, hexstring msisdn, charstring algo, boolean is_opc) := {
239 imsi := imsi,
240 msisdn := msisdn,
241 aud2g := omit,
242 aud3g := {
243 algo := algo,
244 k := c_K_DEFAULT,
245 op := c_OP_DEFAULT,
246 op_is_opc := is_opc
247 }
248}
249
250template (value) HlrSubscriber t_Sub2G3G(hexstring imsi, hexstring msisdn, charstring algo2g, charstring algo3g, boolean is_opc) := {
251 imsi := imsi,
252 msisdn := msisdn,
253 aud2g := {
254 algo := algo2g,
255 ki := c_KI_DEFAULT
256 },
257 aud3g := {
258 algo := algo3g,
259 k := c_K_DEFAULT,
260 op := c_OP_DEFAULT,
261 op_is_opc := is_opc
262 }
263}
264
265/* generate a variety of subscribers with different parameters */
266function f_gen_subs() runs on test_CT return HlrSubscriberList {
267 var HlrSubscriber sub;
268 var HlrSubscriberList sl := {};
269
270 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
271 sl := sl & { sub };
272
273 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v2"));
274 sl := sl & { sub };
275
276 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v3"));
277 sl := sl & { sub };
278
279 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", false));
280 sl := sl & { sub };
281
282 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", true));
283 sl := sl & { sub };
284
285 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
286 "comp128v1", "milenage", false));
287 sl := sl & { sub };
288
289 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
290 "comp128v2", "milenage", false));
291 sl := sl & { sub };
292
293 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
294 "comp128v3", "milenage", false));
295 sl := sl & { sub };
296
297 return sl;
298}
Harald Welteaf7c3182019-08-22 12:40:22 +0200299function f_gen_3G_subs() runs on test_CT return HlrSubscriberList {
300 var HlrSubscriber sub;
301 var HlrSubscriberList sl := {};
302
303 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", false));
304 sl := sl & { sub };
305
306 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", true));
307 sl := sl & { sub };
308
309 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
310 "comp128v1", "milenage", false));
311 sl := sl & { sub };
312
313 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
314 "comp128v2", "milenage", false));
315 sl := sl & { sub };
316
317 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
318 "comp128v3", "milenage", false));
319 sl := sl & { sub };
320
321 return sl;
322}
Harald Weltec2c52552018-03-01 21:20:39 +0100323
Harald Welteed380d12018-06-14 13:42:11 +0200324function f_vty_transceive_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
325 var charstring ret := f_vty_transceive_ret(pt, cmd);
326 if (not match(ret, exp_ret)) {
327 setverdict(fail, "Non-matching VTY response: ", ret);
Daniel Willmannafce8662018-07-06 23:11:32 +0200328 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100329 }
330}
331
Oliver Smith141620d2019-06-07 12:27:33 +0200332function f_vty_transceive_nomatch(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
333 var charstring ret := f_vty_transceive_ret(pt, cmd);
334 if (match(ret, exp_ret)) {
335 setverdict(fail, "Matching VTY response: ", ret, ", should *not* have matched: ", exp_ret);
336 mtc.stop;
337 }
338}
339
Harald Welte70296062018-03-01 22:42:03 +0100340private template (value) charstring t_subscr_prefix(hexstring imsi) :=
341 "subscriber imsi " & hex2str(imsi) & " ";
342
Harald Weltec2c52552018-03-01 21:20:39 +0100343/* create a given subscriber using the VTY */
Harald Welteed380d12018-06-14 13:42:11 +0200344function f_vty_subscr_create(TELNETasp_PT VTY, HlrSubscriber sub) {
Harald Welte70296062018-03-01 22:42:03 +0100345 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100346 f_vty_transceive_match(VTY, prefix & "create", pattern "% Created subscriber *");
347 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(sub.msisdn),
348 pattern "% Updated subscriber *");
349 if (ispresent(sub.aud2g)) {
350 f_vty_transceive_match(VTY, prefix & "update aud2g " & sub.aud2g.algo &
351 " ki " & oct2str(sub.aud2g.ki),
352 pattern "");
353 } else {
354 f_vty_transceive_match(VTY, prefix & "update aud2g none", pattern "");
355 }
356
357 if (ispresent(sub.aud3g)) {
358 var charstring op_mode := "op";
359 if (sub.aud3g.op_is_opc) {
360 op_mode := "opc";
361 }
362 f_vty_transceive_match(VTY, prefix & "update aud3g " & sub.aud3g.algo &
363 " k " & oct2str(sub.aud3g.k) & " " & op_mode & " " &
364 oct2str(sub.aud3g.op), pattern "");
365 } else {
366 f_vty_transceive_match(VTY, prefix & "update aud3g none", pattern "");
367 }
368}
369
Harald Welteed380d12018-06-14 13:42:11 +0200370function f_vty_subscr_update_msisdn(TELNETasp_PT VTY, HlrSubscriber sub, hexstring new_msisdn) {
Harald Welte09b3c502018-03-01 22:42:22 +0100371 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
372 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(new_msisdn),
373 pattern "% Updated subscriber *");
374}
375
Harald Weltec2c52552018-03-01 21:20:39 +0100376/* perform 'delete' on subscriber */
Harald Welteed380d12018-06-14 13:42:11 +0200377function f_vty_subscr_delete(TELNETasp_PT VTY, HlrSubscriber sub) {
Harald Welte70296062018-03-01 22:42:03 +0100378 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100379 f_vty_transceive_match(VTY, prefix & "delete",
380 pattern "% Deleted subscriber for IMSI *");
381}
382
383/* perform 'show' on subscriber; match result with pattern 'exp' */
Harald Welteed380d12018-06-14 13:42:11 +0200384function f_vty_subscr_show(TELNETasp_PT VTY, HlrSubscriber sub, template charstring exp) {
Harald Welte70296062018-03-01 22:42:03 +0100385 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100386 f_vty_transceive_match(VTY, prefix & "show", exp);
387}
388
Oliver Smith141620d2019-06-07 12:27:33 +0200389/* perform 'show' on subscriber; result must not match with pattern 'exp' */
390function f_vty_subscr_show_nomatch(TELNETasp_PT VTY, HlrSubscriber sub, template charstring exp) {
391 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
392 f_vty_transceive_nomatch(VTY, prefix & "show", exp);
393}
Harald Weltec2c52552018-03-01 21:20:39 +0100394
Harald Welteed380d12018-06-14 13:42:11 +0200395/***********************************************************************
396 * Helper functions for ConnHdlr
397 ***********************************************************************/
398
Harald Weltec2c52552018-03-01 21:20:39 +0100399/* perform SendAuthInfo for given imsi, return the GSUP response/error */
Harald Welteaf7c3182019-08-22 12:40:22 +0200400function f_perform_SAI(hexstring imsi, template (omit) integer exp_err_cause := omit,
Alexander Couzens92696442020-01-10 07:57:16 +0100401 boolean is_eps := false, template (omit) integer num_auth_tuple := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200402runs on HLR_ConnHdlr return GSUP_PDU {
Alexander Couzens92696442020-01-10 07:57:16 +0100403 var template GSUP_PDU sai_msg;
Harald Weltec2c52552018-03-01 21:20:39 +0100404 var GSUP_PDU ret;
405 timer T := 3.0;
406 var boolean exp_fail := false;
407 if (not istemplatekind(exp_err_cause, "omit")) {
408 exp_fail := true;
409 }
410
Harald Welteaf7c3182019-08-22 12:40:22 +0200411 if (is_eps) {
Alexander Couzens92696442020-01-10 07:57:16 +0100412 sai_msg := ts_GSUP_SAI_REQ_EPS(imsi);
Harald Welteaf7c3182019-08-22 12:40:22 +0200413 } else {
Alexander Couzens92696442020-01-10 07:57:16 +0100414 sai_msg := ts_GSUP_SAI_REQ(imsi);
Harald Welteaf7c3182019-08-22 12:40:22 +0200415 }
Alexander Couzens92696442020-01-10 07:57:16 +0100416 if (not istemplatekind(num_auth_tuple, "omit")) {
417 sai_msg.ies := valueof(sai_msg.ies) & {
418 valueof(ts_GSUP_IE_NUM_VECTORS_REQ(int2oct(valueof(num_auth_tuple), 1)))
419 };
420 }
421 GSUP.send(sai_msg);
422
Harald Weltec2c52552018-03-01 21:20:39 +0100423 T.start;
424 alt {
425 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, exp_err_cause)) -> value ret {
426 setverdict(pass);
427 }
428 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
429 setverdict(fail, "Unexpected SAI ERROR Cause");
430 }
431 [exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
432 setverdict(fail, "Unexpected SAI.res for unknown IMSI");
433 }
434 [not exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
435 setverdict(fail, "Unexpected SAI ERROR");
436 }
437 [not exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
438 setverdict(pass);
439 }
440 [] GSUP.receive { repeat; }
441 [] T.timeout {
442 setverdict(fail, "Timeout waiting for SAI response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200443 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100444 }
445 }
446 return ret;
447}
448
449function f_perform_UL(hexstring imsi, template hexstring msisdn,
450 template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200451runs on HLR_ConnHdlr return GSUP_PDU {
Harald Weltec2c52552018-03-01 21:20:39 +0100452 var GSUP_PDU ret;
453 timer T := 3.0;
454 var boolean exp_fail := false;
455 var boolean isd_done := false;
456 if (not istemplatekind(exp_err_cause, "omit")) {
457 exp_fail := true;
458 }
459
460 GSUP.send(valueof(ts_GSUP_UL_REQ(imsi)));
461 T.start;
462 alt {
463 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, exp_err_cause)) -> value ret {
464 setverdict(pass);
465 }
466 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
467 setverdict(fail, "Unexpected UL ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100468 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100469 }
470 [exp_fail] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
471 setverdict(fail, "Unexpected UL.res for unknown IMSI");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100472 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100473 }
474 [exp_fail] GSUP.receive(tr_GSUP_ISD_REQ(imsi)) -> value ret {
475 setverdict(fail, "Unexpected ISD.req in error case");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100476 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100477 }
478 [not exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
479 setverdict(fail, "Unexpected UL ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100480 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100481 }
482 [not exp_fail and not isd_done] GSUP.receive(tr_GSUP_ISD_REQ(imsi, msisdn)) -> value ret {
483 GSUP.send(ts_GSUP_ISD_RES(imsi));
484 isd_done := true;
Harald Welte8f0c9332018-03-01 23:38:40 +0100485 repeat;
Harald Weltec2c52552018-03-01 21:20:39 +0100486 }
487 [not exp_fail and isd_done] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
488 setverdict(pass);
489 }
490 [] GSUP.receive { repeat; }
491 [] T.timeout {
492 setverdict(fail, "Timeout waiting for UL response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200493 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100494 }
495 }
496 return ret;
497}
498
Harald Welte958f8b42018-03-01 23:40:17 +0100499/* perform PurgeMS for given imsi, return the GSUP response/error */
500function f_perform_PURGE(hexstring imsi, GSUP_CnDomain cn_dom,
501 template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200502runs on HLR_ConnHdlr return GSUP_PDU {
Harald Welte958f8b42018-03-01 23:40:17 +0100503 var GSUP_PDU ret;
504 timer T := 3.0;
505 var boolean exp_fail := false;
506 if (not istemplatekind(exp_err_cause, "omit")) {
507 exp_fail := true;
508 }
509
510 GSUP.send(valueof(ts_GSUP_PURGE_MS_REQ(imsi, cn_dom)));
511 T.start;
512 alt {
513 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, exp_err_cause)) -> value ret {
514 setverdict(pass);
515 }
516 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
517 setverdict(fail, "Unexpected PURGE ERROR Cause");
518 }
519 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
520 setverdict(fail, "Unexpected PURGE.res for unknown IMSI");
521 }
522 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
523 setverdict(fail, "Unexpected PURGE ERROR");
524 }
525 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
526 setverdict(pass);
527 }
528 [] GSUP.receive { repeat; }
529 [] T.timeout {
530 setverdict(fail, "Timeout waiting for PURGE response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200531 mtc.stop;
Harald Welte958f8b42018-03-01 23:40:17 +0100532 }
533 }
534 return ret;
535}
536
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200537function f_SS_xceive(hexstring imsi, OCT4 sid, GSUP_SessionState state, octetstring ss,
538 template (omit) integer exp_err_cause := omit)
539runs on HLR_ConnHdlr return GSUP_PDU {
540 var GSUP_PDU ret;
541 timer T := 3.0;
542 var boolean exp_fail := false;
543 if (not istemplatekind(exp_err_cause, "omit")) {
544 exp_fail := true;
545 }
546
547 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(imsi, sid, state, ss)));
548 T.start;
549 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700550 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, exp_err_cause)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200551 setverdict(pass);
552 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700553 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200554 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
555 }
556 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
557 setverdict(fail, "Unexpected PROC_SS.res for unknown IMSI");
558 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700559 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200560 setverdict(fail, "Unexpected PROC_SS ERROR");
561 }
562 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
563 setverdict(pass);
564 }
565 [] GSUP.receive { repeat; }
566 [] T.timeout {
567 setverdict(fail, "Timeout waiting for PROC_SS response");
568 self.stop;
569 }
570 }
571 return ret;
572}
573
574private function f_SS_expect(hexstring imsi, OCT4 sid, GSUP_SessionState state,
575 template SS_FacilityInformation facility := *)
576runs on HLR_ConnHdlr return GSUP_PDU {
577 var GSUP_PDU ret;
578 timer T := 3.0;
579 var boolean exp_ss := true;
580 if (istemplatekind(facility, "omit")) {
581 exp_ss := false;
582 }
583 T.start;
584 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700585 [] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200586 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100587 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200588 }
589 [not exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
590 setverdict(pass);
591 }
592 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
593 setverdict(fail, "Unexpected PROC_SS.res without SS IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100594 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200595 }
596/*
597 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, decmatch facility)) -> value ret {
598 setverdict(pass);
599 }
600*/
601
602 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, ?)) -> value ret {
603 var GSUP_IeValue ss_ie;
604 f_gsup_find_ie(ret, OSMO_GSUP_SS_INFO_IE, ss_ie);
605 var SS_FacilityInformation dec_fac := dec_SS_FacilityInformation(ss_ie.ss_info);
606 log("pattern: ", facility);
607 if (match(dec_fac, facility)) {
608 setverdict(pass);
609 } else {
610 setverdict(fail, "Unexpected PROC_SS.res with non-matching facility IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100611 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200612 }
613 }
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100614 [] GSUP.receive {
615 setverdict(fail, "Unexpected GSUP");
616 mtc.stop;
617 }
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200618 [] T.timeout {
619 setverdict(fail, "Timeout waiting for PROC_SS response");
620 self.stop;
621 }
622 }
623
624 return ret;
625}
626
Oliver Smith936dbe62019-06-04 15:54:17 +0200627function f_perform_CHECK_IMEI(hexstring imsi, hexstring imei,
628 template (omit) integer exp_err_cause := omit,
629 template (omit) GSUP_IMEIResult result := omit)
630runs on HLR_ConnHdlr {
631 var GSUP_PDU pdu;
632 timer T := 3.0;
633 var boolean exp_fail := false;
634 if (not istemplatekind(exp_err_cause, "omit")) {
635 exp_fail := true;
636 }
637
638 GSUP.send(valueof(ts_GSUP_CHECK_IMEI_REQ(imsi, imei)));
639 T.start;
640 alt {
641 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, exp_err_cause)) -> value pdu {
642 setverdict(pass);
643 }
644 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?)) -> value pdu {
645 setverdict(fail, "Unexpected CHECK IMEI ERROR Cause: ", pdu);
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100646 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200647 }
648 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?)) -> value pdu {
649 setverdict(fail, "Unexpected CHECK IMEI RES instead of ERR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100650 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200651 }
652 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?)) -> value pdu {
653 setverdict(fail, "Unexpected CHECK IMEI ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100654 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200655 }
656 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, result)) -> value pdu {
657 setverdict(pass);
658 }
659 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?)) -> value pdu {
660 setverdict(fail, "Unexpected CHECK IMEI RES");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100661 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200662 }
663 [] GSUP.receive { repeat; }
664 [] T.timeout {
665 setverdict(fail, "Timeout waiting for CHECK IMEI response");
666 mtc.stop;
667 }
668 }
669}
670
671
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200672
Harald Welte958f8b42018-03-01 23:40:17 +0100673
Harald Welteed380d12018-06-14 13:42:11 +0200674/***********************************************************************
675 * Testcases
676 ***********************************************************************/
677
678/* 23.003 Section 2.2 clearly states that an IMSI with less
679 * than 5 digits is impossible. Even 5 digits is still questionable */
680private function f_TC_gsup_sai_err_invalid_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100681 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200682 res := f_perform_SAI(g_pars.sub.imsi, 96); /* Invalid Mandatory information */
683 setverdict(pass);
684}
685testcase TC_gsup_sai_err_invalid_imsi() runs on test_CT {
686 var HLR_ConnHdlr vc_conn;
687 var HLR_ConnHdlrPars pars := valueof(t_Pars('0123'H));
688 f_init(false);
689 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_invalid_imsi), pars);
690 vc_conn.done;
691}
Harald Weltec2c52552018-03-01 21:20:39 +0100692
Harald Weltec2c52552018-03-01 21:20:39 +0100693
Harald Welteed380d12018-06-14 13:42:11 +0200694private function f_TC_gsup_sai_err_unknown_imsi() runs on HLR_ConnHdlr {
695 var GSUP_PDU res;
696 res := f_perform_SAI(g_pars.sub.imsi, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100697 setverdict(pass);
698}
699
Harald Welte3f662762018-03-02 10:48:20 +0100700testcase TC_gsup_sai_err_unknown_imsi() runs on test_CT {
Harald Welteed380d12018-06-14 13:42:11 +0200701 var HLR_ConnHdlr vc_conn;
702 var HLR_ConnHdlrPars pars := valueof(t_Pars(f_rnd_imsi('26242'H)));
703 f_init(false);
704 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_unknown_imsi), pars);
705 vc_conn.done;
Harald Welte3f662762018-03-02 10:48:20 +0100706}
707
Harald Welteed380d12018-06-14 13:42:11 +0200708function f_start_handler_per_sub(void_fn fn, HlrSubscriberList sl) runs on test_CT {
709 for (var integer i := 0; i < sizeof(sl); i := i+1) {
710 var HlrSubscriber sub := sl[i];
711 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sub));
712 var HLR_ConnHdlr vc_conn;
713
714 f_vty_subscr_create(VTY, sub);
715 vc_conn := f_start_handler(fn, pars);
716 vc_conn.done;
717 f_vty_subscr_delete(VTY, sub);
718 }
719}
Harald Welte3f662762018-03-02 10:48:20 +0100720
Harald Weltec2c52552018-03-01 21:20:39 +0100721/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
Harald Welteed380d12018-06-14 13:42:11 +0200722private function f_TC_gsup_sai() runs on HLR_ConnHdlr {
723 var GSUP_PDU res;
724 res := f_perform_SAI(g_pars.sub.imsi);
Harald Welte4b612042019-12-03 20:08:57 +0100725 if (ispresent(g_pars.sub.aud3g)) {
726 f_ensure_amf_separation_bit(res, '0'B);
727 }
Alexander Couzens92696442020-01-10 07:57:16 +0100728
729 f_count_auth_tuples(res, mp_default_num_auth_tuples);
Harald Welteed380d12018-06-14 13:42:11 +0200730 setverdict(pass);
731}
Harald Weltec2c52552018-03-01 21:20:39 +0100732testcase TC_gsup_sai() runs on test_CT {
733 var HlrSubscriberList sl;
734 var GSUP_PDU res;
735
Harald Welteed380d12018-06-14 13:42:11 +0200736 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100737
738 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200739 f_start_handler_per_sub(refers(f_TC_gsup_sai), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100740
741 setverdict(pass);
742}
743
Alexander Couzens92696442020-01-10 07:57:16 +0100744/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
745private function f_TC_gsup_sai_num_auth_vectors() runs on HLR_ConnHdlr {
746 var GSUP_PDU res;
747 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 1);
748 f_count_auth_tuples(res, 1);
749 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 4);
750 f_count_auth_tuples(res, 4);
751 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 5);
752 f_count_auth_tuples(res, 5);
753 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 254);
754 f_count_auth_tuples(res, 5);
755 setverdict(pass);
756}
757testcase TC_gsup_sai_num_auth_vectors() runs on test_CT {
758 var HlrSubscriberList sl;
759 var GSUP_PDU res;
760
761 f_init(false);
762
763 sl := f_gen_subs();
764 f_start_handler_per_sub(refers(f_TC_gsup_sai_num_auth_vectors), sl);
765
766 setverdict(pass);
767}
768
Harald Welteaf7c3182019-08-22 12:40:22 +0200769private function f_ensure_amf_separation_bit(GSUP_PDU res, BIT1 sep_bit)
770{
771 for (var integer i := 0; i < lengthof(res.ies); i := i+1) {
772 var GSUP_IE tuple := res.ies[i];
773 if (tuple.tag != OSMO_GSUP_AUTH_TUPLE_IE) {
774 continue;
775 }
776 var GSUP_IeValue autn;
777 if (f_gsup_find_nested_ie(tuple.val.auth_tuple, OSMO_GSUP_AUTN_IE, autn) == false) {
778 setverdict(fail, "Couldn't find AUTN IE in tuple ", i);
779 mtc.stop;
780 }
781 var bitstring amf := oct2bit(substr(autn.autn, 6, 2));
782 if (amf[0] != sep_bit) {
783 setverdict(fail, "AMF bit 0 (separation bit) must be ", sep_bit," but was not");
784 mtc.stop;
785 }
786 }
787}
788
Alexander Couzens92696442020-01-10 07:57:16 +0100789private function f_count_auth_tuples(GSUP_PDU res, template (omit) integer expected_auth_tuples := omit)
790{
791 var integer auth_tuples := 0;
792 for (var integer i := 0; i < lengthof(res.ies); i := i+1) {
793 var GSUP_IE tuple := res.ies[i];
794 if (tuple.tag == OSMO_GSUP_AUTH_TUPLE_IE) {
795 auth_tuples := auth_tuples + 1;
796 }
797 }
798
799 if ((not istemplatekind(expected_auth_tuples, "omit")) and
800 not match(auth_tuples, valueof(expected_auth_tuples))) {
801 setverdict(fail,
802 "Did not received expected number of auth tuples. Expected ",
803 mp_default_num_auth_tuples,
804 " but received ", auth_tuples);
805 }
806}
807
Harald Welteaf7c3182019-08-22 12:40:22 +0200808/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
809private function f_TC_gsup_sai_eps() runs on HLR_ConnHdlr {
810 var GSUP_PDU res;
811 res := f_perform_SAI(g_pars.sub.imsi, is_eps := true);
812 f_ensure_amf_separation_bit(res, '1'B);
813
814 /* TODO: match if tuple[s] matches expectation */
815 setverdict(pass);
816}
817testcase TC_gsup_sai_eps() runs on test_CT {
818 var HlrSubscriberList sl;
819 var GSUP_PDU res;
820
821 f_init(false);
822
823 sl := f_gen_3G_subs();
824 f_start_handler_per_sub(refers(f_TC_gsup_sai_eps), sl);
825
826 setverdict(pass);
827}
828
829
Harald Weltec2c52552018-03-01 21:20:39 +0100830/* test UL for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200831private function f_TC_ul_unknown_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100832 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200833 res := f_perform_UL(g_pars.sub.imsi, ?, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100834 setverdict(pass);
835}
Harald Welteed380d12018-06-14 13:42:11 +0200836testcase TC_gsup_ul_unknown_imsi() runs on test_CT {
837 var hexstring imsi := f_rnd_imsi('26242'H);
838 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
839 var HLR_ConnHdlr vc_conn;
Harald Weltec2c52552018-03-01 21:20:39 +0100840
Harald Welteed380d12018-06-14 13:42:11 +0200841 f_init(false);
842 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
843 vc_conn.done;
844}
845
846/* test UL for a number of different subscriber cases (algo, 2g/3g, ...) */
847private function f_TC_gsup_ul() runs on HLR_ConnHdlr {
848 var GSUP_PDU res;
849 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
850 setverdict(pass);
851}
Harald Weltec2c52552018-03-01 21:20:39 +0100852testcase TC_gsup_ul() runs on test_CT {
853 var HlrSubscriberList sl;
854 var GSUP_PDU res;
855
Harald Welteed380d12018-06-14 13:42:11 +0200856 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100857 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200858 f_start_handler_per_sub(refers(f_TC_gsup_ul), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100859
860 setverdict(pass);
861}
862
863/* Test only the VTY commands */
864testcase TC_vty() runs on test_CT {
865 var HlrSubscriber sub;
866
867 f_init();
868
869 /* we're not using f_gen_subs() here as the expect pattern for the 'show' are different
870 * from case to case */
871 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
Harald Welteed380d12018-06-14 13:42:11 +0200872 f_vty_subscr_create(VTY, sub);
873 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*");
874 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100875
876 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
877 "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +0200878 f_vty_subscr_create(VTY, sub);
879 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *3G auth: MILENAGE*");
880 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100881
882 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
883 "comp128v1", "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +0200884 f_vty_subscr_create(VTY, sub);
885 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*3G auth: MILENAGE*");
886 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100887
888 setverdict(pass);
889}
890
Harald Welte09b3c502018-03-01 22:42:22 +0100891/* VTY changes to MSISDN should result in ISD to current VLR */
Harald Welteed380d12018-06-14 13:42:11 +0200892private function f_TC_vty_msisdn_isd() runs on HLR_ConnHdlr {
Harald Welte09b3c502018-03-01 22:42:22 +0100893 var hexstring new_msisdn;
894 var GSUP_PDU res;
895 timer T := 5.0;
896
Harald Welte09b3c502018-03-01 22:42:22 +0100897 /* Create Subscriber */
Harald Welteed380d12018-06-14 13:42:11 +0200898 f_vty_subscr_create(VTY, g_pars.sub);
Harald Welte09b3c502018-03-01 22:42:22 +0100899
900 /* Perform UpdateLocation (VLR now known to HLR) */
Harald Welteed380d12018-06-14 13:42:11 +0200901 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +0100902
903 /* Then change IMSI via VTY */
904 new_msisdn := '49161'H & f_rnd_hexstring(7, 9);
Harald Welteed380d12018-06-14 13:42:11 +0200905 f_vty_subscr_update_msisdn(VTY, g_pars.sub, new_msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +0100906 /* And expect InsertSubscriberData as result */
907 T.start;
908 alt {
Harald Welteed380d12018-06-14 13:42:11 +0200909 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, new_msisdn)) {
910 GSUP.send(ts_GSUP_ISD_RES(g_pars.sub.imsi));
911 g_pars.sub.msisdn := new_msisdn;
Harald Welte09b3c502018-03-01 22:42:22 +0100912 setverdict(pass);
913 }
Harald Welteed380d12018-06-14 13:42:11 +0200914 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, g_pars.sub.msisdn)) {
Stefan Sperling7c096872018-04-09 11:24:22 +0200915 log("received ISD req with old MSISDN");
916 setverdict(fail);
917 }
Harald Welte09b3c502018-03-01 22:42:22 +0100918 [] GSUP.receive { repeat; }
919 [] T.timeout {
920 setverdict(fail, "Timeout waiting for ISD.req");
921 }
922 }
923}
Harald Welteed380d12018-06-14 13:42:11 +0200924testcase TC_vty_msisdn_isd() runs on test_CT {
925 var HlrSubscriber sub;
926 var HLR_ConnHdlr vc_conn;
927
928 f_init(false);
929
930 /* Create Subscriber */
931 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
932
933 vc_conn := f_start_handler(refers(f_TC_vty_msisdn_isd), valueof(t_Pars_sub(sub)));
934 vc_conn.done;
935}
Harald Welte09b3c502018-03-01 22:42:22 +0100936
Harald Welte958f8b42018-03-01 23:40:17 +0100937/* Test PURGE MS for CS services */
Harald Welteed380d12018-06-14 13:42:11 +0200938private function f_TC_gsup_purge_cs() runs on HLR_ConnHdlr {
939 var GSUP_PDU res;
940 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
941 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS);
942}
Harald Welte958f8b42018-03-01 23:40:17 +0100943testcase TC_gsup_purge_cs() runs on test_CT {
944 var HlrSubscriberList sl;
945 var GSUP_PDU res;
946
Harald Welteed380d12018-06-14 13:42:11 +0200947 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +0100948 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200949 f_start_handler_per_sub(refers(f_TC_gsup_purge_cs), sl);
Harald Welte958f8b42018-03-01 23:40:17 +0100950
951 setverdict(pass);
952}
953
954/* Test PURGE MS for PS services */
Harald Welteed380d12018-06-14 13:42:11 +0200955private function f_TC_gsup_purge_ps() runs on HLR_ConnHdlr {
956 var GSUP_PDU res;
957 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
958 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_PS);
959}
Harald Welte958f8b42018-03-01 23:40:17 +0100960testcase TC_gsup_purge_ps() runs on test_CT {
961 var HlrSubscriberList sl;
Harald Welte958f8b42018-03-01 23:40:17 +0100962
Harald Welteed380d12018-06-14 13:42:11 +0200963 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +0100964 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200965 f_start_handler_per_sub(refers(f_TC_gsup_purge_ps), sl);
Harald Welte958f8b42018-03-01 23:40:17 +0100966
967 setverdict(pass);
968}
969
970/* Test PURGEG MS procedure for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200971
972private function f_TC_gsup_purge_unknown() runs on HLR_ConnHdlr {
973 var GSUP_PDU res;
974 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS, 2);
975}
Harald Welte958f8b42018-03-01 23:40:17 +0100976testcase TC_gsup_purge_unknown() runs on test_CT {
977 var hexstring imsi := '2345743413463'H;
Harald Welteed380d12018-06-14 13:42:11 +0200978 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
979 var HLR_ConnHdlr vc_conn;
Harald Welte958f8b42018-03-01 23:40:17 +0100980
Harald Welteed380d12018-06-14 13:42:11 +0200981 f_init(false);
982 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
983 vc_conn.done;
Harald Welte958f8b42018-03-01 23:40:17 +0100984
985 setverdict(pass);
986}
987
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200988import from HLR_EUSE all;
989
990/* Test for USSD request to undefined/unrouted short-code. Expect ss-NotAvailable(18) */
991private function f_TC_mo_ussd_unknown() runs on HLR_ConnHdlr {
992 var GSUP_PDU res;
993 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
994 op_code := SS_OP_CODE_PROCESS_USS_REQ,
995 ussd_string := "*#200#");
996 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
997 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
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_FACILITY_RETURN_ERROR(1, 18));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001001}
1002testcase TC_mo_ussd_unknown() runs on test_CT {
1003 var HlrSubscriberList sl;
1004 var HLR_ConnHdlr vc_conn;
1005
1006 f_init(false);
1007 sl := f_gen_subs();
1008 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1009 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1010 pars.ussd.sid := f_rnd_octstring(4);
1011 f_vty_subscr_create(VTY, pars.sub);
1012 vc_conn := f_start_handler(refers(f_TC_mo_ussd_unknown), pars);
1013 vc_conn.done;
1014 }
1015}
1016
1017/* Test for USSD request to currently disconnected EUSE. Expect ss-SystemFailure(34) */
1018private function f_TC_mo_ussd_euse_disc() runs on HLR_ConnHdlr {
1019 var GSUP_PDU res;
1020 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1021 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1022 ussd_string := "*100#");
1023 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1024 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001025 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1026 OSMO_GSUP_SESSION_STATE_END,
1027 tr_SS_FACILITY_RETURN_ERROR(1, 34));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001028}
1029testcase TC_mo_ussd_euse_disc() runs on test_CT {
1030 var HlrSubscriberList sl;
1031 var HLR_ConnHdlr vc_conn;
1032
1033 f_init(false);
1034 sl := f_gen_subs();
1035 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1036 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1037 pars.ussd.sid := f_rnd_octstring(4);
1038 f_vty_subscr_create(VTY, pars.sub);
1039 vc_conn := f_start_handler(refers(f_TC_mo_ussd_euse_disc), pars);
1040 vc_conn.done;
1041 }
1042}
1043
1044/* Test for USSD request to internal own-imsi IUSE. */
1045private function f_TC_mo_ussd_iuse_imsi() runs on HLR_ConnHdlr {
1046 var GSUP_PDU res;
1047 var charstring resp_str;
1048 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1049 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1050 ussd_string := "*#101#");
1051 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1052 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1053 resp_str := "Your IMSI is " & hex2str(g_pars.sub.imsi);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001054 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1055 OSMO_GSUP_SESSION_STATE_END,
1056 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1057 f_encGSM7bit(resp_str)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001058}
1059testcase TC_mo_ussd_iuse_imsi() runs on test_CT {
1060 var HlrSubscriberList sl;
1061 var HLR_ConnHdlr vc_conn;
1062
1063 f_init(false);
1064 sl := f_gen_subs();
1065 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1066 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1067 pars.ussd.sid := f_rnd_octstring(4);
1068 f_vty_subscr_create(VTY, pars.sub);
1069 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_imsi), pars);
1070 vc_conn.done;
1071 }
1072}
1073
1074/* Test for USSD request to internal own-msisdn IUSE. */
1075private function f_TC_mo_ussd_iuse_msisdn() runs on HLR_ConnHdlr {
1076 var GSUP_PDU res;
1077 var charstring resp_str;
1078 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1079 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1080 ussd_string := "*#100#");
1081 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1082 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1083 resp_str := "Your extension is " & hex2str(g_pars.sub.msisdn);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001084 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1085 OSMO_GSUP_SESSION_STATE_END,
1086 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1087 f_encGSM7bit(resp_str)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001088}
1089testcase TC_mo_ussd_iuse_msisdn() runs on test_CT {
1090 var HlrSubscriberList sl;
1091 var HLR_ConnHdlr vc_conn;
1092
1093 f_init(false);
1094 sl := f_gen_subs();
1095 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1096 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1097 pars.ussd.sid := f_rnd_octstring(4);
1098 f_vty_subscr_create(VTY, pars.sub);
1099 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_msisdn), pars);
1100 vc_conn.done;
1101 }
1102}
1103
1104/* Test routing of USSD to EUSE by a specific route */
1105private function f_TC_mo_ussd_100() runs on HLR_ConnHdlr {
1106 var GSUP_PDU res;
1107 /* invoke / invoke id 1 / processUSS-req */
1108 //var octetstring ss := 'a11202010102013b300a04010f0405aa180c3602'O;
1109 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1110 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1111 ussd_string := "*100#");
1112 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1113 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001114 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1115 OSMO_GSUP_SESSION_STATE_END,
1116 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1117 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001118}
1119testcase TC_mo_ussd_euse() runs on test_CT {
1120 var HlrSubscriberList sl;
1121 var HLR_ConnHdlr vc_conn;
1122
1123 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1124 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
1125
1126 f_init(false);
1127 sl := f_gen_subs();
1128 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1129 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1130 pars.ussd.sid := f_rnd_octstring(4);
1131 f_vty_subscr_create(VTY, pars.sub);
1132 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100), pars);
1133 vc_conn.done;
1134 }
1135
1136 vc_EUSE.stop;
1137}
1138
1139/* Test routing of USSD to EUSE by a specific route, with CONTINUE */
1140private function f_TC_mo_ussd_100_continue() runs on HLR_ConnHdlr {
1141 var GSUP_PDU res;
1142 /* Simulate BEGIN from MS/MSC */
1143 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1144 ussd_string := "*100#");
1145 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1146 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1147 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001148 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1149 OSMO_GSUP_SESSION_STATE_CONTINUE,
1150 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1151 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001152
1153 /* Simulate CONTINUE from MS/MSC */
1154 ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1155 ussd_string := "mahlzeit");
1156 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1157 OSMO_GSUP_SESSION_STATE_CONTINUE, ss)));
1158
1159 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001160 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1161 OSMO_GSUP_SESSION_STATE_END,
1162 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1163 f_encGSM7bit("mahlzeit")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001164}
1165testcase TC_mo_ussd_euse_continue() runs on test_CT {
1166 var HlrSubscriberList sl;
1167 var HLR_ConnHdlr vc_conn;
1168
1169 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1170 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar",
1171 refers(f_ss_echo_continue)));
1172
1173 f_init(false);
1174 sl := f_gen_subs();
1175 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1176 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1177 pars.ussd.sid := f_rnd_octstring(4);
1178 f_vty_subscr_create(VTY, pars.sub);
1179 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100_continue), pars);
1180 vc_conn.done;
1181 }
1182
1183 vc_EUSE.stop;
1184}
1185
1186
1187/* Test routing of USSD to EUSE by default-route */
1188private function f_TC_mo_ussd_999() runs on HLR_ConnHdlr {
1189 var GSUP_PDU res;
1190 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1191 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1192 ussd_string := "*999#");
1193 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1194 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001195 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1196 OSMO_GSUP_SESSION_STATE_END,
1197 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1198 f_encGSM7bit("*999#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001199}
1200testcase TC_mo_ussd_euse_defaultroute() runs on test_CT {
1201 var HlrSubscriberList sl;
1202 var HLR_ConnHdlr vc_conn;
1203
1204 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1205 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
1206
1207 f_init(false);
1208 f_vty_config(VTY, "hlr", "ussd default-route external foobar");
1209
1210 sl := f_gen_subs();
1211 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1212 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1213 pars.ussd.sid := f_rnd_octstring(4);
1214 f_vty_subscr_create(VTY, pars.sub);
1215 vc_conn := f_start_handler(refers(f_TC_mo_ussd_999), pars);
1216 vc_conn.done;
1217 }
1218
1219 f_vty_config(VTY, "hlr", "no ussd default-route");
1220 vc_EUSE.stop;
1221}
1222
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001223/**
1224 * Test "Structured" Supplementary Services
1225 *
1226 * NOTE: at the moment, OsmoHLR doesn't support "structured" SS,
1227 * so such requests are being rejected (actually ReturnError
1228 * with GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED).
1229 */
1230private function f_TC_mo_sss_reject() runs on HLR_ConnHdlr {
1231 var SS_FacilityInformation ss_req;
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001232 var GSUP_PDU res;
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001233
1234 /* Prepare '*#21#' SS request */
1235 ss_req := valueof(ts_SS_FACILITY_INVOKE(
1236 invoke_id := 0,
1237 op_code := SS_OP_CODE_INTERROGATE_SS,
1238 ss_code := '21'O));
1239
1240 /* Send it towards HLR */
1241 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(
1242 g_pars.sub.imsi,
1243 g_pars.ussd.sid,
1244 OSMO_GSUP_SESSION_STATE_BEGIN,
1245 enc_SS_FacilityInformation(ss_req))));
1246
1247 /* Expect ReturnError with FACILITY_NOT_SUPPORTED */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001248 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1249 OSMO_GSUP_SESSION_STATE_END,
1250 tr_SS_FACILITY_RETURN_ERROR(0, 21));
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001251}
1252testcase TC_mo_sss_reject() runs on test_CT {
1253 var HLR_ConnHdlrPars pars;
1254 var HLR_ConnHdlr vc_conn;
1255 var HlrSubscriber sub;
1256
1257 f_init(false);
1258
1259 /* Create a random subscriber */
1260 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H),
1261 '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
1262 pars := valueof(t_Pars_sub(sub));
1263 pars.ussd.sid := f_rnd_octstring(4);
1264
1265 f_vty_subscr_create(VTY, sub);
1266 vc_conn := f_start_handler(refers(f_TC_mo_sss_reject), pars);
1267 vc_conn.done;
1268 f_vty_subscr_delete(VTY, sub);
1269}
1270
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001271
1272/* TODO USSD:
1273 * MO USSD for IMSI of non-existant subscriber
1274 * MT USSD from EUSE
1275 * timeout cases
1276 */
1277
Oliver Smith936dbe62019-06-04 15:54:17 +02001278
1279/* Test Check IMEI */
1280private function f_TC_gsup_check_imei() runs on HLR_ConnHdlr {
1281 /* store-imei disabled */
1282 f_vty_config(VTY, "hlr", "no store-imei");
1283 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1284 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1285
1286 /* store-imei enabled */
1287 f_vty_config(VTY, "hlr", "store-imei");
1288 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1289 f_vty_subscr_show(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1290}
1291testcase TC_gsup_check_imei() runs on test_CT {
1292 var HlrSubscriberList sl;
1293
1294 f_init(false);
1295 sl := f_gen_subs();
1296 f_start_handler_per_sub(refers(f_TC_gsup_check_imei), sl);
1297
1298 setverdict(pass);
1299}
1300
1301/* Test Check IMEI with invalid IMEI length */
1302private function f_TC_gsup_check_imei_invalid_len() runs on HLR_ConnHdlr {
1303 /* IMEI too long */
1304 f_perform_CHECK_IMEI(g_pars.sub.imsi, '111456789012345F'H, 96 /* Invalid Mandatory Information */);
1305 f_perform_CHECK_IMEI(g_pars.sub.imsi, '2224567890123456'H, 96 /* Invalid Mandatory Information */);
1306
1307 /* IMEI too short */
1308 f_perform_CHECK_IMEI(g_pars.sub.imsi, '3334567890123F'H, 96 /* Invalid Mandatory Information */);
1309 f_perform_CHECK_IMEI(g_pars.sub.imsi, '444456789012'H, 96 /* Invalid Mandatory Information */);
1310 f_perform_CHECK_IMEI(g_pars.sub.imsi, ''H, 96 /* Invalid Mandatory Information */);
1311}
1312testcase TC_gsup_check_imei_invalid_len() runs on test_CT {
1313 var HlrSubscriberList sl;
1314
1315 f_init(false);
1316 sl := f_gen_subs();
1317 f_start_handler_per_sub(refers(f_TC_gsup_check_imei_invalid_len), sl);
1318
1319 setverdict(pass);
1320}
1321
1322/* Test Check IMEI with unknown IMSI */
1323private function f_TC_gsup_check_imei_unknown_imsi() runs on HLR_ConnHdlr {
1324 f_vty_config(VTY, "hlr", "no store-imei");
1325 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1326
1327 /* Check again with store-imei set (different code path) */
1328 f_vty_config(VTY, "hlr", "store-imei");
1329 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1330
1331 setverdict(pass);
1332}
1333testcase TC_gsup_check_imei_unknown_imsi() runs on test_CT {
1334 var hexstring imsi := f_rnd_imsi('26242'H);
1335 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1336 var HLR_ConnHdlr vc_conn;
1337
1338 f_init(false);
1339 vc_conn := f_start_handler(refers(f_TC_gsup_check_imei_unknown_imsi), pars);
1340 vc_conn.done;
1341}
1342
Oliver Smith1b257802019-06-11 09:43:42 +02001343/* Test create-subscriber-on-demand during Check IMEI (OsmoMSC would be set to "check-imei-rqd early") */
1344private function f_TC_subscr_create_on_demand_check_imei_early() runs on HLR_ConnHdlr {
1345 var GSUP_PDU res; /* save various return values to prevent ttcn3 compiler warnings */
1346 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1347
1348 /* Random MSISDN and CS+PS NAM (LU must pass) */
1349 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1350 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1351 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1352 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1353 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1354 res := f_perform_UL(g_pars.sub.imsi, ?);
1355 f_vty_subscr_delete(VTY, g_pars.sub);
1356
1357 /* Random MSISDN and PS NAM (LU must pass) */
1358 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1359 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1360 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1361 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1362 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1363 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1364 res := f_perform_UL(g_pars.sub.imsi, ?);
1365 f_vty_subscr_delete(VTY, g_pars.sub);
1366
1367 /* Random MSISDN and CS NAM (LU must fail) */
1368 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1369 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1370 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1371 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1372 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1373 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1374 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1375 f_vty_subscr_delete(VTY, g_pars.sub);
1376
1377 /* Random MSISDN and no NAM (LU must fail) */
1378 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1379 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1380 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1381 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1382 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1383 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1384 f_vty_subscr_delete(VTY, g_pars.sub);
1385
1386 /* No MSISDN and no NAM (LU must fail) */
1387 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1388 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1389 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1390 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1391 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1392 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1393 f_vty_subscr_delete(VTY, g_pars.sub);
1394
1395 /* No MSISDN and CS+PS NAM (LU must pass) */
1396 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1397 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1398 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1399 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1400 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1401 res := f_perform_UL(g_pars.sub.imsi, omit);
1402 f_vty_subscr_delete(VTY, g_pars.sub);
1403
1404 setverdict(pass);
1405}
1406testcase TC_subscr_create_on_demand_check_imei_early() runs on test_CT {
1407 var hexstring imsi := f_rnd_imsi('26242'H);
1408 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1409 var HLR_ConnHdlr vc_conn;
1410
1411 f_init(false);
1412 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_check_imei_early), pars);
1413 vc_conn.done;
1414}
1415
1416/* Test create-subscriber-on-demand during LU (Location Update) */
1417private function f_TC_subscr_create_on_demand_ul() runs on HLR_ConnHdlr {
1418 var GSUP_PDU res;
1419 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1420
1421 /* Random MSISDN and CS+PS NAM (LU must pass) */
1422 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1423 res := f_perform_UL(g_pars.sub.imsi, ?);
1424 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1425 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1426 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1427 f_vty_subscr_delete(VTY, g_pars.sub);
1428
1429 /* Random MSISDN and PS NAM (LU must pass) */
1430 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1431 res := f_perform_UL(g_pars.sub.imsi, ?);
1432 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1433 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1434 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1435 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1436 f_vty_subscr_delete(VTY, g_pars.sub);
1437
1438 /* Random MSISDN and CS NAM (LU must fail) */
1439 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1440 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1441 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1442 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1443 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1444 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1445 f_vty_subscr_delete(VTY, g_pars.sub);
1446
1447 /* Random MSISDN and no NAM (LU must fail) */
1448 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1449 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1450 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1451 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1452 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1453 f_vty_subscr_delete(VTY, g_pars.sub);
1454
1455 /* No MSISDN and no NAM (LU must fail) */
1456 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1457 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1458 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1459 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1460 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1461 f_vty_subscr_delete(VTY, g_pars.sub);
1462
1463 /* No MSISDN and CS+PS NAM (LU must pass) */
1464 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1465 res := f_perform_UL(g_pars.sub.imsi, omit);
1466 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1467 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1468 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1469 f_vty_subscr_delete(VTY, g_pars.sub);
1470
1471 setverdict(pass);
1472}
1473testcase TC_subscr_create_on_demand_ul() runs on test_CT {
1474 var hexstring imsi := f_rnd_imsi('26242'H);
1475 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1476 var HLR_ConnHdlr vc_conn;
1477
1478 f_init(false);
1479 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_ul), pars);
1480 vc_conn.done;
1481}
1482
1483/* Test create-subscriber-on-demand during SAI (SendAuthInfo) */
1484private function f_TC_subscr_create_on_demand_sai() runs on HLR_ConnHdlr {
1485 var GSUP_PDU res;
1486 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1487
1488 /* HLR creates the subscriber on demand. Then the IMSI is known, but there is no auth data, so the HLR returns
1489 * the "slightly inaccurate cause 'IMSI Unknown' via GSUP". The MS is able to do a LU afterwards. */
1490 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1491 res := f_perform_SAI(g_pars.sub.imsi, 2 /* IMSI Unknown */ );
1492
1493 /* Verify that it was created before the LU */
1494 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1495 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1496 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1497
1498 /* Location update */
1499 res := f_perform_UL(g_pars.sub.imsi, ?);
1500 f_vty_subscr_delete(VTY, g_pars.sub);
1501 setverdict(pass);
1502}
1503testcase TC_subscr_create_on_demand_sai() runs on test_CT {
1504 var hexstring imsi := f_rnd_imsi('26242'H);
1505 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1506 var HLR_ConnHdlr vc_conn;
1507
1508 f_init(false);
1509 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_sai), pars);
1510 vc_conn.done;
1511}
1512
Harald Weltec2c52552018-03-01 21:20:39 +01001513/* TODO:
1514 * UL with ISD error
1515 * UL with ISD timeout
Harald Weltec2c52552018-03-01 21:20:39 +01001516 * LOCATION CANCEL
1517 * AUTH FAIL REP
1518 * DELETE DATA after hlr_subscr_nam() change
1519 * correctness
1520 ** wrong message type
1521 ** wrong length of PDU
1522 ** too short message
1523 ** missing IMSI IE
1524
1525 */
1526
Harald Weltedf327232017-12-28 22:51:51 +01001527control {
1528 execute( TC_gsup_sai_err_invalid_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001529 execute( TC_gsup_sai() );
Alexander Couzens92696442020-01-10 07:57:16 +01001530 execute( TC_gsup_sai_num_auth_vectors() );
Harald Welteaf7c3182019-08-22 12:40:22 +02001531 execute( TC_gsup_sai_eps() );
Harald Weltec2c52552018-03-01 21:20:39 +01001532 execute( TC_gsup_ul_unknown_imsi() );
Harald Welte3f662762018-03-02 10:48:20 +01001533 execute( TC_gsup_sai_err_unknown_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001534 execute( TC_gsup_ul() );
1535 execute( TC_vty() );
Harald Welte09b3c502018-03-01 22:42:22 +01001536 execute( TC_vty_msisdn_isd() );
Harald Welte958f8b42018-03-01 23:40:17 +01001537 execute( TC_gsup_purge_cs() );
1538 execute( TC_gsup_purge_ps() );
1539 execute( TC_gsup_purge_unknown() );
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001540
1541 execute( TC_mo_ussd_unknown() );
1542 execute( TC_mo_ussd_euse_disc() );
1543 execute( TC_mo_ussd_iuse_imsi() );
1544 execute( TC_mo_ussd_iuse_msisdn() );
1545 execute( TC_mo_ussd_euse() );
1546 execute( TC_mo_ussd_euse_continue() );
1547 execute( TC_mo_ussd_euse_defaultroute() );
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001548
1549 /* "Structured" Supplementary Services */
1550 execute( TC_mo_sss_reject() );
Oliver Smith936dbe62019-06-04 15:54:17 +02001551
1552 execute( TC_gsup_check_imei() );
1553 execute( TC_gsup_check_imei_invalid_len() );
1554 execute( TC_gsup_check_imei_unknown_imsi() );
Oliver Smith1b257802019-06-11 09:43:42 +02001555 execute( TC_subscr_create_on_demand_check_imei_early() );
1556 execute( TC_subscr_create_on_demand_ul() );
1557 execute( TC_subscr_create_on_demand_sai() );
Harald Weltedf327232017-12-28 22:51:51 +01001558};
1559
1560};