blob: e00bd8b511e7afd819a7a3624016c0093205cc03 [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
Oliver Smithdeb80a62019-11-29 16:01:54 +010034import from MSLookup_mDNS_Types all;
35import from MSLookup_mDNS_Emulation all;
36import from MSLookup_mDNS_Templates all;
Oliver Smithb51a53f2020-01-29 15:06:54 +010037import from DNS_Helpers all;
Oliver Smithdeb80a62019-11-29 16:01:54 +010038
Harald Welte39b82d32018-03-01 10:21:29 +010039type component test_CT extends CTRL_Adapter_CT {
Oliver Smith6e81f7e2020-01-29 14:25:41 +010040 /* emulated GSUP client (MSC/SGSN) */
Harald Weltedf327232017-12-28 22:51:51 +010041 var IPA_Emulation_CT vc_IPA;
42 var IPA_CCM_Parameters ccm_pars;
Harald Welteed380d12018-06-14 13:42:11 +020043 /* legacy tests without ConnHdlr */
Harald Weltedf327232017-12-28 22:51:51 +010044 port IPA_GSUP_PT GSUP;
Harald Welteed380d12018-06-14 13:42:11 +020045 /* new tests using ConnHdlr + GSUP_Emulation */
46 var GSUP_Emulation_CT vc_GSUP;
47 /* only to get events from IPA underneath GSUP */
48 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte39b82d32018-03-01 10:21:29 +010049
50 port TELNETasp_PT VTY;
Harald Weltec2c52552018-03-01 21:20:39 +010051
Oliver Smithdeb80a62019-11-29 16:01:54 +010052 var MSLookup_mDNS_Emulation_CT vc_MSLookup_mDNS;
53
Oliver Smith6e81f7e2020-01-29 14:25:41 +010054 /* emulated GSUP server (second HLR) */
55 var IPA_Emulation_CT vc_IPA_server;
56 var GSUP_Emulation_CT vc_GSUP_server;
57
Harald Weltec2c52552018-03-01 21:20:39 +010058 timer g_Tguard := 10.0;
Harald Weltedf327232017-12-28 22:51:51 +010059};
60
61modulepar {
Oliver Smith6e81f7e2020-01-29 14:25:41 +010062 /* OsmoHLR */
Harald Weltedf327232017-12-28 22:51:51 +010063 charstring mp_hlr_ip := "127.0.0.1";
64 integer mp_hlr_gsup_port := 4222;
65 integer mp_hlr_ctrl_port := 4259;
Alexander Couzens92696442020-01-10 07:57:16 +010066 /* how many auth tuples are expected
67 when IE ts_GSUP_IE_NUM_VECTORS_REQ is absent */
68 integer mp_default_num_auth_tuples := 5;
Oliver Smithdeb80a62019-11-29 16:01:54 +010069
Oliver Smith6e81f7e2020-01-29 14:25:41 +010070 /* emulated GSUP server (second HLR) */
71 charstring mp_hlr_ts_ip := "127.0.0.99";
72 integer mp_hlr_ts_port := 4222;
73
Oliver Smithdeb80a62019-11-29 16:01:54 +010074 /* drop after osmo-hlr release > 1.2.0 */
75 boolean mp_hlr_supports_dgsm := true;
Harald Weltedf327232017-12-28 22:51:51 +010076};
77
Harald Weltec2c52552018-03-01 21:20:39 +010078type record HlrSubscrAud2G {
79 charstring algo,
80 OCT16 ki
81}
82
83type record HlrSubscrAud3G {
84 charstring algo,
85 OCT16 k,
86 OCT16 op,
87 boolean op_is_opc
88}
89
90type record HlrSubscriber {
91 hexstring imsi,
92 hexstring msisdn,
93 HlrSubscrAud2G aud2g optional,
94 HlrSubscrAud3G aud3g optional
95}
96
97type record of HlrSubscriber HlrSubscriberList;
98
Harald Welteed380d12018-06-14 13:42:11 +020099type component HLR_ConnHdlr extends GSUP_ConnHdlr {
100 timer g_Tguard := 10.0;
101 var HLR_ConnHdlrPars g_pars;
102 port TELNETasp_PT VTY;
Oliver Smithdeb80a62019-11-29 16:01:54 +0100103 port MSLookup_mDNS_PT mDNS;
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100104
105 /* Pass from test_CT for explicit addressing */
106 var GSUP_Emulation_CT vc_GSUP_server;
107 var GSUP_Emulation_CT vc_GSUP_client;
108 var IPA_CCM_Parameters ccm_pars_client;
Harald Welteed380d12018-06-14 13:42:11 +0200109}
110
111type record HLR_ConnHdlrPars {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200112 HlrSubscriber sub,
113 HLR_ConnHdlrParsUssd ussd optional
114}
115
116type record HLR_ConnHdlrParsUssd {
117 OCT4 sid
Harald Welteed380d12018-06-14 13:42:11 +0200118}
119
120template (value) HLR_ConnHdlrPars t_Pars(hexstring imsi, hexstring msisdn := ''H) := {
121 sub := {
122 imsi := imsi,
123 msisdn := msisdn,
124 aud2g := omit,
125 aud3g := omit
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200126 },
127 ussd := omit
Harald Welteed380d12018-06-14 13:42:11 +0200128}
129
130template (value) HLR_ConnHdlrPars t_Pars_sub(HlrSubscriber sub) := {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200131 sub := sub,
132 ussd := omit
Harald Welteed380d12018-06-14 13:42:11 +0200133}
134
135type function void_fn() runs on HLR_ConnHdlr;
136
137/***********************************************************************
138 * Main Component
139 ***********************************************************************/
140
141function f_init_vty() runs on test_CT {
142 map(self:VTY, system:VTY);
143 f_vty_set_prompts(VTY);
144 f_vty_transceive(VTY, "enable");
Oliver Smithdeb80a62019-11-29 16:01:54 +0100145 if (mp_hlr_supports_dgsm) {
146 f_vty_config(VTY, "mslookup", "no mdns bind");
147 }
Harald Welteed380d12018-06-14 13:42:11 +0200148}
149
150private altstep as_Tguard() runs on test_CT {
151 [] g_Tguard.timeout {
152 setverdict(fail, "g_Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200153 mtc.stop;
Harald Welteed380d12018-06-14 13:42:11 +0200154 }
155}
156
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100157/* emulated GSUP client (MSC/SGSN) */
Harald Welteed380d12018-06-14 13:42:11 +0200158function f_init_gsup(charstring id, boolean legacy) runs on test_CT {
159 id := id & "-GSUP";
160 var GsupOps ops := {
161 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
162 }
163
164 ccm_pars := c_IPA_default_ccm_pars;
165 ccm_pars.name := "Osmocom TTCN-3 GSUP Simulator";
Harald Welte4a3242e2018-06-24 22:28:53 +0200166 ccm_pars.ser_nr := "MSC-00-00-00-00-00-00";
Harald Welteed380d12018-06-14 13:42:11 +0200167
168 vc_IPA := IPA_Emulation_CT.create(id & "-IPA");
169 log("legacy= ", legacy);
170 if (not legacy) {
171 log("in not legacy case 1");
172 vc_GSUP := GSUP_Emulation_CT.create(id);
173 }
174
175 map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
176 if (not legacy) {
177 log("in not legacy case 2");
178 connect(vc_GSUP:GSUP, vc_IPA:IPA_GSUP_PORT);
179 connect(vc_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
180 vc_GSUP.start(GSUP_Emulation.main(ops, id));
181 } else {
182 connect(vc_IPA:IPA_GSUP_PORT, self:GSUP);
183 }
184
185 vc_IPA.start(IPA_Emulation.main_client(mp_hlr_ip, mp_hlr_gsup_port, "", -1, ccm_pars));
186
187 /* wait for incoming connection to GSUP port before proceeding */
188 timer T := 10.0;
189 T.start;
190 alt {
191 [not legacy] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
192 [legacy] GSUP.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP}) { }
193 [] T.timeout {
194 setverdict(fail, "No connection to GSUP Port");
Daniel Willmannafce8662018-07-06 23:11:32 +0200195 mtc.stop;
Harald Welteed380d12018-06-14 13:42:11 +0200196 }
197 }
198}
199
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100200/* emulated GSUP server (second HLR) */
201function f_init_gsup_server(charstring id) runs on test_CT {
202 id := id & "-GSUP-server";
203 var GsupOps ops := {
204 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
205 }
206
207 vc_GSUP_server := GSUP_Emulation_CT.create(id);
208 vc_IPA_server := IPA_Emulation_CT.create(id & "-IPA");
209
210 connect(vc_GSUP_server:GSUP, vc_IPA_server:IPA_GSUP_PORT);
211 map(vc_IPA_server:IPA_PORT, system:IPA_CODEC_PT);
212
213 vc_GSUP_server.start(GSUP_Emulation.main(ops, id));
214 vc_IPA_server.start(IPA_Emulation.main_server(mp_hlr_ts_ip, mp_hlr_ts_port));
215}
216
Oliver Smithdeb80a62019-11-29 16:01:54 +0100217function f_init_mslookup() runs on test_CT {
218 vc_MSLookup_mDNS := MSLookup_mDNS_Emulation_CT.create;
219 vc_MSLookup_mDNS.start(MSLookup_mDNS_Emulation.f_main());
220}
221
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100222function f_init(boolean legacy := true, boolean gsup_server := false) runs on test_CT {
Harald Welteed380d12018-06-14 13:42:11 +0200223
224 /* activate default guard timer to ensure all tests eventually terminate */
225 g_Tguard.start;
226 activate(as_Tguard());
227
228 f_init_gsup("HLR_Test", legacy);
229 f_init_vty();
Oliver Smithdeb80a62019-11-29 16:01:54 +0100230 f_init_mslookup();
Harald Welteed380d12018-06-14 13:42:11 +0200231
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100232 if (gsup_server) {
233 f_init_gsup_server("HLR_Test");
234 }
235
Harald Welteed380d12018-06-14 13:42:11 +0200236 f_ipa_ctrl_start(mp_hlr_ip, mp_hlr_ctrl_port);
237}
238
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100239/*! Start HLR_ConnHdlr from testCT in a separate thread.
240 * \param void_fn function to run inside the thread.
241 * \param gsup_server if true, connect the emulated GSUP server ports to the new HLR_ConnHdlr. Then both the emulated
242 * GSUP client (MSC/SGSN) and server (second HLR) are connected. Explicit addressing with "to" and
243 * "from" must be used, i.e. 'GSUP.receive(tr_GSUP_UL_REQ(...)) from vc_GSUP_server'. */
244function f_start_handler(void_fn fn, HLR_ConnHdlrPars pars, boolean gsup_server := false) runs on test_CT
245return HLR_ConnHdlr {
Harald Welteed380d12018-06-14 13:42:11 +0200246 var HLR_ConnHdlr vc_conn;
247 var charstring id := testcasename();
248
249 vc_conn := HLR_ConnHdlr.create(id);
250 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
251 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
Oliver Smithdeb80a62019-11-29 16:01:54 +0100252 connect(vc_conn:mDNS, vc_MSLookup_mDNS:mDNS);
Harald Welteed380d12018-06-14 13:42:11 +0200253
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100254 if (gsup_server) {
255 connect(vc_conn:GSUP, vc_GSUP_server:GSUP_CLIENT);
256 connect(vc_conn:GSUP_PROC, vc_GSUP_server:GSUP_PROC);
257 vc_conn.start(f_handler_init(fn, id, vc_GSUP_server, vc_GSUP, ccm_pars, pars));
258 } else {
259 vc_conn.start(f_handler_init(fn, id, omit, vc_GSUP, ccm_pars, pars));
260 }
261
Harald Welteed380d12018-06-14 13:42:11 +0200262 return vc_conn;
263}
264
265private function f_handler_init_vty() runs on HLR_ConnHdlr {
266 map(self:VTY, system:VTY);
267 f_vty_set_prompts(VTY);
268 f_vty_transceive(VTY, "enable");
269}
270
271/* first function inside ConnHdlr component; sets g_pars + starts function */
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100272function f_handler_init(void_fn fn, charstring id,
273 template (omit) GSUP_Emulation_CT vc_GSUP_server_test_ct,
274 GSUP_Emulation_CT vc_GSUP_client_test_ct,
275 IPA_CCM_Parameters ccm_pars_client_test_ct,
276 template (omit) HLR_ConnHdlrPars pars := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200277runs on HLR_ConnHdlr
278{
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100279 /* Pass from test_CT for explicit addressing */
280 if (isvalue(vc_GSUP_server_test_ct)) {
281 vc_GSUP_server := valueof(vc_GSUP_server_test_ct);
282 }
283 vc_GSUP_client := vc_GSUP_client_test_ct;
284 ccm_pars_client := ccm_pars_client_test_ct;
285
Harald Welteed380d12018-06-14 13:42:11 +0200286 if (isvalue(pars)) {
287 g_pars := valueof(pars);
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100288 f_create_gsup_expect_explicit(hex2str(g_pars.sub.imsi), vc_GSUP_client);
Harald Welteed380d12018-06-14 13:42:11 +0200289 }
290 f_handler_init_vty();
291 fn.apply();
292}
293
294/***********************************************************************
295 * Subscriber creation via VTY
296 ***********************************************************************/
297
Harald Weltec2c52552018-03-01 21:20:39 +0100298template (value) HlrSubscriber t_SubNoAuth(hexstring imsi, hexstring msisdn) := {
299 imsi := imsi,
300 msisdn := msisdn,
301 aud2g := omit,
302 aud3g := omit
303}
304
305const OCT16 c_KI_DEFAULT := '000102030405060708090a0b0c0d0e0f'O;
306const OCT16 c_K_DEFAULT := '101112131415161718191a1b1c1d1e1f'O;
307const OCT16 c_OP_DEFAULT := '202122232425262728292a2b2c2d2e2f'O;
308//const OCT16 c_OPC_DEFAULT := '303132333435363738393a3b3c3d3f'O;
309
310template (value) HlrSubscriber t_Sub2G(hexstring imsi, hexstring msisdn, charstring algo) := {
311 imsi := imsi,
312 msisdn := msisdn,
313 aud2g := {
314 algo := algo,
315 ki := c_KI_DEFAULT
316 },
317 aud3g := omit
318}
319
320template (value) HlrSubscriber t_Sub3G(hexstring imsi, hexstring msisdn, charstring algo, boolean is_opc) := {
321 imsi := imsi,
322 msisdn := msisdn,
323 aud2g := omit,
324 aud3g := {
325 algo := algo,
326 k := c_K_DEFAULT,
327 op := c_OP_DEFAULT,
328 op_is_opc := is_opc
329 }
330}
331
332template (value) HlrSubscriber t_Sub2G3G(hexstring imsi, hexstring msisdn, charstring algo2g, charstring algo3g, boolean is_opc) := {
333 imsi := imsi,
334 msisdn := msisdn,
335 aud2g := {
336 algo := algo2g,
337 ki := c_KI_DEFAULT
338 },
339 aud3g := {
340 algo := algo3g,
341 k := c_K_DEFAULT,
342 op := c_OP_DEFAULT,
343 op_is_opc := is_opc
344 }
345}
346
347/* generate a variety of subscribers with different parameters */
348function f_gen_subs() runs on test_CT return HlrSubscriberList {
349 var HlrSubscriber sub;
350 var HlrSubscriberList sl := {};
351
352 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
353 sl := sl & { sub };
354
355 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v2"));
356 sl := sl & { sub };
357
358 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v3"));
359 sl := sl & { sub };
360
361 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", false));
362 sl := sl & { sub };
363
364 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", true));
365 sl := sl & { sub };
366
367 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
368 "comp128v1", "milenage", false));
369 sl := sl & { sub };
370
371 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
372 "comp128v2", "milenage", false));
373 sl := sl & { sub };
374
375 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
376 "comp128v3", "milenage", false));
377 sl := sl & { sub };
378
379 return sl;
380}
Harald Welteaf7c3182019-08-22 12:40:22 +0200381function f_gen_3G_subs() runs on test_CT return HlrSubscriberList {
382 var HlrSubscriber sub;
383 var HlrSubscriberList sl := {};
384
385 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", false));
386 sl := sl & { sub };
387
388 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", true));
389 sl := sl & { sub };
390
391 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
392 "comp128v1", "milenage", false));
393 sl := sl & { sub };
394
395 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
396 "comp128v2", "milenage", false));
397 sl := sl & { sub };
398
399 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
400 "comp128v3", "milenage", false));
401 sl := sl & { sub };
402
403 return sl;
404}
Harald Weltec2c52552018-03-01 21:20:39 +0100405
Harald Welteed380d12018-06-14 13:42:11 +0200406function f_vty_transceive_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
407 var charstring ret := f_vty_transceive_ret(pt, cmd);
408 if (not match(ret, exp_ret)) {
409 setverdict(fail, "Non-matching VTY response: ", ret);
Daniel Willmannafce8662018-07-06 23:11:32 +0200410 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100411 }
412}
413
Oliver Smith141620d2019-06-07 12:27:33 +0200414function f_vty_transceive_nomatch(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
415 var charstring ret := f_vty_transceive_ret(pt, cmd);
416 if (match(ret, exp_ret)) {
417 setverdict(fail, "Matching VTY response: ", ret, ", should *not* have matched: ", exp_ret);
418 mtc.stop;
419 }
420}
421
Harald Welte70296062018-03-01 22:42:03 +0100422private template (value) charstring t_subscr_prefix(hexstring imsi) :=
423 "subscriber imsi " & hex2str(imsi) & " ";
424
Harald Weltec2c52552018-03-01 21:20:39 +0100425/* create a given subscriber using the VTY */
Harald Welteed380d12018-06-14 13:42:11 +0200426function f_vty_subscr_create(TELNETasp_PT VTY, HlrSubscriber sub) {
Harald Welte70296062018-03-01 22:42:03 +0100427 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100428 f_vty_transceive_match(VTY, prefix & "create", pattern "% Created subscriber *");
429 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(sub.msisdn),
430 pattern "% Updated subscriber *");
431 if (ispresent(sub.aud2g)) {
432 f_vty_transceive_match(VTY, prefix & "update aud2g " & sub.aud2g.algo &
433 " ki " & oct2str(sub.aud2g.ki),
434 pattern "");
435 } else {
436 f_vty_transceive_match(VTY, prefix & "update aud2g none", pattern "");
437 }
438
439 if (ispresent(sub.aud3g)) {
440 var charstring op_mode := "op";
441 if (sub.aud3g.op_is_opc) {
442 op_mode := "opc";
443 }
444 f_vty_transceive_match(VTY, prefix & "update aud3g " & sub.aud3g.algo &
445 " k " & oct2str(sub.aud3g.k) & " " & op_mode & " " &
446 oct2str(sub.aud3g.op), pattern "");
447 } else {
448 f_vty_transceive_match(VTY, prefix & "update aud3g none", pattern "");
449 }
450}
451
Harald Welteed380d12018-06-14 13:42:11 +0200452function f_vty_subscr_update_msisdn(TELNETasp_PT VTY, HlrSubscriber sub, hexstring new_msisdn) {
Harald Welte09b3c502018-03-01 22:42:22 +0100453 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
454 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(new_msisdn),
455 pattern "% Updated subscriber *");
456}
457
Harald Weltec2c52552018-03-01 21:20:39 +0100458/* perform 'delete' on subscriber */
Harald Welteed380d12018-06-14 13:42:11 +0200459function f_vty_subscr_delete(TELNETasp_PT VTY, HlrSubscriber sub) {
Harald Welte70296062018-03-01 22:42:03 +0100460 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100461 f_vty_transceive_match(VTY, prefix & "delete",
462 pattern "% Deleted subscriber for IMSI *");
463}
464
465/* perform 'show' on subscriber; match result with pattern 'exp' */
Harald Welteed380d12018-06-14 13:42:11 +0200466function f_vty_subscr_show(TELNETasp_PT VTY, HlrSubscriber sub, template charstring exp) {
Harald Welte70296062018-03-01 22:42:03 +0100467 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100468 f_vty_transceive_match(VTY, prefix & "show", exp);
469}
470
Oliver Smith141620d2019-06-07 12:27:33 +0200471/* perform 'show' on subscriber; result must not match with pattern 'exp' */
472function f_vty_subscr_show_nomatch(TELNETasp_PT VTY, HlrSubscriber sub, template charstring exp) {
473 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
474 f_vty_transceive_nomatch(VTY, prefix & "show", exp);
475}
Harald Weltec2c52552018-03-01 21:20:39 +0100476
Harald Welteed380d12018-06-14 13:42:11 +0200477/***********************************************************************
478 * Helper functions for ConnHdlr
479 ***********************************************************************/
480
Harald Weltec2c52552018-03-01 21:20:39 +0100481/* perform SendAuthInfo for given imsi, return the GSUP response/error */
Harald Welteaf7c3182019-08-22 12:40:22 +0200482function f_perform_SAI(hexstring imsi, template (omit) integer exp_err_cause := omit,
Alexander Couzens92696442020-01-10 07:57:16 +0100483 boolean is_eps := false, template (omit) integer num_auth_tuple := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200484runs on HLR_ConnHdlr return GSUP_PDU {
Alexander Couzens92696442020-01-10 07:57:16 +0100485 var template GSUP_PDU sai_msg;
Harald Weltec2c52552018-03-01 21:20:39 +0100486 var GSUP_PDU ret;
487 timer T := 3.0;
488 var boolean exp_fail := false;
489 if (not istemplatekind(exp_err_cause, "omit")) {
490 exp_fail := true;
491 }
492
Harald Welteaf7c3182019-08-22 12:40:22 +0200493 if (is_eps) {
Alexander Couzens92696442020-01-10 07:57:16 +0100494 sai_msg := ts_GSUP_SAI_REQ_EPS(imsi);
Harald Welteaf7c3182019-08-22 12:40:22 +0200495 } else {
Alexander Couzens92696442020-01-10 07:57:16 +0100496 sai_msg := ts_GSUP_SAI_REQ(imsi);
Harald Welteaf7c3182019-08-22 12:40:22 +0200497 }
Alexander Couzens92696442020-01-10 07:57:16 +0100498 if (not istemplatekind(num_auth_tuple, "omit")) {
499 sai_msg.ies := valueof(sai_msg.ies) & {
500 valueof(ts_GSUP_IE_NUM_VECTORS_REQ(int2oct(valueof(num_auth_tuple), 1)))
501 };
502 }
503 GSUP.send(sai_msg);
504
Harald Weltec2c52552018-03-01 21:20:39 +0100505 T.start;
506 alt {
507 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, exp_err_cause)) -> value ret {
508 setverdict(pass);
509 }
510 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
511 setverdict(fail, "Unexpected SAI ERROR Cause");
512 }
513 [exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
514 setverdict(fail, "Unexpected SAI.res for unknown IMSI");
515 }
516 [not exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
517 setverdict(fail, "Unexpected SAI ERROR");
518 }
519 [not exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
520 setverdict(pass);
521 }
522 [] GSUP.receive { repeat; }
523 [] T.timeout {
524 setverdict(fail, "Timeout waiting for SAI response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200525 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100526 }
527 }
528 return ret;
529}
530
531function f_perform_UL(hexstring imsi, template hexstring msisdn,
Oliver Smith62a1c632020-01-15 15:58:54 +0100532 template (omit) integer exp_err_cause := omit,
533 GSUP_CnDomain dom := OSMO_GSUP_CN_DOMAIN_PS)
Harald Welteed380d12018-06-14 13:42:11 +0200534runs on HLR_ConnHdlr return GSUP_PDU {
Harald Weltec2c52552018-03-01 21:20:39 +0100535 var GSUP_PDU ret;
536 timer T := 3.0;
537 var boolean exp_fail := false;
538 var boolean isd_done := false;
539 if (not istemplatekind(exp_err_cause, "omit")) {
540 exp_fail := true;
541 }
542
Oliver Smith62a1c632020-01-15 15:58:54 +0100543 GSUP.send(valueof(ts_GSUP_UL_REQ(imsi, dom)));
Harald Weltec2c52552018-03-01 21:20:39 +0100544 T.start;
545 alt {
546 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, exp_err_cause)) -> value ret {
547 setverdict(pass);
548 }
549 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
550 setverdict(fail, "Unexpected UL ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100551 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100552 }
553 [exp_fail] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
554 setverdict(fail, "Unexpected UL.res for unknown IMSI");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100555 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100556 }
557 [exp_fail] GSUP.receive(tr_GSUP_ISD_REQ(imsi)) -> value ret {
558 setverdict(fail, "Unexpected ISD.req in error case");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100559 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100560 }
561 [not exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?)) -> value ret {
562 setverdict(fail, "Unexpected UL ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100563 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100564 }
565 [not exp_fail and not isd_done] GSUP.receive(tr_GSUP_ISD_REQ(imsi, msisdn)) -> value ret {
566 GSUP.send(ts_GSUP_ISD_RES(imsi));
567 isd_done := true;
Harald Welte8f0c9332018-03-01 23:38:40 +0100568 repeat;
Harald Weltec2c52552018-03-01 21:20:39 +0100569 }
570 [not exp_fail and isd_done] GSUP.receive(tr_GSUP_UL_RES(imsi)) -> value ret {
571 setverdict(pass);
572 }
573 [] GSUP.receive { repeat; }
574 [] T.timeout {
575 setverdict(fail, "Timeout waiting for UL response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200576 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100577 }
578 }
579 return ret;
580}
581
Oliver Smithb51a53f2020-01-29 15:06:54 +0100582/* Perform Location Update with IMSI that is unknown to OsmoHLR. Let it ask for the HLR that knows the IMSI via
583 * mslookup. The TTCN-3 testsuite pretends to be the home HLR, that knows the IMSI. The proxy HLR connects to the
584 * home HLR and forwards GSUP messages, until LU is complete.
585 * Make sure to let a timer run while calling this function (see TC_MSLookup_GSUP_proxy). */
586function f_perform_UL_proxy(hexstring imsi, hexstring msisdn, GSUP_CnDomain dom := OSMO_GSUP_CN_DOMAIN_PS)
587runs on HLR_ConnHdlr {
588 var MSLookup_mDNS mdns_msg;
589 var integer id;
590 var charstring domain := "gsup.hlr." & hex2str(imsi) & ".imsi.mdns.osmocom.org";
591 var octetstring destination_name := char2oct(ccm_pars_client.ser_nr) & '00'O; /* TS-MSC IPA name */
592
593 /* Testing the HLR as proxy. The MSC asking the proxy and the home HLR are both enacted by TTCN3 (TS).
594 * MSC=vc_GSUP_client <---> osmo-hlr as proxy <---> vc_GSUP_server=home HLR
595 * GSUP.send(..) to vc_GSUP_client ---> osmo-hlr ---> GSUP.receive(..) from vc_GSUP_server
596 * GSUP.receive(..) from vc_GSUP_client <--- osmo-hlr <--- GSUP.send(..) to vc_GSUP_server */
597
598 /* [GSUP] TS-MSC => HLR proxy: Update Location Request with unknown IMSI */
599 GSUP.send(ts_GSUP_UL_REQ(imsi, dom)) to vc_GSUP_client;
600
601 /* [GSUP] TS-HLR: expect GSUP messages with that IMSI */
602 f_create_gsup_expect_explicit(hex2str(imsi), vc_GSUP_server);
603
604 /* [mDNS] TS-HLR <= HLR proxy: query for GSUP server who knows the IMSI */
605 mDNS.receive(tr_MSLookup_mDNS_query(domain)) -> value mdns_msg;
606
607 /* [mDNS] TS-HLR => HLR proxy: result with IP/port of TS GSUP server */
608 id := mdns_msg.dnsMessage.header.id;
609 mDNS.send(ts_MSLookup_mDNS_result_IPv4(id, domain, f_enc_IPv4(mp_hlr_ts_ip), mp_hlr_ts_port));
610
611 /* [GSUP] TS-HLR <=> HLR proxy <=> TS-MSC: finish up UL */
612 GSUP.receive(tr_GSUP_UL_REQ(imsi)) from vc_GSUP_server;
613 GSUP.send(ts_GSUP_ISD_REQ(imsi, msisdn, destination_name)) to vc_GSUP_server;
614 GSUP.receive(tr_GSUP_ISD_REQ(imsi, g_pars.sub.msisdn)) from vc_GSUP_client;
615 GSUP.send(ts_GSUP_ISD_RES(imsi, destination_name)) to vc_GSUP_server;
616 GSUP.receive(tr_GSUP_ISD_RES(imsi)) from vc_GSUP_client;
617 GSUP.send(ts_GSUP_UL_RES(imsi, destination_name)) to vc_GSUP_server;
618 GSUP.receive(tr_GSUP_UL_RES(imsi)) from vc_GSUP_client;
619}
620
Harald Welte958f8b42018-03-01 23:40:17 +0100621/* perform PurgeMS for given imsi, return the GSUP response/error */
622function f_perform_PURGE(hexstring imsi, GSUP_CnDomain cn_dom,
623 template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200624runs on HLR_ConnHdlr return GSUP_PDU {
Harald Welte958f8b42018-03-01 23:40:17 +0100625 var GSUP_PDU ret;
626 timer T := 3.0;
627 var boolean exp_fail := false;
628 if (not istemplatekind(exp_err_cause, "omit")) {
629 exp_fail := true;
630 }
631
632 GSUP.send(valueof(ts_GSUP_PURGE_MS_REQ(imsi, cn_dom)));
633 T.start;
634 alt {
635 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, exp_err_cause)) -> value ret {
636 setverdict(pass);
637 }
638 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
639 setverdict(fail, "Unexpected PURGE ERROR Cause");
640 }
641 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
642 setverdict(fail, "Unexpected PURGE.res for unknown IMSI");
643 }
644 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
645 setverdict(fail, "Unexpected PURGE ERROR");
646 }
647 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
648 setverdict(pass);
649 }
650 [] GSUP.receive { repeat; }
651 [] T.timeout {
652 setverdict(fail, "Timeout waiting for PURGE response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200653 mtc.stop;
Harald Welte958f8b42018-03-01 23:40:17 +0100654 }
655 }
656 return ret;
657}
658
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200659function f_SS_xceive(hexstring imsi, OCT4 sid, GSUP_SessionState state, octetstring ss,
660 template (omit) integer exp_err_cause := omit)
661runs on HLR_ConnHdlr return GSUP_PDU {
662 var GSUP_PDU ret;
663 timer T := 3.0;
664 var boolean exp_fail := false;
665 if (not istemplatekind(exp_err_cause, "omit")) {
666 exp_fail := true;
667 }
668
669 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(imsi, sid, state, ss)));
670 T.start;
671 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700672 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, exp_err_cause)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200673 setverdict(pass);
674 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700675 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200676 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
677 }
678 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
679 setverdict(fail, "Unexpected PROC_SS.res for unknown IMSI");
680 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700681 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200682 setverdict(fail, "Unexpected PROC_SS ERROR");
683 }
684 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
685 setverdict(pass);
686 }
687 [] GSUP.receive { repeat; }
688 [] T.timeout {
689 setverdict(fail, "Timeout waiting for PROC_SS response");
690 self.stop;
691 }
692 }
693 return ret;
694}
695
696private function f_SS_expect(hexstring imsi, OCT4 sid, GSUP_SessionState state,
697 template SS_FacilityInformation facility := *)
698runs on HLR_ConnHdlr return GSUP_PDU {
699 var GSUP_PDU ret;
700 timer T := 3.0;
701 var boolean exp_ss := true;
702 if (istemplatekind(facility, "omit")) {
703 exp_ss := false;
704 }
705 T.start;
706 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700707 [] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200708 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100709 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200710 }
711 [not exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
712 setverdict(pass);
713 }
714 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
715 setverdict(fail, "Unexpected PROC_SS.res without SS IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100716 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200717 }
718/*
719 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, decmatch facility)) -> value ret {
720 setverdict(pass);
721 }
722*/
723
724 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, ?)) -> value ret {
725 var GSUP_IeValue ss_ie;
726 f_gsup_find_ie(ret, OSMO_GSUP_SS_INFO_IE, ss_ie);
727 var SS_FacilityInformation dec_fac := dec_SS_FacilityInformation(ss_ie.ss_info);
728 log("pattern: ", facility);
729 if (match(dec_fac, facility)) {
730 setverdict(pass);
731 } else {
732 setverdict(fail, "Unexpected PROC_SS.res with non-matching facility IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100733 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200734 }
735 }
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100736 [] GSUP.receive {
737 setverdict(fail, "Unexpected GSUP");
738 mtc.stop;
739 }
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200740 [] T.timeout {
741 setverdict(fail, "Timeout waiting for PROC_SS response");
742 self.stop;
743 }
744 }
745
746 return ret;
747}
748
Oliver Smith936dbe62019-06-04 15:54:17 +0200749function f_perform_CHECK_IMEI(hexstring imsi, hexstring imei,
750 template (omit) integer exp_err_cause := omit,
751 template (omit) GSUP_IMEIResult result := omit)
752runs on HLR_ConnHdlr {
753 var GSUP_PDU pdu;
754 timer T := 3.0;
755 var boolean exp_fail := false;
756 if (not istemplatekind(exp_err_cause, "omit")) {
757 exp_fail := true;
758 }
759
760 GSUP.send(valueof(ts_GSUP_CHECK_IMEI_REQ(imsi, imei)));
761 T.start;
762 alt {
763 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, exp_err_cause)) -> value pdu {
764 setverdict(pass);
765 }
766 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?)) -> value pdu {
767 setverdict(fail, "Unexpected CHECK IMEI ERROR Cause: ", pdu);
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100768 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200769 }
770 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?)) -> value pdu {
771 setverdict(fail, "Unexpected CHECK IMEI RES instead of ERR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100772 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200773 }
774 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?)) -> value pdu {
775 setverdict(fail, "Unexpected CHECK IMEI ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100776 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200777 }
778 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, result)) -> value pdu {
779 setverdict(pass);
780 }
781 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?)) -> value pdu {
782 setverdict(fail, "Unexpected CHECK IMEI RES");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100783 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200784 }
785 [] GSUP.receive { repeat; }
786 [] T.timeout {
787 setverdict(fail, "Timeout waiting for CHECK IMEI response");
788 mtc.stop;
789 }
790 }
791}
792
793
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200794
Harald Welte958f8b42018-03-01 23:40:17 +0100795
Harald Welteed380d12018-06-14 13:42:11 +0200796/***********************************************************************
797 * Testcases
798 ***********************************************************************/
799
800/* 23.003 Section 2.2 clearly states that an IMSI with less
801 * than 5 digits is impossible. Even 5 digits is still questionable */
802private function f_TC_gsup_sai_err_invalid_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100803 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200804 res := f_perform_SAI(g_pars.sub.imsi, 96); /* Invalid Mandatory information */
805 setverdict(pass);
806}
807testcase TC_gsup_sai_err_invalid_imsi() runs on test_CT {
808 var HLR_ConnHdlr vc_conn;
809 var HLR_ConnHdlrPars pars := valueof(t_Pars('0123'H));
810 f_init(false);
811 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_invalid_imsi), pars);
812 vc_conn.done;
813}
Harald Weltec2c52552018-03-01 21:20:39 +0100814
Harald Weltec2c52552018-03-01 21:20:39 +0100815
Harald Welteed380d12018-06-14 13:42:11 +0200816private function f_TC_gsup_sai_err_unknown_imsi() runs on HLR_ConnHdlr {
817 var GSUP_PDU res;
818 res := f_perform_SAI(g_pars.sub.imsi, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100819 setverdict(pass);
820}
821
Harald Welte3f662762018-03-02 10:48:20 +0100822testcase TC_gsup_sai_err_unknown_imsi() runs on test_CT {
Harald Welteed380d12018-06-14 13:42:11 +0200823 var HLR_ConnHdlr vc_conn;
824 var HLR_ConnHdlrPars pars := valueof(t_Pars(f_rnd_imsi('26242'H)));
825 f_init(false);
826 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_unknown_imsi), pars);
827 vc_conn.done;
Harald Welte3f662762018-03-02 10:48:20 +0100828}
829
Harald Welteed380d12018-06-14 13:42:11 +0200830function f_start_handler_per_sub(void_fn fn, HlrSubscriberList sl) runs on test_CT {
831 for (var integer i := 0; i < sizeof(sl); i := i+1) {
832 var HlrSubscriber sub := sl[i];
833 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sub));
834 var HLR_ConnHdlr vc_conn;
835
836 f_vty_subscr_create(VTY, sub);
837 vc_conn := f_start_handler(fn, pars);
838 vc_conn.done;
839 f_vty_subscr_delete(VTY, sub);
840 }
841}
Harald Welte3f662762018-03-02 10:48:20 +0100842
Harald Weltec2c52552018-03-01 21:20:39 +0100843/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
Harald Welteed380d12018-06-14 13:42:11 +0200844private function f_TC_gsup_sai() runs on HLR_ConnHdlr {
845 var GSUP_PDU res;
846 res := f_perform_SAI(g_pars.sub.imsi);
Harald Welte4b612042019-12-03 20:08:57 +0100847 if (ispresent(g_pars.sub.aud3g)) {
848 f_ensure_amf_separation_bit(res, '0'B);
849 }
Alexander Couzens92696442020-01-10 07:57:16 +0100850
851 f_count_auth_tuples(res, mp_default_num_auth_tuples);
Harald Welteed380d12018-06-14 13:42:11 +0200852 setverdict(pass);
853}
Harald Weltec2c52552018-03-01 21:20:39 +0100854testcase TC_gsup_sai() runs on test_CT {
855 var HlrSubscriberList sl;
856 var GSUP_PDU res;
857
Harald Welteed380d12018-06-14 13:42:11 +0200858 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100859
860 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200861 f_start_handler_per_sub(refers(f_TC_gsup_sai), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100862
863 setverdict(pass);
864}
865
Alexander Couzens92696442020-01-10 07:57:16 +0100866/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
867private function f_TC_gsup_sai_num_auth_vectors() runs on HLR_ConnHdlr {
868 var GSUP_PDU res;
869 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 1);
870 f_count_auth_tuples(res, 1);
871 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 4);
872 f_count_auth_tuples(res, 4);
873 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 5);
874 f_count_auth_tuples(res, 5);
875 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 254);
876 f_count_auth_tuples(res, 5);
877 setverdict(pass);
878}
879testcase TC_gsup_sai_num_auth_vectors() runs on test_CT {
880 var HlrSubscriberList sl;
881 var GSUP_PDU res;
882
883 f_init(false);
884
885 sl := f_gen_subs();
886 f_start_handler_per_sub(refers(f_TC_gsup_sai_num_auth_vectors), sl);
887
888 setverdict(pass);
889}
890
Harald Welteaf7c3182019-08-22 12:40:22 +0200891private function f_ensure_amf_separation_bit(GSUP_PDU res, BIT1 sep_bit)
892{
893 for (var integer i := 0; i < lengthof(res.ies); i := i+1) {
894 var GSUP_IE tuple := res.ies[i];
895 if (tuple.tag != OSMO_GSUP_AUTH_TUPLE_IE) {
896 continue;
897 }
898 var GSUP_IeValue autn;
899 if (f_gsup_find_nested_ie(tuple.val.auth_tuple, OSMO_GSUP_AUTN_IE, autn) == false) {
900 setverdict(fail, "Couldn't find AUTN IE in tuple ", i);
901 mtc.stop;
902 }
903 var bitstring amf := oct2bit(substr(autn.autn, 6, 2));
904 if (amf[0] != sep_bit) {
905 setverdict(fail, "AMF bit 0 (separation bit) must be ", sep_bit," but was not");
906 mtc.stop;
907 }
908 }
909}
910
Alexander Couzens92696442020-01-10 07:57:16 +0100911private function f_count_auth_tuples(GSUP_PDU res, template (omit) integer expected_auth_tuples := omit)
912{
913 var integer auth_tuples := 0;
914 for (var integer i := 0; i < lengthof(res.ies); i := i+1) {
915 var GSUP_IE tuple := res.ies[i];
916 if (tuple.tag == OSMO_GSUP_AUTH_TUPLE_IE) {
917 auth_tuples := auth_tuples + 1;
918 }
919 }
920
921 if ((not istemplatekind(expected_auth_tuples, "omit")) and
922 not match(auth_tuples, valueof(expected_auth_tuples))) {
923 setverdict(fail,
924 "Did not received expected number of auth tuples. Expected ",
925 mp_default_num_auth_tuples,
926 " but received ", auth_tuples);
927 }
928}
929
Harald Welteaf7c3182019-08-22 12:40:22 +0200930/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
931private function f_TC_gsup_sai_eps() runs on HLR_ConnHdlr {
932 var GSUP_PDU res;
933 res := f_perform_SAI(g_pars.sub.imsi, is_eps := true);
934 f_ensure_amf_separation_bit(res, '1'B);
935
936 /* TODO: match if tuple[s] matches expectation */
937 setverdict(pass);
938}
939testcase TC_gsup_sai_eps() runs on test_CT {
940 var HlrSubscriberList sl;
941 var GSUP_PDU res;
942
943 f_init(false);
944
945 sl := f_gen_3G_subs();
946 f_start_handler_per_sub(refers(f_TC_gsup_sai_eps), sl);
947
948 setverdict(pass);
949}
950
951
Harald Weltec2c52552018-03-01 21:20:39 +0100952/* test UL for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200953private function f_TC_ul_unknown_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100954 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200955 res := f_perform_UL(g_pars.sub.imsi, ?, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100956 setverdict(pass);
957}
Harald Welteed380d12018-06-14 13:42:11 +0200958testcase TC_gsup_ul_unknown_imsi() runs on test_CT {
959 var hexstring imsi := f_rnd_imsi('26242'H);
960 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
961 var HLR_ConnHdlr vc_conn;
Harald Weltec2c52552018-03-01 21:20:39 +0100962
Harald Welteed380d12018-06-14 13:42:11 +0200963 f_init(false);
964 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
965 vc_conn.done;
966}
967
968/* test UL for a number of different subscriber cases (algo, 2g/3g, ...) */
969private function f_TC_gsup_ul() runs on HLR_ConnHdlr {
970 var GSUP_PDU res;
971 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
972 setverdict(pass);
973}
Harald Weltec2c52552018-03-01 21:20:39 +0100974testcase TC_gsup_ul() runs on test_CT {
975 var HlrSubscriberList sl;
976 var GSUP_PDU res;
977
Harald Welteed380d12018-06-14 13:42:11 +0200978 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100979 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200980 f_start_handler_per_sub(refers(f_TC_gsup_ul), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100981
982 setverdict(pass);
983}
984
985/* Test only the VTY commands */
986testcase TC_vty() runs on test_CT {
987 var HlrSubscriber sub;
988
989 f_init();
990
991 /* we're not using f_gen_subs() here as the expect pattern for the 'show' are different
992 * from case to case */
993 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
Harald Welteed380d12018-06-14 13:42:11 +0200994 f_vty_subscr_create(VTY, sub);
995 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*");
996 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +0100997
998 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
999 "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +02001000 f_vty_subscr_create(VTY, sub);
1001 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *3G auth: MILENAGE*");
1002 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +01001003
1004 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
1005 "comp128v1", "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +02001006 f_vty_subscr_create(VTY, sub);
1007 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*3G auth: MILENAGE*");
1008 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +01001009
1010 setverdict(pass);
1011}
1012
Harald Welte09b3c502018-03-01 22:42:22 +01001013/* VTY changes to MSISDN should result in ISD to current VLR */
Harald Welteed380d12018-06-14 13:42:11 +02001014private function f_TC_vty_msisdn_isd() runs on HLR_ConnHdlr {
Harald Welte09b3c502018-03-01 22:42:22 +01001015 var hexstring new_msisdn;
1016 var GSUP_PDU res;
1017 timer T := 5.0;
1018
Harald Welte09b3c502018-03-01 22:42:22 +01001019 /* Create Subscriber */
Harald Welteed380d12018-06-14 13:42:11 +02001020 f_vty_subscr_create(VTY, g_pars.sub);
Harald Welte09b3c502018-03-01 22:42:22 +01001021
1022 /* Perform UpdateLocation (VLR now known to HLR) */
Harald Welteed380d12018-06-14 13:42:11 +02001023 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +01001024
1025 /* Then change IMSI via VTY */
1026 new_msisdn := '49161'H & f_rnd_hexstring(7, 9);
Harald Welteed380d12018-06-14 13:42:11 +02001027 f_vty_subscr_update_msisdn(VTY, g_pars.sub, new_msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +01001028 /* And expect InsertSubscriberData as result */
1029 T.start;
1030 alt {
Harald Welteed380d12018-06-14 13:42:11 +02001031 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, new_msisdn)) {
1032 GSUP.send(ts_GSUP_ISD_RES(g_pars.sub.imsi));
1033 g_pars.sub.msisdn := new_msisdn;
Harald Welte09b3c502018-03-01 22:42:22 +01001034 setverdict(pass);
1035 }
Harald Welteed380d12018-06-14 13:42:11 +02001036 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, g_pars.sub.msisdn)) {
Stefan Sperling7c096872018-04-09 11:24:22 +02001037 log("received ISD req with old MSISDN");
1038 setverdict(fail);
1039 }
Harald Welte09b3c502018-03-01 22:42:22 +01001040 [] GSUP.receive { repeat; }
1041 [] T.timeout {
1042 setverdict(fail, "Timeout waiting for ISD.req");
1043 }
1044 }
1045}
Harald Welteed380d12018-06-14 13:42:11 +02001046testcase TC_vty_msisdn_isd() runs on test_CT {
1047 var HlrSubscriber sub;
1048 var HLR_ConnHdlr vc_conn;
1049
1050 f_init(false);
1051
1052 /* Create Subscriber */
1053 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
1054
1055 vc_conn := f_start_handler(refers(f_TC_vty_msisdn_isd), valueof(t_Pars_sub(sub)));
1056 vc_conn.done;
1057}
Harald Welte09b3c502018-03-01 22:42:22 +01001058
Harald Welte958f8b42018-03-01 23:40:17 +01001059/* Test PURGE MS for CS services */
Harald Welteed380d12018-06-14 13:42:11 +02001060private function f_TC_gsup_purge_cs() runs on HLR_ConnHdlr {
1061 var GSUP_PDU res;
1062 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
1063 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS);
1064}
Harald Welte958f8b42018-03-01 23:40:17 +01001065testcase TC_gsup_purge_cs() runs on test_CT {
1066 var HlrSubscriberList sl;
1067 var GSUP_PDU res;
1068
Harald Welteed380d12018-06-14 13:42:11 +02001069 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +01001070 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +02001071 f_start_handler_per_sub(refers(f_TC_gsup_purge_cs), sl);
Harald Welte958f8b42018-03-01 23:40:17 +01001072
1073 setverdict(pass);
1074}
1075
1076/* Test PURGE MS for PS services */
Harald Welteed380d12018-06-14 13:42:11 +02001077private function f_TC_gsup_purge_ps() runs on HLR_ConnHdlr {
1078 var GSUP_PDU res;
1079 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
1080 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_PS);
1081}
Harald Welte958f8b42018-03-01 23:40:17 +01001082testcase TC_gsup_purge_ps() runs on test_CT {
1083 var HlrSubscriberList sl;
Harald Welte958f8b42018-03-01 23:40:17 +01001084
Harald Welteed380d12018-06-14 13:42:11 +02001085 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +01001086 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +02001087 f_start_handler_per_sub(refers(f_TC_gsup_purge_ps), sl);
Harald Welte958f8b42018-03-01 23:40:17 +01001088
1089 setverdict(pass);
1090}
1091
1092/* Test PURGEG MS procedure for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +02001093
1094private function f_TC_gsup_purge_unknown() runs on HLR_ConnHdlr {
1095 var GSUP_PDU res;
1096 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS, 2);
1097}
Harald Welte958f8b42018-03-01 23:40:17 +01001098testcase TC_gsup_purge_unknown() runs on test_CT {
1099 var hexstring imsi := '2345743413463'H;
Harald Welteed380d12018-06-14 13:42:11 +02001100 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1101 var HLR_ConnHdlr vc_conn;
Harald Welte958f8b42018-03-01 23:40:17 +01001102
Harald Welteed380d12018-06-14 13:42:11 +02001103 f_init(false);
1104 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
1105 vc_conn.done;
Harald Welte958f8b42018-03-01 23:40:17 +01001106
1107 setverdict(pass);
1108}
1109
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001110import from HLR_EUSE all;
1111
1112/* Test for USSD request to undefined/unrouted short-code. Expect ss-NotAvailable(18) */
1113private function f_TC_mo_ussd_unknown() runs on HLR_ConnHdlr {
1114 var GSUP_PDU res;
1115 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1116 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1117 ussd_string := "*#200#");
1118 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1119 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001120 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1121 OSMO_GSUP_SESSION_STATE_END,
1122 tr_SS_FACILITY_RETURN_ERROR(1, 18));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001123}
1124testcase TC_mo_ussd_unknown() runs on test_CT {
1125 var HlrSubscriberList sl;
1126 var HLR_ConnHdlr vc_conn;
1127
1128 f_init(false);
1129 sl := f_gen_subs();
1130 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1131 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1132 pars.ussd.sid := f_rnd_octstring(4);
1133 f_vty_subscr_create(VTY, pars.sub);
1134 vc_conn := f_start_handler(refers(f_TC_mo_ussd_unknown), pars);
1135 vc_conn.done;
1136 }
1137}
1138
1139/* Test for USSD request to currently disconnected EUSE. Expect ss-SystemFailure(34) */
1140private function f_TC_mo_ussd_euse_disc() runs on HLR_ConnHdlr {
1141 var GSUP_PDU res;
1142 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1143 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)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001147 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1148 OSMO_GSUP_SESSION_STATE_END,
1149 tr_SS_FACILITY_RETURN_ERROR(1, 34));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001150}
1151testcase TC_mo_ussd_euse_disc() runs on test_CT {
1152 var HlrSubscriberList sl;
1153 var HLR_ConnHdlr vc_conn;
1154
1155 f_init(false);
1156 sl := f_gen_subs();
1157 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1158 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1159 pars.ussd.sid := f_rnd_octstring(4);
1160 f_vty_subscr_create(VTY, pars.sub);
1161 vc_conn := f_start_handler(refers(f_TC_mo_ussd_euse_disc), pars);
1162 vc_conn.done;
1163 }
1164}
1165
1166/* Test for USSD request to internal own-imsi IUSE. */
1167private function f_TC_mo_ussd_iuse_imsi() runs on HLR_ConnHdlr {
1168 var GSUP_PDU res;
1169 var charstring resp_str;
1170 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1171 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1172 ussd_string := "*#101#");
1173 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1174 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1175 resp_str := "Your IMSI is " & hex2str(g_pars.sub.imsi);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001176 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1177 OSMO_GSUP_SESSION_STATE_END,
1178 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1179 f_encGSM7bit(resp_str)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001180}
1181testcase TC_mo_ussd_iuse_imsi() runs on test_CT {
1182 var HlrSubscriberList sl;
1183 var HLR_ConnHdlr vc_conn;
1184
1185 f_init(false);
1186 sl := f_gen_subs();
1187 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1188 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1189 pars.ussd.sid := f_rnd_octstring(4);
1190 f_vty_subscr_create(VTY, pars.sub);
1191 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_imsi), pars);
1192 vc_conn.done;
1193 }
1194}
1195
1196/* Test for USSD request to internal own-msisdn IUSE. */
1197private function f_TC_mo_ussd_iuse_msisdn() runs on HLR_ConnHdlr {
1198 var GSUP_PDU res;
1199 var charstring resp_str;
1200 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1201 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1202 ussd_string := "*#100#");
1203 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1204 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1205 resp_str := "Your extension is " & hex2str(g_pars.sub.msisdn);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001206 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1207 OSMO_GSUP_SESSION_STATE_END,
1208 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1209 f_encGSM7bit(resp_str)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001210}
1211testcase TC_mo_ussd_iuse_msisdn() runs on test_CT {
1212 var HlrSubscriberList sl;
1213 var HLR_ConnHdlr vc_conn;
1214
1215 f_init(false);
1216 sl := f_gen_subs();
1217 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1218 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1219 pars.ussd.sid := f_rnd_octstring(4);
1220 f_vty_subscr_create(VTY, pars.sub);
1221 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_msisdn), pars);
1222 vc_conn.done;
1223 }
1224}
1225
1226/* Test routing of USSD to EUSE by a specific route */
1227private function f_TC_mo_ussd_100() runs on HLR_ConnHdlr {
1228 var GSUP_PDU res;
1229 /* invoke / invoke id 1 / processUSS-req */
1230 //var octetstring ss := 'a11202010102013b300a04010f0405aa180c3602'O;
1231 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1232 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1233 ussd_string := "*100#");
1234 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1235 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001236 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1237 OSMO_GSUP_SESSION_STATE_END,
1238 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1239 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001240}
1241testcase TC_mo_ussd_euse() runs on test_CT {
1242 var HlrSubscriberList sl;
1243 var HLR_ConnHdlr vc_conn;
1244
1245 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1246 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
1247
1248 f_init(false);
1249 sl := f_gen_subs();
1250 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1251 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1252 pars.ussd.sid := f_rnd_octstring(4);
1253 f_vty_subscr_create(VTY, pars.sub);
1254 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100), pars);
1255 vc_conn.done;
1256 }
1257
1258 vc_EUSE.stop;
1259}
1260
1261/* Test routing of USSD to EUSE by a specific route, with CONTINUE */
1262private function f_TC_mo_ussd_100_continue() runs on HLR_ConnHdlr {
1263 var GSUP_PDU res;
1264 /* Simulate BEGIN from MS/MSC */
1265 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1266 ussd_string := "*100#");
1267 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1268 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1269 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001270 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1271 OSMO_GSUP_SESSION_STATE_CONTINUE,
1272 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1273 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001274
1275 /* Simulate CONTINUE from MS/MSC */
1276 ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1277 ussd_string := "mahlzeit");
1278 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1279 OSMO_GSUP_SESSION_STATE_CONTINUE, ss)));
1280
1281 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001282 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1283 OSMO_GSUP_SESSION_STATE_END,
1284 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1285 f_encGSM7bit("mahlzeit")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001286}
1287testcase TC_mo_ussd_euse_continue() runs on test_CT {
1288 var HlrSubscriberList sl;
1289 var HLR_ConnHdlr vc_conn;
1290
1291 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1292 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar",
1293 refers(f_ss_echo_continue)));
1294
1295 f_init(false);
1296 sl := f_gen_subs();
1297 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1298 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1299 pars.ussd.sid := f_rnd_octstring(4);
1300 f_vty_subscr_create(VTY, pars.sub);
1301 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100_continue), pars);
1302 vc_conn.done;
1303 }
1304
1305 vc_EUSE.stop;
1306}
1307
1308
1309/* Test routing of USSD to EUSE by default-route */
1310private function f_TC_mo_ussd_999() runs on HLR_ConnHdlr {
1311 var GSUP_PDU res;
1312 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1313 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1314 ussd_string := "*999#");
1315 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1316 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001317 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1318 OSMO_GSUP_SESSION_STATE_END,
1319 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1320 f_encGSM7bit("*999#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001321}
1322testcase TC_mo_ussd_euse_defaultroute() runs on test_CT {
1323 var HlrSubscriberList sl;
1324 var HLR_ConnHdlr vc_conn;
1325
1326 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1327 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
1328
1329 f_init(false);
1330 f_vty_config(VTY, "hlr", "ussd default-route external foobar");
1331
1332 sl := f_gen_subs();
1333 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1334 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1335 pars.ussd.sid := f_rnd_octstring(4);
1336 f_vty_subscr_create(VTY, pars.sub);
1337 vc_conn := f_start_handler(refers(f_TC_mo_ussd_999), pars);
1338 vc_conn.done;
1339 }
1340
1341 f_vty_config(VTY, "hlr", "no ussd default-route");
1342 vc_EUSE.stop;
1343}
1344
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001345/**
1346 * Test "Structured" Supplementary Services
1347 *
1348 * NOTE: at the moment, OsmoHLR doesn't support "structured" SS,
1349 * so such requests are being rejected (actually ReturnError
1350 * with GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED).
1351 */
1352private function f_TC_mo_sss_reject() runs on HLR_ConnHdlr {
1353 var SS_FacilityInformation ss_req;
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001354 var GSUP_PDU res;
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001355
1356 /* Prepare '*#21#' SS request */
1357 ss_req := valueof(ts_SS_FACILITY_INVOKE(
1358 invoke_id := 0,
1359 op_code := SS_OP_CODE_INTERROGATE_SS,
1360 ss_code := '21'O));
1361
1362 /* Send it towards HLR */
1363 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(
1364 g_pars.sub.imsi,
1365 g_pars.ussd.sid,
1366 OSMO_GSUP_SESSION_STATE_BEGIN,
1367 enc_SS_FacilityInformation(ss_req))));
1368
1369 /* Expect ReturnError with FACILITY_NOT_SUPPORTED */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001370 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1371 OSMO_GSUP_SESSION_STATE_END,
1372 tr_SS_FACILITY_RETURN_ERROR(0, 21));
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001373}
1374testcase TC_mo_sss_reject() runs on test_CT {
1375 var HLR_ConnHdlrPars pars;
1376 var HLR_ConnHdlr vc_conn;
1377 var HlrSubscriber sub;
1378
1379 f_init(false);
1380
1381 /* Create a random subscriber */
1382 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H),
1383 '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
1384 pars := valueof(t_Pars_sub(sub));
1385 pars.ussd.sid := f_rnd_octstring(4);
1386
1387 f_vty_subscr_create(VTY, sub);
1388 vc_conn := f_start_handler(refers(f_TC_mo_sss_reject), pars);
1389 vc_conn.done;
1390 f_vty_subscr_delete(VTY, sub);
1391}
1392
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001393
1394/* TODO USSD:
1395 * MO USSD for IMSI of non-existant subscriber
1396 * MT USSD from EUSE
1397 * timeout cases
1398 */
1399
Oliver Smith936dbe62019-06-04 15:54:17 +02001400
1401/* Test Check IMEI */
1402private function f_TC_gsup_check_imei() runs on HLR_ConnHdlr {
1403 /* store-imei disabled */
1404 f_vty_config(VTY, "hlr", "no store-imei");
1405 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1406 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1407
1408 /* store-imei enabled */
1409 f_vty_config(VTY, "hlr", "store-imei");
1410 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1411 f_vty_subscr_show(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1412}
1413testcase TC_gsup_check_imei() runs on test_CT {
1414 var HlrSubscriberList sl;
1415
1416 f_init(false);
1417 sl := f_gen_subs();
1418 f_start_handler_per_sub(refers(f_TC_gsup_check_imei), sl);
1419
1420 setverdict(pass);
1421}
1422
1423/* Test Check IMEI with invalid IMEI length */
1424private function f_TC_gsup_check_imei_invalid_len() runs on HLR_ConnHdlr {
1425 /* IMEI too long */
1426 f_perform_CHECK_IMEI(g_pars.sub.imsi, '111456789012345F'H, 96 /* Invalid Mandatory Information */);
1427 f_perform_CHECK_IMEI(g_pars.sub.imsi, '2224567890123456'H, 96 /* Invalid Mandatory Information */);
1428
1429 /* IMEI too short */
1430 f_perform_CHECK_IMEI(g_pars.sub.imsi, '3334567890123F'H, 96 /* Invalid Mandatory Information */);
1431 f_perform_CHECK_IMEI(g_pars.sub.imsi, '444456789012'H, 96 /* Invalid Mandatory Information */);
1432 f_perform_CHECK_IMEI(g_pars.sub.imsi, ''H, 96 /* Invalid Mandatory Information */);
1433}
1434testcase TC_gsup_check_imei_invalid_len() runs on test_CT {
1435 var HlrSubscriberList sl;
1436
1437 f_init(false);
1438 sl := f_gen_subs();
1439 f_start_handler_per_sub(refers(f_TC_gsup_check_imei_invalid_len), sl);
1440
1441 setverdict(pass);
1442}
1443
1444/* Test Check IMEI with unknown IMSI */
1445private function f_TC_gsup_check_imei_unknown_imsi() runs on HLR_ConnHdlr {
1446 f_vty_config(VTY, "hlr", "no store-imei");
1447 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1448
1449 /* Check again with store-imei set (different code path) */
1450 f_vty_config(VTY, "hlr", "store-imei");
1451 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1452
1453 setverdict(pass);
1454}
1455testcase TC_gsup_check_imei_unknown_imsi() runs on test_CT {
1456 var hexstring imsi := f_rnd_imsi('26242'H);
1457 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1458 var HLR_ConnHdlr vc_conn;
1459
1460 f_init(false);
1461 vc_conn := f_start_handler(refers(f_TC_gsup_check_imei_unknown_imsi), pars);
1462 vc_conn.done;
1463}
1464
Oliver Smith1b257802019-06-11 09:43:42 +02001465/* Test create-subscriber-on-demand during Check IMEI (OsmoMSC would be set to "check-imei-rqd early") */
1466private function f_TC_subscr_create_on_demand_check_imei_early() runs on HLR_ConnHdlr {
1467 var GSUP_PDU res; /* save various return values to prevent ttcn3 compiler warnings */
1468 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1469
1470 /* Random MSISDN and CS+PS NAM (LU must pass) */
1471 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1472 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1473 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1474 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1475 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1476 res := f_perform_UL(g_pars.sub.imsi, ?);
1477 f_vty_subscr_delete(VTY, g_pars.sub);
1478
1479 /* Random MSISDN and PS NAM (LU must pass) */
1480 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1481 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1482 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1483 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1484 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1485 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1486 res := f_perform_UL(g_pars.sub.imsi, ?);
1487 f_vty_subscr_delete(VTY, g_pars.sub);
1488
1489 /* Random MSISDN and CS NAM (LU must fail) */
1490 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1491 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1492 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1493 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1494 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1495 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1496 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1497 f_vty_subscr_delete(VTY, g_pars.sub);
1498
1499 /* Random MSISDN and no NAM (LU must fail) */
1500 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1501 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1502 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1503 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1504 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1505 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1506 f_vty_subscr_delete(VTY, g_pars.sub);
1507
1508 /* No MSISDN and no NAM (LU must fail) */
1509 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1510 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1511 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1512 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1513 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1514 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1515 f_vty_subscr_delete(VTY, g_pars.sub);
1516
1517 /* No MSISDN and CS+PS NAM (LU must pass) */
1518 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1519 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1520 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1521 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1522 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1523 res := f_perform_UL(g_pars.sub.imsi, omit);
1524 f_vty_subscr_delete(VTY, g_pars.sub);
1525
1526 setverdict(pass);
1527}
1528testcase TC_subscr_create_on_demand_check_imei_early() runs on test_CT {
1529 var hexstring imsi := f_rnd_imsi('26242'H);
1530 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1531 var HLR_ConnHdlr vc_conn;
1532
1533 f_init(false);
1534 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_check_imei_early), pars);
1535 vc_conn.done;
1536}
1537
1538/* Test create-subscriber-on-demand during LU (Location Update) */
1539private function f_TC_subscr_create_on_demand_ul() runs on HLR_ConnHdlr {
1540 var GSUP_PDU res;
1541 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1542
1543 /* Random MSISDN and CS+PS NAM (LU must pass) */
1544 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1545 res := f_perform_UL(g_pars.sub.imsi, ?);
1546 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1547 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1548 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1549 f_vty_subscr_delete(VTY, g_pars.sub);
1550
1551 /* Random MSISDN and PS NAM (LU must pass) */
1552 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1553 res := f_perform_UL(g_pars.sub.imsi, ?);
1554 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1555 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1556 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1557 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1558 f_vty_subscr_delete(VTY, g_pars.sub);
1559
1560 /* Random MSISDN and CS NAM (LU must fail) */
1561 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1562 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1563 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1564 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1565 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1566 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1567 f_vty_subscr_delete(VTY, g_pars.sub);
1568
1569 /* Random MSISDN and no NAM (LU must fail) */
1570 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1571 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1572 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1573 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1574 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1575 f_vty_subscr_delete(VTY, g_pars.sub);
1576
1577 /* No MSISDN and no NAM (LU must fail) */
1578 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1579 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1580 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1581 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1582 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1583 f_vty_subscr_delete(VTY, g_pars.sub);
1584
1585 /* No MSISDN and CS+PS NAM (LU must pass) */
1586 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1587 res := f_perform_UL(g_pars.sub.imsi, omit);
1588 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1589 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1590 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1591 f_vty_subscr_delete(VTY, g_pars.sub);
1592
1593 setverdict(pass);
1594}
1595testcase TC_subscr_create_on_demand_ul() runs on test_CT {
1596 var hexstring imsi := f_rnd_imsi('26242'H);
1597 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1598 var HLR_ConnHdlr vc_conn;
1599
1600 f_init(false);
1601 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_ul), pars);
1602 vc_conn.done;
1603}
1604
1605/* Test create-subscriber-on-demand during SAI (SendAuthInfo) */
1606private function f_TC_subscr_create_on_demand_sai() runs on HLR_ConnHdlr {
1607 var GSUP_PDU res;
1608 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1609
1610 /* HLR creates the subscriber on demand. Then the IMSI is known, but there is no auth data, so the HLR returns
1611 * the "slightly inaccurate cause 'IMSI Unknown' via GSUP". The MS is able to do a LU afterwards. */
1612 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1613 res := f_perform_SAI(g_pars.sub.imsi, 2 /* IMSI Unknown */ );
1614
1615 /* Verify that it was created before the LU */
1616 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1617 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1618 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1619
1620 /* Location update */
1621 res := f_perform_UL(g_pars.sub.imsi, ?);
1622 f_vty_subscr_delete(VTY, g_pars.sub);
1623 setverdict(pass);
1624}
1625testcase TC_subscr_create_on_demand_sai() runs on test_CT {
1626 var hexstring imsi := f_rnd_imsi('26242'H);
1627 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1628 var HLR_ConnHdlr vc_conn;
1629
1630 f_init(false);
1631 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_sai), pars);
1632 vc_conn.done;
1633}
1634
Oliver Smithdeb80a62019-11-29 16:01:54 +01001635/* Send an mslookup mDNS request to the home HLR, asking about a service that is not "gsup.hlr". (Hence the "_other" in
1636 * the test name, service "gsup.hlr" has different code paths, see related tests). */
1637private function f_TC_MSLookup_mDNS_service_other_home() runs on HLR_ConnHdlr {
1638 timer T;
1639 var MSLookup_mDNS vl_rmsg;
1640 var integer id := f_rnd_int(65535); /* mDNS packet ID */
1641 var hexstring msisdn := '49161'H & f_rnd_hexstring(7, 9);
1642 var charstring domain := "sip.voice." & hex2str(msisdn) & ".msisdn.mdns.osmocom.org";
1643
1644 /* Create subscriber */
1645 g_pars.sub.msisdn := msisdn;
1646 f_vty_subscr_create(VTY, g_pars.sub);
1647
1648 /* Send mDNS query, expect timeout */
1649 mDNS.send(ts_MSLookup_mDNS_query(id, domain));
1650 T.start(1.0);
1651 alt {
1652 [] mDNS.receive(tr_MSLookup_mDNS_result_IPv4(id, domain, '42424242'O, 5060)) {
1653 setverdict(fail, "OsmoHLR answered to mDNS query before subscriber did LU");
1654 }
1655 [] mDNS.receive(MSLookup_mDNS:?) -> value vl_rmsg {
1656 repeat;
1657 }
1658 [] T.timeout {
1659 }
1660 }
1661
1662 /* Location update */
1663 f_perform_UL(g_pars.sub.imsi, msisdn, dom := OSMO_GSUP_CN_DOMAIN_CS);
1664
1665 /* Send mDNS query again, expect result */
1666 mDNS.send(ts_MSLookup_mDNS_query(id, domain));
1667 T.start(1.0);
1668 alt {
1669 [] mDNS.receive(tr_MSLookup_mDNS_result_IPv4(id, domain, '42424242'O, 5060)) {
1670 setverdict(pass);
1671 }
1672 [] mDNS.receive(MSLookup_mDNS:?) -> value vl_rmsg {
1673 repeat;
1674 }
1675 [] T.timeout {
1676 setverdict(fail, "OsmoHLR did not answer to mDNS query");
1677 }
1678 }
1679
1680 f_vty_subscr_delete(VTY, g_pars.sub);
1681}
1682testcase TC_MSLookup_mDNS_service_other_home() runs on test_CT {
1683 var hexstring imsi := f_rnd_imsi('26242'H);
1684 var HLR_ConnHdlr vc_conn;
1685 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1686
1687 f_init(false);
1688 f_vty_config(VTY, "mslookup", "mdns bind");
1689 f_vty_config2(VTY, {"mslookup", "server"}, "service sip.voice at 66.66.66.66 5060");
1690
1691 vc_conn := f_start_handler(refers(f_TC_MSLookup_mDNS_service_other_home), pars);
1692 vc_conn.done;
1693}
1694
Oliver Smithb51a53f2020-01-29 15:06:54 +01001695/* Let OsmoHLR act as proxy between MSC and another HLR during UL */
1696private function f_TC_MSLookup_GSUP_proxy() runs on HLR_ConnHdlr {
1697 f_perform_UL_proxy(g_pars.sub.imsi, g_pars.sub.msisdn, OSMO_GSUP_CN_DOMAIN_CS);
1698 setverdict(pass);
1699}
1700testcase TC_MSLookup_GSUP_proxy() runs on test_CT {
1701 var hexstring imsi := f_rnd_imsi('26242'H);
1702 var hexstring msisdn := '49161'H & f_rnd_hexstring(7, 9);
1703 var HLR_ConnHdlr vc_conn;
1704 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi, msisdn));
1705
1706 f_init(false, true);
1707 f_vty_config(VTY, "mslookup", "mdns bind");
1708 vc_conn := f_start_handler(refers(f_TC_MSLookup_GSUP_proxy), pars, true);
1709
1710 timer T := 3.0;
1711 T.start;
1712 alt {
1713 [] vc_conn.done {}
1714 [] T.timeout { setverdict(fail, "Timeout"); mtc.stop; };
1715 }
1716}
1717
Oliver Smith18b48082020-01-30 10:34:47 +01001718/* Request "gsup.hlr" service right after creating subscriber from the home HLR. "TC_MSLookup_mDNS_service_other_home"
1719 * is similar, but does not query the "gsup.hlr" service. The "gsup.hlr" service has a different code path in OsmoHLR:
1720 * - it exists without being explicitly configured and returns the IP and port of the HLR's own GSUP server
1721 * - the request is answered, even if the subscriber is not attached to the HLR (for Location Update via proxy) */
1722private function f_TC_MSLookup_mDNS_service_GSUP_HLR_home() runs on HLR_ConnHdlr {
1723 timer T;
1724 var MSLookup_mDNS vl_rmsg;
1725 var integer id := f_rnd_int(65535); /* mDNS packet ID */
1726 var charstring domain := "gsup.hlr." & hex2str(g_pars.sub.imsi) & ".imsi.mdns.osmocom.org";
1727
1728 /* Create subscriber */
1729 g_pars.sub.msisdn := '133713381339'H;
1730 f_vty_subscr_create(VTY, g_pars.sub);
1731
1732 /* Send mDNS query, expect result */
1733 mDNS.send(ts_MSLookup_mDNS_query(id, domain));
1734 T.start(1.0);
1735 alt {
1736 [] mDNS.receive(tr_MSLookup_mDNS_result_IPv4(id, domain, f_enc_IPv4(mp_hlr_ip), mp_hlr_gsup_port)) {
1737 setverdict(pass);
1738 }
1739 [] mDNS.receive(MSLookup_mDNS:?) -> value vl_rmsg {
1740 repeat;
1741 }
1742 [] T.timeout {
1743 setverdict(fail, "OsmoHLR did not answer to mDNS query");
1744 }
1745 }
1746
1747 f_vty_subscr_delete(VTY, g_pars.sub);
1748}
1749testcase TC_MSLookup_mDNS_service_GSUP_HLR_home() runs on test_CT {
1750 var hexstring imsi := f_rnd_imsi('26242'H);
1751 var HLR_ConnHdlr vc_conn;
1752 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1753
1754 f_init(false);
1755 f_vty_config(VTY, "mslookup", "mdns bind");
1756
1757 vc_conn := f_start_handler(refers(f_TC_MSLookup_mDNS_service_GSUP_HLR_home), pars);
1758 vc_conn.done;
1759}
1760
Oliver Smithda83c832020-01-30 15:10:20 +01001761/* Ask proxy HLR about gsup.hlr service, and expect no answer. */
1762private function f_TC_MSLookup_mDNS_service_GSUP_HLR_proxy() runs on HLR_ConnHdlr {
1763 timer T;
1764 var integer id := f_rnd_int(65535); /* mDNS packet ID */
1765 var charstring domain := "gsup.hlr." & hex2str(g_pars.sub.imsi) & ".imsi.mdns.osmocom.org";
1766
1767 f_perform_UL_proxy(g_pars.sub.imsi, g_pars.sub.msisdn, OSMO_GSUP_CN_DOMAIN_CS);
1768
1769 /* Send mDNS query, expect timeout */
1770 mDNS.send(ts_MSLookup_mDNS_query(id, domain));
1771 T.start(1.0);
1772 alt {
1773 [] mDNS.receive(tr_MSLookup_mDNS_result_IPv4(id, domain, f_enc_IPv4(mp_hlr_ip), mp_hlr_gsup_port)) {
1774 setverdict(fail, "mslookup result received from proxy HLR for gsup.hlr service");
1775 }
1776 [] mDNS.receive(MSLookup_mDNS:?) {
1777 repeat;
1778 }
1779 [] T.timeout {
1780 setverdict(pass);
1781 }
1782 }
1783}
1784testcase TC_MSLookup_mDNS_service_GSUP_HLR_proxy() runs on test_CT {
1785 var hexstring imsi := f_rnd_imsi('26242'H);
1786 var hexstring msisdn := '49161'H & f_rnd_hexstring(7, 9);
1787 var HLR_ConnHdlr vc_conn;
1788 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi, msisdn));
1789
1790 f_init(false, true);
1791 f_vty_config(VTY, "mslookup", "mdns bind");
1792 vc_conn := f_start_handler(refers(f_TC_MSLookup_mDNS_service_GSUP_HLR_proxy), pars, true);
1793
1794 timer T := 3.0;
1795 T.start;
1796 alt {
1797 [] vc_conn.done {}
1798 [] T.timeout { setverdict(fail, "Timeout"); mtc.stop; };
1799 }
1800}
1801
Harald Weltec2c52552018-03-01 21:20:39 +01001802/* TODO:
1803 * UL with ISD error
1804 * UL with ISD timeout
Harald Weltec2c52552018-03-01 21:20:39 +01001805 * LOCATION CANCEL
1806 * AUTH FAIL REP
1807 * DELETE DATA after hlr_subscr_nam() change
1808 * correctness
1809 ** wrong message type
1810 ** wrong length of PDU
1811 ** too short message
1812 ** missing IMSI IE
1813
1814 */
1815
Harald Weltedf327232017-12-28 22:51:51 +01001816control {
1817 execute( TC_gsup_sai_err_invalid_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001818 execute( TC_gsup_sai() );
Alexander Couzens92696442020-01-10 07:57:16 +01001819 execute( TC_gsup_sai_num_auth_vectors() );
Harald Welteaf7c3182019-08-22 12:40:22 +02001820 execute( TC_gsup_sai_eps() );
Harald Weltec2c52552018-03-01 21:20:39 +01001821 execute( TC_gsup_ul_unknown_imsi() );
Harald Welte3f662762018-03-02 10:48:20 +01001822 execute( TC_gsup_sai_err_unknown_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01001823 execute( TC_gsup_ul() );
1824 execute( TC_vty() );
Harald Welte09b3c502018-03-01 22:42:22 +01001825 execute( TC_vty_msisdn_isd() );
Harald Welte958f8b42018-03-01 23:40:17 +01001826 execute( TC_gsup_purge_cs() );
1827 execute( TC_gsup_purge_ps() );
1828 execute( TC_gsup_purge_unknown() );
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001829
1830 execute( TC_mo_ussd_unknown() );
1831 execute( TC_mo_ussd_euse_disc() );
1832 execute( TC_mo_ussd_iuse_imsi() );
1833 execute( TC_mo_ussd_iuse_msisdn() );
1834 execute( TC_mo_ussd_euse() );
1835 execute( TC_mo_ussd_euse_continue() );
1836 execute( TC_mo_ussd_euse_defaultroute() );
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001837
1838 /* "Structured" Supplementary Services */
1839 execute( TC_mo_sss_reject() );
Oliver Smith936dbe62019-06-04 15:54:17 +02001840
1841 execute( TC_gsup_check_imei() );
1842 execute( TC_gsup_check_imei_invalid_len() );
1843 execute( TC_gsup_check_imei_unknown_imsi() );
Oliver Smith1b257802019-06-11 09:43:42 +02001844 execute( TC_subscr_create_on_demand_check_imei_early() );
1845 execute( TC_subscr_create_on_demand_ul() );
1846 execute( TC_subscr_create_on_demand_sai() );
Oliver Smithdeb80a62019-11-29 16:01:54 +01001847
1848 if (mp_hlr_supports_dgsm) {
1849 execute( TC_MSLookup_mDNS_service_other_home() );
Oliver Smithb51a53f2020-01-29 15:06:54 +01001850 execute( TC_MSLookup_GSUP_proxy() );
Oliver Smith18b48082020-01-30 10:34:47 +01001851 execute( TC_MSLookup_mDNS_service_GSUP_HLR_home() );
Oliver Smithda83c832020-01-30 15:10:20 +01001852 execute( TC_MSLookup_mDNS_service_GSUP_HLR_proxy() );
Oliver Smithdeb80a62019-11-29 16:01:54 +01001853 }
Harald Weltedf327232017-12-28 22:51:51 +01001854};
1855
1856};