blob: b59f86eab5086a6fa7ceeb91200fc76076667e5f [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,
Oliver Smith62a1c632020-01-15 15:58:54 +0100450 template (omit) integer exp_err_cause := omit,
451 GSUP_CnDomain dom := OSMO_GSUP_CN_DOMAIN_PS)
Harald Welteed380d12018-06-14 13:42:11 +0200452runs on HLR_ConnHdlr return GSUP_PDU {
Harald Weltec2c52552018-03-01 21:20:39 +0100453 var GSUP_PDU ret;
454 timer T := 3.0;
455 var boolean exp_fail := false;
456 var boolean isd_done := false;
457 if (not istemplatekind(exp_err_cause, "omit")) {
458 exp_fail := true;
459 }
460
Oliver Smith62a1c632020-01-15 15:58:54 +0100461 GSUP.send(valueof(ts_GSUP_UL_REQ(imsi, dom)));
Harald Weltec2c52552018-03-01 21:20:39 +0100462 T.start;
463 alt {
464 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, exp_err_cause)) -> value ret {
465 setverdict(pass);
466 }
467 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
468 setverdict(fail, "Unexpected UL ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100469 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100470 }
471 [exp_fail] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
472 setverdict(fail, "Unexpected UL.res for unknown IMSI");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100473 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100474 }
475 [exp_fail] GSUP.receive(tr_GSUP_ISD_REQ(imsi)) -> value ret {
476 setverdict(fail, "Unexpected ISD.req in error case");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100477 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100478 }
479 [not exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
480 setverdict(fail, "Unexpected UL ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100481 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100482 }
483 [not exp_fail and not isd_done] GSUP.receive(tr_GSUP_ISD_REQ(imsi, msisdn)) -> value ret {
484 GSUP.send(ts_GSUP_ISD_RES(imsi));
485 isd_done := true;
Harald Welte8f0c9332018-03-01 23:38:40 +0100486 repeat;
Harald Weltec2c52552018-03-01 21:20:39 +0100487 }
488 [not exp_fail and isd_done] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
489 setverdict(pass);
490 }
491 [] GSUP.receive { repeat; }
492 [] T.timeout {
493 setverdict(fail, "Timeout waiting for UL response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200494 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100495 }
496 }
497 return ret;
498}
499
Harald Welte958f8b42018-03-01 23:40:17 +0100500/* perform PurgeMS for given imsi, return the GSUP response/error */
501function f_perform_PURGE(hexstring imsi, GSUP_CnDomain cn_dom,
502 template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200503runs on HLR_ConnHdlr return GSUP_PDU {
Harald Welte958f8b42018-03-01 23:40:17 +0100504 var GSUP_PDU ret;
505 timer T := 3.0;
506 var boolean exp_fail := false;
507 if (not istemplatekind(exp_err_cause, "omit")) {
508 exp_fail := true;
509 }
510
511 GSUP.send(valueof(ts_GSUP_PURGE_MS_REQ(imsi, cn_dom)));
512 T.start;
513 alt {
514 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, exp_err_cause)) -> value ret {
515 setverdict(pass);
516 }
517 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
518 setverdict(fail, "Unexpected PURGE ERROR Cause");
519 }
520 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
521 setverdict(fail, "Unexpected PURGE.res for unknown IMSI");
522 }
523 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
524 setverdict(fail, "Unexpected PURGE ERROR");
525 }
526 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
527 setverdict(pass);
528 }
529 [] GSUP.receive { repeat; }
530 [] T.timeout {
531 setverdict(fail, "Timeout waiting for PURGE response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200532 mtc.stop;
Harald Welte958f8b42018-03-01 23:40:17 +0100533 }
534 }
535 return ret;
536}
537
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200538function f_SS_xceive(hexstring imsi, OCT4 sid, GSUP_SessionState state, octetstring ss,
539 template (omit) integer exp_err_cause := omit)
540runs on HLR_ConnHdlr return GSUP_PDU {
541 var GSUP_PDU ret;
542 timer T := 3.0;
543 var boolean exp_fail := false;
544 if (not istemplatekind(exp_err_cause, "omit")) {
545 exp_fail := true;
546 }
547
548 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(imsi, sid, state, ss)));
549 T.start;
550 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700551 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, exp_err_cause)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200552 setverdict(pass);
553 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700554 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200555 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
556 }
557 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
558 setverdict(fail, "Unexpected PROC_SS.res for unknown IMSI");
559 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700560 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200561 setverdict(fail, "Unexpected PROC_SS ERROR");
562 }
563 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
564 setverdict(pass);
565 }
566 [] GSUP.receive { repeat; }
567 [] T.timeout {
568 setverdict(fail, "Timeout waiting for PROC_SS response");
569 self.stop;
570 }
571 }
572 return ret;
573}
574
575private function f_SS_expect(hexstring imsi, OCT4 sid, GSUP_SessionState state,
576 template SS_FacilityInformation facility := *)
577runs on HLR_ConnHdlr return GSUP_PDU {
578 var GSUP_PDU ret;
579 timer T := 3.0;
580 var boolean exp_ss := true;
581 if (istemplatekind(facility, "omit")) {
582 exp_ss := false;
583 }
584 T.start;
585 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700586 [] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200587 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100588 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200589 }
590 [not exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
591 setverdict(pass);
592 }
593 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
594 setverdict(fail, "Unexpected PROC_SS.res without SS IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100595 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200596 }
597/*
598 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, decmatch facility)) -> value ret {
599 setverdict(pass);
600 }
601*/
602
603 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, ?)) -> value ret {
604 var GSUP_IeValue ss_ie;
605 f_gsup_find_ie(ret, OSMO_GSUP_SS_INFO_IE, ss_ie);
606 var SS_FacilityInformation dec_fac := dec_SS_FacilityInformation(ss_ie.ss_info);
607 log("pattern: ", facility);
608 if (match(dec_fac, facility)) {
609 setverdict(pass);
610 } else {
611 setverdict(fail, "Unexpected PROC_SS.res with non-matching facility IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100612 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200613 }
614 }
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100615 [] GSUP.receive {
616 setverdict(fail, "Unexpected GSUP");
617 mtc.stop;
618 }
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200619 [] T.timeout {
620 setverdict(fail, "Timeout waiting for PROC_SS response");
621 self.stop;
622 }
623 }
624
625 return ret;
626}
627
Oliver Smith936dbe62019-06-04 15:54:17 +0200628function f_perform_CHECK_IMEI(hexstring imsi, hexstring imei,
629 template (omit) integer exp_err_cause := omit,
630 template (omit) GSUP_IMEIResult result := omit)
631runs on HLR_ConnHdlr {
632 var GSUP_PDU pdu;
633 timer T := 3.0;
634 var boolean exp_fail := false;
635 if (not istemplatekind(exp_err_cause, "omit")) {
636 exp_fail := true;
637 }
638
639 GSUP.send(valueof(ts_GSUP_CHECK_IMEI_REQ(imsi, imei)));
640 T.start;
641 alt {
642 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, exp_err_cause)) -> value pdu {
643 setverdict(pass);
644 }
645 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?)) -> value pdu {
646 setverdict(fail, "Unexpected CHECK IMEI ERROR Cause: ", pdu);
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100647 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200648 }
649 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?)) -> value pdu {
650 setverdict(fail, "Unexpected CHECK IMEI RES instead of ERR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100651 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200652 }
653 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?)) -> value pdu {
654 setverdict(fail, "Unexpected CHECK IMEI ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100655 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200656 }
657 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, result)) -> value pdu {
658 setverdict(pass);
659 }
660 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?)) -> value pdu {
661 setverdict(fail, "Unexpected CHECK IMEI RES");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100662 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200663 }
664 [] GSUP.receive { repeat; }
665 [] T.timeout {
666 setverdict(fail, "Timeout waiting for CHECK IMEI response");
667 mtc.stop;
668 }
669 }
670}
671
672
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200673
Harald Welte958f8b42018-03-01 23:40:17 +0100674
Harald Welteed380d12018-06-14 13:42:11 +0200675/***********************************************************************
676 * Testcases
677 ***********************************************************************/
678
679/* 23.003 Section 2.2 clearly states that an IMSI with less
680 * than 5 digits is impossible. Even 5 digits is still questionable */
681private function f_TC_gsup_sai_err_invalid_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100682 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200683 res := f_perform_SAI(g_pars.sub.imsi, 96); /* Invalid Mandatory information */
684 setverdict(pass);
685}
686testcase TC_gsup_sai_err_invalid_imsi() runs on test_CT {
687 var HLR_ConnHdlr vc_conn;
688 var HLR_ConnHdlrPars pars := valueof(t_Pars('0123'H));
689 f_init(false);
690 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_invalid_imsi), pars);
691 vc_conn.done;
692}
Harald Weltec2c52552018-03-01 21:20:39 +0100693
Harald Weltec2c52552018-03-01 21:20:39 +0100694
Harald Welteed380d12018-06-14 13:42:11 +0200695private function f_TC_gsup_sai_err_unknown_imsi() runs on HLR_ConnHdlr {
696 var GSUP_PDU res;
697 res := f_perform_SAI(g_pars.sub.imsi, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100698 setverdict(pass);
699}
700
Harald Welte3f662762018-03-02 10:48:20 +0100701testcase TC_gsup_sai_err_unknown_imsi() runs on test_CT {
Harald Welteed380d12018-06-14 13:42:11 +0200702 var HLR_ConnHdlr vc_conn;
703 var HLR_ConnHdlrPars pars := valueof(t_Pars(f_rnd_imsi('26242'H)));
704 f_init(false);
705 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_unknown_imsi), pars);
706 vc_conn.done;
Harald Welte3f662762018-03-02 10:48:20 +0100707}
708
Harald Welteed380d12018-06-14 13:42:11 +0200709function f_start_handler_per_sub(void_fn fn, HlrSubscriberList sl) runs on test_CT {
710 for (var integer i := 0; i < sizeof(sl); i := i+1) {
711 var HlrSubscriber sub := sl[i];
712 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sub));
713 var HLR_ConnHdlr vc_conn;
714
715 f_vty_subscr_create(VTY, sub);
716 vc_conn := f_start_handler(fn, pars);
717 vc_conn.done;
718 f_vty_subscr_delete(VTY, sub);
719 }
720}
Harald Welte3f662762018-03-02 10:48:20 +0100721
Harald Weltec2c52552018-03-01 21:20:39 +0100722/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
Harald Welteed380d12018-06-14 13:42:11 +0200723private function f_TC_gsup_sai() runs on HLR_ConnHdlr {
724 var GSUP_PDU res;
725 res := f_perform_SAI(g_pars.sub.imsi);
Harald Welte4b612042019-12-03 20:08:57 +0100726 if (ispresent(g_pars.sub.aud3g)) {
727 f_ensure_amf_separation_bit(res, '0'B);
728 }
Alexander Couzens92696442020-01-10 07:57:16 +0100729
730 f_count_auth_tuples(res, mp_default_num_auth_tuples);
Harald Welteed380d12018-06-14 13:42:11 +0200731 setverdict(pass);
732}
Harald Weltec2c52552018-03-01 21:20:39 +0100733testcase TC_gsup_sai() runs on test_CT {
734 var HlrSubscriberList sl;
735 var GSUP_PDU res;
736
Harald Welteed380d12018-06-14 13:42:11 +0200737 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100738
739 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200740 f_start_handler_per_sub(refers(f_TC_gsup_sai), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100741
742 setverdict(pass);
743}
744
Alexander Couzens92696442020-01-10 07:57:16 +0100745/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
746private function f_TC_gsup_sai_num_auth_vectors() runs on HLR_ConnHdlr {
747 var GSUP_PDU res;
748 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 1);
749 f_count_auth_tuples(res, 1);
750 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 4);
751 f_count_auth_tuples(res, 4);
752 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 5);
753 f_count_auth_tuples(res, 5);
754 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 254);
755 f_count_auth_tuples(res, 5);
756 setverdict(pass);
757}
758testcase TC_gsup_sai_num_auth_vectors() runs on test_CT {
759 var HlrSubscriberList sl;
760 var GSUP_PDU res;
761
762 f_init(false);
763
764 sl := f_gen_subs();
765 f_start_handler_per_sub(refers(f_TC_gsup_sai_num_auth_vectors), sl);
766
767 setverdict(pass);
768}
769
Harald Welteaf7c3182019-08-22 12:40:22 +0200770private function f_ensure_amf_separation_bit(GSUP_PDU res, BIT1 sep_bit)
771{
772 for (var integer i := 0; i < lengthof(res.ies); i := i+1) {
773 var GSUP_IE tuple := res.ies[i];
774 if (tuple.tag != OSMO_GSUP_AUTH_TUPLE_IE) {
775 continue;
776 }
777 var GSUP_IeValue autn;
778 if (f_gsup_find_nested_ie(tuple.val.auth_tuple, OSMO_GSUP_AUTN_IE, autn) == false) {
779 setverdict(fail, "Couldn't find AUTN IE in tuple ", i);
780 mtc.stop;
781 }
782 var bitstring amf := oct2bit(substr(autn.autn, 6, 2));
783 if (amf[0] != sep_bit) {
784 setverdict(fail, "AMF bit 0 (separation bit) must be ", sep_bit," but was not");
785 mtc.stop;
786 }
787 }
788}
789
Alexander Couzens92696442020-01-10 07:57:16 +0100790private function f_count_auth_tuples(GSUP_PDU res, template (omit) integer expected_auth_tuples := omit)
791{
792 var integer auth_tuples := 0;
793 for (var integer i := 0; i < lengthof(res.ies); i := i+1) {
794 var GSUP_IE tuple := res.ies[i];
795 if (tuple.tag == OSMO_GSUP_AUTH_TUPLE_IE) {
796 auth_tuples := auth_tuples + 1;
797 }
798 }
799
800 if ((not istemplatekind(expected_auth_tuples, "omit")) and
801 not match(auth_tuples, valueof(expected_auth_tuples))) {
802 setverdict(fail,
803 "Did not received expected number of auth tuples. Expected ",
804 mp_default_num_auth_tuples,
805 " but received ", auth_tuples);
806 }
807}
808
Harald Welteaf7c3182019-08-22 12:40:22 +0200809/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
810private function f_TC_gsup_sai_eps() runs on HLR_ConnHdlr {
811 var GSUP_PDU res;
812 res := f_perform_SAI(g_pars.sub.imsi, is_eps := true);
813 f_ensure_amf_separation_bit(res, '1'B);
814
815 /* TODO: match if tuple[s] matches expectation */
816 setverdict(pass);
817}
818testcase TC_gsup_sai_eps() runs on test_CT {
819 var HlrSubscriberList sl;
820 var GSUP_PDU res;
821
822 f_init(false);
823
824 sl := f_gen_3G_subs();
825 f_start_handler_per_sub(refers(f_TC_gsup_sai_eps), sl);
826
827 setverdict(pass);
828}
829
830
Harald Weltec2c52552018-03-01 21:20:39 +0100831/* test UL for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200832private function f_TC_ul_unknown_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100833 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200834 res := f_perform_UL(g_pars.sub.imsi, ?, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100835 setverdict(pass);
836}
Harald Welteed380d12018-06-14 13:42:11 +0200837testcase TC_gsup_ul_unknown_imsi() runs on test_CT {
838 var hexstring imsi := f_rnd_imsi('26242'H);
839 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
840 var HLR_ConnHdlr vc_conn;
Harald Weltec2c52552018-03-01 21:20:39 +0100841
Harald Welteed380d12018-06-14 13:42:11 +0200842 f_init(false);
843 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
844 vc_conn.done;
845}
846
847/* test UL for a number of different subscriber cases (algo, 2g/3g, ...) */
848private function f_TC_gsup_ul() runs on HLR_ConnHdlr {
849 var GSUP_PDU res;
850 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
851 setverdict(pass);
852}
Harald Weltec2c52552018-03-01 21:20:39 +0100853testcase TC_gsup_ul() runs on test_CT {
854 var HlrSubscriberList sl;
855 var GSUP_PDU res;
856
Harald Welteed380d12018-06-14 13:42:11 +0200857 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100858 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200859 f_start_handler_per_sub(refers(f_TC_gsup_ul), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100860
861 setverdict(pass);
862}
863
864/* Test only the VTY commands */
865testcase TC_vty() runs on test_CT {
866 var HlrSubscriber sub;
867
868 f_init();
869
870 /* we're not using f_gen_subs() here as the expect pattern for the 'show' are different
871 * from case to case */
872 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
Harald Welteed380d12018-06-14 13:42:11 +0200873 f_vty_subscr_create(VTY, sub);
874 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*");
875 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100876
877 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
878 "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +0200879 f_vty_subscr_create(VTY, sub);
880 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *3G auth: MILENAGE*");
881 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100882
883 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
884 "comp128v1", "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +0200885 f_vty_subscr_create(VTY, sub);
886 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*3G auth: MILENAGE*");
887 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100888
889 setverdict(pass);
890}
891
Harald Welte09b3c502018-03-01 22:42:22 +0100892/* VTY changes to MSISDN should result in ISD to current VLR */
Harald Welteed380d12018-06-14 13:42:11 +0200893private function f_TC_vty_msisdn_isd() runs on HLR_ConnHdlr {
Harald Welte09b3c502018-03-01 22:42:22 +0100894 var hexstring new_msisdn;
895 var GSUP_PDU res;
896 timer T := 5.0;
897
Harald Welte09b3c502018-03-01 22:42:22 +0100898 /* Create Subscriber */
Harald Welteed380d12018-06-14 13:42:11 +0200899 f_vty_subscr_create(VTY, g_pars.sub);
Harald Welte09b3c502018-03-01 22:42:22 +0100900
901 /* Perform UpdateLocation (VLR now known to HLR) */
Harald Welteed380d12018-06-14 13:42:11 +0200902 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +0100903
904 /* Then change IMSI via VTY */
905 new_msisdn := '49161'H & f_rnd_hexstring(7, 9);
Harald Welteed380d12018-06-14 13:42:11 +0200906 f_vty_subscr_update_msisdn(VTY, g_pars.sub, new_msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +0100907 /* And expect InsertSubscriberData as result */
908 T.start;
909 alt {
Harald Welteed380d12018-06-14 13:42:11 +0200910 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, new_msisdn)) {
911 GSUP.send(ts_GSUP_ISD_RES(g_pars.sub.imsi));
912 g_pars.sub.msisdn := new_msisdn;
Harald Welte09b3c502018-03-01 22:42:22 +0100913 setverdict(pass);
914 }
Harald Welteed380d12018-06-14 13:42:11 +0200915 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, g_pars.sub.msisdn)) {
Stefan Sperling7c096872018-04-09 11:24:22 +0200916 log("received ISD req with old MSISDN");
917 setverdict(fail);
918 }
Harald Welte09b3c502018-03-01 22:42:22 +0100919 [] GSUP.receive { repeat; }
920 [] T.timeout {
921 setverdict(fail, "Timeout waiting for ISD.req");
922 }
923 }
924}
Harald Welteed380d12018-06-14 13:42:11 +0200925testcase TC_vty_msisdn_isd() runs on test_CT {
926 var HlrSubscriber sub;
927 var HLR_ConnHdlr vc_conn;
928
929 f_init(false);
930
931 /* Create Subscriber */
932 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
933
934 vc_conn := f_start_handler(refers(f_TC_vty_msisdn_isd), valueof(t_Pars_sub(sub)));
935 vc_conn.done;
936}
Harald Welte09b3c502018-03-01 22:42:22 +0100937
Harald Welte958f8b42018-03-01 23:40:17 +0100938/* Test PURGE MS for CS services */
Harald Welteed380d12018-06-14 13:42:11 +0200939private function f_TC_gsup_purge_cs() runs on HLR_ConnHdlr {
940 var GSUP_PDU res;
941 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
942 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS);
943}
Harald Welte958f8b42018-03-01 23:40:17 +0100944testcase TC_gsup_purge_cs() runs on test_CT {
945 var HlrSubscriberList sl;
946 var GSUP_PDU res;
947
Harald Welteed380d12018-06-14 13:42:11 +0200948 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +0100949 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200950 f_start_handler_per_sub(refers(f_TC_gsup_purge_cs), sl);
Harald Welte958f8b42018-03-01 23:40:17 +0100951
952 setverdict(pass);
953}
954
955/* Test PURGE MS for PS services */
Harald Welteed380d12018-06-14 13:42:11 +0200956private function f_TC_gsup_purge_ps() runs on HLR_ConnHdlr {
957 var GSUP_PDU res;
958 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
959 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_PS);
960}
Harald Welte958f8b42018-03-01 23:40:17 +0100961testcase TC_gsup_purge_ps() runs on test_CT {
962 var HlrSubscriberList sl;
Harald Welte958f8b42018-03-01 23:40:17 +0100963
Harald Welteed380d12018-06-14 13:42:11 +0200964 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +0100965 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200966 f_start_handler_per_sub(refers(f_TC_gsup_purge_ps), sl);
Harald Welte958f8b42018-03-01 23:40:17 +0100967
968 setverdict(pass);
969}
970
971/* Test PURGEG MS procedure for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200972
973private function f_TC_gsup_purge_unknown() runs on HLR_ConnHdlr {
974 var GSUP_PDU res;
975 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS, 2);
976}
Harald Welte958f8b42018-03-01 23:40:17 +0100977testcase TC_gsup_purge_unknown() runs on test_CT {
978 var hexstring imsi := '2345743413463'H;
Harald Welteed380d12018-06-14 13:42:11 +0200979 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
980 var HLR_ConnHdlr vc_conn;
Harald Welte958f8b42018-03-01 23:40:17 +0100981
Harald Welteed380d12018-06-14 13:42:11 +0200982 f_init(false);
983 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
984 vc_conn.done;
Harald Welte958f8b42018-03-01 23:40:17 +0100985
986 setverdict(pass);
987}
988
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200989import from HLR_EUSE all;
990
991/* Test for USSD request to undefined/unrouted short-code. Expect ss-NotAvailable(18) */
992private function f_TC_mo_ussd_unknown() runs on HLR_ConnHdlr {
993 var GSUP_PDU res;
994 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
995 op_code := SS_OP_CODE_PROCESS_USS_REQ,
996 ussd_string := "*#200#");
997 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
998 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +0700999 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1000 OSMO_GSUP_SESSION_STATE_END,
1001 tr_SS_FACILITY_RETURN_ERROR(1, 18));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001002}
1003testcase TC_mo_ussd_unknown() 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_unknown), pars);
1014 vc_conn.done;
1015 }
1016}
1017
1018/* Test for USSD request to currently disconnected EUSE. Expect ss-SystemFailure(34) */
1019private function f_TC_mo_ussd_euse_disc() runs on HLR_ConnHdlr {
1020 var GSUP_PDU res;
1021 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1022 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1023 ussd_string := "*100#");
1024 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1025 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001026 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1027 OSMO_GSUP_SESSION_STATE_END,
1028 tr_SS_FACILITY_RETURN_ERROR(1, 34));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001029}
1030testcase TC_mo_ussd_euse_disc() runs on test_CT {
1031 var HlrSubscriberList sl;
1032 var HLR_ConnHdlr vc_conn;
1033
1034 f_init(false);
1035 sl := f_gen_subs();
1036 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1037 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1038 pars.ussd.sid := f_rnd_octstring(4);
1039 f_vty_subscr_create(VTY, pars.sub);
1040 vc_conn := f_start_handler(refers(f_TC_mo_ussd_euse_disc), pars);
1041 vc_conn.done;
1042 }
1043}
1044
1045/* Test for USSD request to internal own-imsi IUSE. */
1046private function f_TC_mo_ussd_iuse_imsi() runs on HLR_ConnHdlr {
1047 var GSUP_PDU res;
1048 var charstring resp_str;
1049 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1050 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1051 ussd_string := "*#101#");
1052 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1053 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1054 resp_str := "Your IMSI is " & hex2str(g_pars.sub.imsi);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001055 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1056 OSMO_GSUP_SESSION_STATE_END,
1057 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1058 f_encGSM7bit(resp_str)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001059}
1060testcase TC_mo_ussd_iuse_imsi() runs on test_CT {
1061 var HlrSubscriberList sl;
1062 var HLR_ConnHdlr vc_conn;
1063
1064 f_init(false);
1065 sl := f_gen_subs();
1066 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1067 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1068 pars.ussd.sid := f_rnd_octstring(4);
1069 f_vty_subscr_create(VTY, pars.sub);
1070 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_imsi), pars);
1071 vc_conn.done;
1072 }
1073}
1074
1075/* Test for USSD request to internal own-msisdn IUSE. */
1076private function f_TC_mo_ussd_iuse_msisdn() runs on HLR_ConnHdlr {
1077 var GSUP_PDU res;
1078 var charstring resp_str;
1079 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1080 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1081 ussd_string := "*#100#");
1082 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1083 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1084 resp_str := "Your extension is " & hex2str(g_pars.sub.msisdn);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001085 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1086 OSMO_GSUP_SESSION_STATE_END,
1087 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1088 f_encGSM7bit(resp_str)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001089}
1090testcase TC_mo_ussd_iuse_msisdn() runs on test_CT {
1091 var HlrSubscriberList sl;
1092 var HLR_ConnHdlr vc_conn;
1093
1094 f_init(false);
1095 sl := f_gen_subs();
1096 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1097 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1098 pars.ussd.sid := f_rnd_octstring(4);
1099 f_vty_subscr_create(VTY, pars.sub);
1100 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_msisdn), pars);
1101 vc_conn.done;
1102 }
1103}
1104
1105/* Test routing of USSD to EUSE by a specific route */
1106private function f_TC_mo_ussd_100() runs on HLR_ConnHdlr {
1107 var GSUP_PDU res;
1108 /* invoke / invoke id 1 / processUSS-req */
1109 //var octetstring ss := 'a11202010102013b300a04010f0405aa180c3602'O;
1110 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1111 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1112 ussd_string := "*100#");
1113 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1114 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001115 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1116 OSMO_GSUP_SESSION_STATE_END,
1117 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1118 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001119}
1120testcase TC_mo_ussd_euse() runs on test_CT {
1121 var HlrSubscriberList sl;
1122 var HLR_ConnHdlr vc_conn;
1123
1124 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1125 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
1126
1127 f_init(false);
1128 sl := f_gen_subs();
1129 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1130 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1131 pars.ussd.sid := f_rnd_octstring(4);
1132 f_vty_subscr_create(VTY, pars.sub);
1133 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100), pars);
1134 vc_conn.done;
1135 }
1136
1137 vc_EUSE.stop;
1138}
1139
1140/* Test routing of USSD to EUSE by a specific route, with CONTINUE */
1141private function f_TC_mo_ussd_100_continue() runs on HLR_ConnHdlr {
1142 var GSUP_PDU res;
1143 /* Simulate BEGIN from MS/MSC */
1144 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1145 ussd_string := "*100#");
1146 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1147 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1148 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001149 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1150 OSMO_GSUP_SESSION_STATE_CONTINUE,
1151 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1152 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001153
1154 /* Simulate CONTINUE from MS/MSC */
1155 ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1156 ussd_string := "mahlzeit");
1157 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1158 OSMO_GSUP_SESSION_STATE_CONTINUE, ss)));
1159
1160 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001161 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1162 OSMO_GSUP_SESSION_STATE_END,
1163 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1164 f_encGSM7bit("mahlzeit")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001165}
1166testcase TC_mo_ussd_euse_continue() runs on test_CT {
1167 var HlrSubscriberList sl;
1168 var HLR_ConnHdlr vc_conn;
1169
1170 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1171 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar",
1172 refers(f_ss_echo_continue)));
1173
1174 f_init(false);
1175 sl := f_gen_subs();
1176 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1177 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1178 pars.ussd.sid := f_rnd_octstring(4);
1179 f_vty_subscr_create(VTY, pars.sub);
1180 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100_continue), pars);
1181 vc_conn.done;
1182 }
1183
1184 vc_EUSE.stop;
1185}
1186
1187
1188/* Test routing of USSD to EUSE by default-route */
1189private function f_TC_mo_ussd_999() runs on HLR_ConnHdlr {
1190 var GSUP_PDU res;
1191 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1192 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1193 ussd_string := "*999#");
1194 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1195 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001196 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1197 OSMO_GSUP_SESSION_STATE_END,
1198 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1199 f_encGSM7bit("*999#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001200}
1201testcase TC_mo_ussd_euse_defaultroute() runs on test_CT {
1202 var HlrSubscriberList sl;
1203 var HLR_ConnHdlr vc_conn;
1204
1205 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1206 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
1207
1208 f_init(false);
1209 f_vty_config(VTY, "hlr", "ussd default-route external foobar");
1210
1211 sl := f_gen_subs();
1212 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1213 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1214 pars.ussd.sid := f_rnd_octstring(4);
1215 f_vty_subscr_create(VTY, pars.sub);
1216 vc_conn := f_start_handler(refers(f_TC_mo_ussd_999), pars);
1217 vc_conn.done;
1218 }
1219
1220 f_vty_config(VTY, "hlr", "no ussd default-route");
1221 vc_EUSE.stop;
1222}
1223
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001224/**
1225 * Test "Structured" Supplementary Services
1226 *
1227 * NOTE: at the moment, OsmoHLR doesn't support "structured" SS,
1228 * so such requests are being rejected (actually ReturnError
1229 * with GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED).
1230 */
1231private function f_TC_mo_sss_reject() runs on HLR_ConnHdlr {
1232 var SS_FacilityInformation ss_req;
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001233 var GSUP_PDU res;
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001234
1235 /* Prepare '*#21#' SS request */
1236 ss_req := valueof(ts_SS_FACILITY_INVOKE(
1237 invoke_id := 0,
1238 op_code := SS_OP_CODE_INTERROGATE_SS,
1239 ss_code := '21'O));
1240
1241 /* Send it towards HLR */
1242 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(
1243 g_pars.sub.imsi,
1244 g_pars.ussd.sid,
1245 OSMO_GSUP_SESSION_STATE_BEGIN,
1246 enc_SS_FacilityInformation(ss_req))));
1247
1248 /* Expect ReturnError with FACILITY_NOT_SUPPORTED */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001249 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1250 OSMO_GSUP_SESSION_STATE_END,
1251 tr_SS_FACILITY_RETURN_ERROR(0, 21));
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001252}
1253testcase TC_mo_sss_reject() runs on test_CT {
1254 var HLR_ConnHdlrPars pars;
1255 var HLR_ConnHdlr vc_conn;
1256 var HlrSubscriber sub;
1257
1258 f_init(false);
1259
1260 /* Create a random subscriber */
1261 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H),
1262 '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
1263 pars := valueof(t_Pars_sub(sub));
1264 pars.ussd.sid := f_rnd_octstring(4);
1265
1266 f_vty_subscr_create(VTY, sub);
1267 vc_conn := f_start_handler(refers(f_TC_mo_sss_reject), pars);
1268 vc_conn.done;
1269 f_vty_subscr_delete(VTY, sub);
1270}
1271
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001272
1273/* TODO USSD:
1274 * MO USSD for IMSI of non-existant subscriber
1275 * MT USSD from EUSE
1276 * timeout cases
1277 */
1278
Oliver Smith936dbe62019-06-04 15:54:17 +02001279
1280/* Test Check IMEI */
1281private function f_TC_gsup_check_imei() runs on HLR_ConnHdlr {
1282 /* store-imei disabled */
1283 f_vty_config(VTY, "hlr", "no store-imei");
1284 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1285 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1286
1287 /* store-imei enabled */
1288 f_vty_config(VTY, "hlr", "store-imei");
1289 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1290 f_vty_subscr_show(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1291}
1292testcase TC_gsup_check_imei() runs on test_CT {
1293 var HlrSubscriberList sl;
1294
1295 f_init(false);
1296 sl := f_gen_subs();
1297 f_start_handler_per_sub(refers(f_TC_gsup_check_imei), sl);
1298
1299 setverdict(pass);
1300}
1301
1302/* Test Check IMEI with invalid IMEI length */
1303private function f_TC_gsup_check_imei_invalid_len() runs on HLR_ConnHdlr {
1304 /* IMEI too long */
1305 f_perform_CHECK_IMEI(g_pars.sub.imsi, '111456789012345F'H, 96 /* Invalid Mandatory Information */);
1306 f_perform_CHECK_IMEI(g_pars.sub.imsi, '2224567890123456'H, 96 /* Invalid Mandatory Information */);
1307
1308 /* IMEI too short */
1309 f_perform_CHECK_IMEI(g_pars.sub.imsi, '3334567890123F'H, 96 /* Invalid Mandatory Information */);
1310 f_perform_CHECK_IMEI(g_pars.sub.imsi, '444456789012'H, 96 /* Invalid Mandatory Information */);
1311 f_perform_CHECK_IMEI(g_pars.sub.imsi, ''H, 96 /* Invalid Mandatory Information */);
1312}
1313testcase TC_gsup_check_imei_invalid_len() runs on test_CT {
1314 var HlrSubscriberList sl;
1315
1316 f_init(false);
1317 sl := f_gen_subs();
1318 f_start_handler_per_sub(refers(f_TC_gsup_check_imei_invalid_len), sl);
1319
1320 setverdict(pass);
1321}
1322
1323/* Test Check IMEI with unknown IMSI */
1324private function f_TC_gsup_check_imei_unknown_imsi() runs on HLR_ConnHdlr {
1325 f_vty_config(VTY, "hlr", "no store-imei");
1326 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1327
1328 /* Check again with store-imei set (different code path) */
1329 f_vty_config(VTY, "hlr", "store-imei");
1330 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1331
1332 setverdict(pass);
1333}
1334testcase TC_gsup_check_imei_unknown_imsi() runs on test_CT {
1335 var hexstring imsi := f_rnd_imsi('26242'H);
1336 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1337 var HLR_ConnHdlr vc_conn;
1338
1339 f_init(false);
1340 vc_conn := f_start_handler(refers(f_TC_gsup_check_imei_unknown_imsi), pars);
1341 vc_conn.done;
1342}
1343
Oliver Smith1b257802019-06-11 09:43:42 +02001344/* Test create-subscriber-on-demand during Check IMEI (OsmoMSC would be set to "check-imei-rqd early") */
1345private function f_TC_subscr_create_on_demand_check_imei_early() runs on HLR_ConnHdlr {
1346 var GSUP_PDU res; /* save various return values to prevent ttcn3 compiler warnings */
1347 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1348
1349 /* Random MSISDN and CS+PS NAM (LU must pass) */
1350 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1351 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1352 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1353 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1354 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1355 res := f_perform_UL(g_pars.sub.imsi, ?);
1356 f_vty_subscr_delete(VTY, g_pars.sub);
1357
1358 /* Random MSISDN and PS NAM (LU must pass) */
1359 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1360 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1361 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1362 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1363 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1364 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1365 res := f_perform_UL(g_pars.sub.imsi, ?);
1366 f_vty_subscr_delete(VTY, g_pars.sub);
1367
1368 /* Random MSISDN and CS NAM (LU must fail) */
1369 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1370 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1371 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1372 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1373 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1374 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1375 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1376 f_vty_subscr_delete(VTY, g_pars.sub);
1377
1378 /* Random MSISDN and no NAM (LU must fail) */
1379 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1380 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1381 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1382 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1383 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1384 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1385 f_vty_subscr_delete(VTY, g_pars.sub);
1386
1387 /* No MSISDN and no NAM (LU must fail) */
1388 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1389 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1390 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1391 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1392 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1393 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1394 f_vty_subscr_delete(VTY, g_pars.sub);
1395
1396 /* No MSISDN and CS+PS NAM (LU must pass) */
1397 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1398 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1399 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1400 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1401 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1402 res := f_perform_UL(g_pars.sub.imsi, omit);
1403 f_vty_subscr_delete(VTY, g_pars.sub);
1404
1405 setverdict(pass);
1406}
1407testcase TC_subscr_create_on_demand_check_imei_early() runs on test_CT {
1408 var hexstring imsi := f_rnd_imsi('26242'H);
1409 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1410 var HLR_ConnHdlr vc_conn;
1411
1412 f_init(false);
1413 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_check_imei_early), pars);
1414 vc_conn.done;
1415}
1416
1417/* Test create-subscriber-on-demand during LU (Location Update) */
1418private function f_TC_subscr_create_on_demand_ul() runs on HLR_ConnHdlr {
1419 var GSUP_PDU res;
1420 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1421
1422 /* Random MSISDN and CS+PS NAM (LU must pass) */
1423 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1424 res := f_perform_UL(g_pars.sub.imsi, ?);
1425 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1426 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1427 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1428 f_vty_subscr_delete(VTY, g_pars.sub);
1429
1430 /* Random MSISDN and PS NAM (LU must pass) */
1431 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1432 res := f_perform_UL(g_pars.sub.imsi, ?);
1433 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1434 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1435 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1436 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1437 f_vty_subscr_delete(VTY, g_pars.sub);
1438
1439 /* Random MSISDN and CS NAM (LU must fail) */
1440 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1441 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1442 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1443 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1444 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1445 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1446 f_vty_subscr_delete(VTY, g_pars.sub);
1447
1448 /* Random MSISDN and no NAM (LU must fail) */
1449 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1450 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1451 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1452 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1453 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1454 f_vty_subscr_delete(VTY, g_pars.sub);
1455
1456 /* No MSISDN and no NAM (LU must fail) */
1457 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1458 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1459 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1460 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1461 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1462 f_vty_subscr_delete(VTY, g_pars.sub);
1463
1464 /* No MSISDN and CS+PS NAM (LU must pass) */
1465 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1466 res := f_perform_UL(g_pars.sub.imsi, omit);
1467 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1468 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1469 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1470 f_vty_subscr_delete(VTY, g_pars.sub);
1471
1472 setverdict(pass);
1473}
1474testcase TC_subscr_create_on_demand_ul() runs on test_CT {
1475 var hexstring imsi := f_rnd_imsi('26242'H);
1476 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1477 var HLR_ConnHdlr vc_conn;
1478
1479 f_init(false);
1480 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_ul), pars);
1481 vc_conn.done;
1482}
1483
1484/* Test create-subscriber-on-demand during SAI (SendAuthInfo) */
1485private function f_TC_subscr_create_on_demand_sai() runs on HLR_ConnHdlr {
1486 var GSUP_PDU res;
1487 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1488
1489 /* HLR creates the subscriber on demand. Then the IMSI is known, but there is no auth data, so the HLR returns
1490 * the "slightly inaccurate cause 'IMSI Unknown' via GSUP". The MS is able to do a LU afterwards. */
1491 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1492 res := f_perform_SAI(g_pars.sub.imsi, 2 /* IMSI Unknown */ );
1493
1494 /* Verify that it was created before the LU */
1495 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1496 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1497 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1498
1499 /* Location update */
1500 res := f_perform_UL(g_pars.sub.imsi, ?);
1501 f_vty_subscr_delete(VTY, g_pars.sub);
1502 setverdict(pass);
1503}
1504testcase TC_subscr_create_on_demand_sai() runs on test_CT {
1505 var hexstring imsi := f_rnd_imsi('26242'H);
1506 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1507 var HLR_ConnHdlr vc_conn;
1508
1509 f_init(false);
1510 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_sai), pars);
1511 vc_conn.done;
1512}
1513
Harald Weltec2c52552018-03-01 21:20:39 +01001514/* TODO:
1515 * UL with ISD error
1516 * UL with ISD timeout
Harald Weltec2c52552018-03-01 21:20:39 +01001517 * LOCATION CANCEL
1518 * AUTH FAIL REP
1519 * DELETE DATA after hlr_subscr_nam() change
1520 * correctness
1521 ** wrong message type
1522 ** wrong length of PDU
1523 ** too short message
1524 ** missing IMSI IE
1525
1526 */
1527
Harald Weltedf327232017-12-28 22:51:51 +01001528control {
1529 execute( TC_gsup_sai_err_invalid_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001530 execute( TC_gsup_sai() );
Alexander Couzens92696442020-01-10 07:57:16 +01001531 execute( TC_gsup_sai_num_auth_vectors() );
Harald Welteaf7c3182019-08-22 12:40:22 +02001532 execute( TC_gsup_sai_eps() );
Harald Weltec2c52552018-03-01 21:20:39 +01001533 execute( TC_gsup_ul_unknown_imsi() );
Harald Welte3f662762018-03-02 10:48:20 +01001534 execute( TC_gsup_sai_err_unknown_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001535 execute( TC_gsup_ul() );
1536 execute( TC_vty() );
Harald Welte09b3c502018-03-01 22:42:22 +01001537 execute( TC_vty_msisdn_isd() );
Harald Welte958f8b42018-03-01 23:40:17 +01001538 execute( TC_gsup_purge_cs() );
1539 execute( TC_gsup_purge_ps() );
1540 execute( TC_gsup_purge_unknown() );
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001541
1542 execute( TC_mo_ussd_unknown() );
1543 execute( TC_mo_ussd_euse_disc() );
1544 execute( TC_mo_ussd_iuse_imsi() );
1545 execute( TC_mo_ussd_iuse_msisdn() );
1546 execute( TC_mo_ussd_euse() );
1547 execute( TC_mo_ussd_euse_continue() );
1548 execute( TC_mo_ussd_euse_defaultroute() );
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001549
1550 /* "Structured" Supplementary Services */
1551 execute( TC_mo_sss_reject() );
Oliver Smith936dbe62019-06-04 15:54:17 +02001552
1553 execute( TC_gsup_check_imei() );
1554 execute( TC_gsup_check_imei_invalid_len() );
1555 execute( TC_gsup_check_imei_unknown_imsi() );
Oliver Smith1b257802019-06-11 09:43:42 +02001556 execute( TC_subscr_create_on_demand_check_imei_early() );
1557 execute( TC_subscr_create_on_demand_ul() );
1558 execute( TC_subscr_create_on_demand_sai() );
Harald Weltedf327232017-12-28 22:51:51 +01001559};
1560
1561};