blob: e99011d6f06588bc60fcf8a421948131f523b076 [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;
Harald Weltedf327232017-12-28 22:51:51 +010073};
74
Harald Weltec2c52552018-03-01 21:20:39 +010075type record HlrSubscrAud2G {
76 charstring algo,
77 OCT16 ki
78}
79
80type record HlrSubscrAud3G {
81 charstring algo,
82 OCT16 k,
83 OCT16 op,
84 boolean op_is_opc
85}
86
87type record HlrSubscriber {
88 hexstring imsi,
89 hexstring msisdn,
90 HlrSubscrAud2G aud2g optional,
91 HlrSubscrAud3G aud3g optional
92}
93
94type record of HlrSubscriber HlrSubscriberList;
95
Harald Welteed380d12018-06-14 13:42:11 +020096type component HLR_ConnHdlr extends GSUP_ConnHdlr {
97 timer g_Tguard := 10.0;
98 var HLR_ConnHdlrPars g_pars;
99 port TELNETasp_PT VTY;
Oliver Smithdeb80a62019-11-29 16:01:54 +0100100 port MSLookup_mDNS_PT mDNS;
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100101
102 /* Pass from test_CT for explicit addressing */
103 var GSUP_Emulation_CT vc_GSUP_server;
104 var GSUP_Emulation_CT vc_GSUP_client;
105 var IPA_CCM_Parameters ccm_pars_client;
Harald Welteed380d12018-06-14 13:42:11 +0200106}
107
108type record HLR_ConnHdlrPars {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200109 HlrSubscriber sub,
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100110 HLR_ConnHdlrParsUssd ussd optional,
111 octetstring source_name optional
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200112}
113
114type record HLR_ConnHdlrParsUssd {
115 OCT4 sid
Harald Welteed380d12018-06-14 13:42:11 +0200116}
117
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100118template (value) HLR_ConnHdlrPars t_Pars(hexstring imsi, hexstring msisdn := ''H,
119 template (omit) octetstring source_name := omit) := {
Harald Welteed380d12018-06-14 13:42:11 +0200120 sub := {
121 imsi := imsi,
122 msisdn := msisdn,
123 aud2g := omit,
124 aud3g := omit
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200125 },
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100126 ussd := omit,
127 source_name := source_name
Harald Welteed380d12018-06-14 13:42:11 +0200128}
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100129template (value) HLR_ConnHdlrPars t_Pars_via_proxy(hexstring imsi, hexstring msisdn := ''H) :=
130 t_Pars(imsi, msisdn, source_name := char2oct("the-source\n"));
Harald Welteed380d12018-06-14 13:42:11 +0200131
132template (value) HLR_ConnHdlrPars t_Pars_sub(HlrSubscriber sub) := {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200133 sub := sub,
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100134 ussd := omit,
135 source_name := omit
136}
137
138template (value) HLR_ConnHdlrPars t_Pars_sub_via_proxy(HlrSubscriber sub) := {
139 sub := sub,
140 ussd := omit,
141 source_name := char2oct("the-source\n")
Harald Welteed380d12018-06-14 13:42:11 +0200142}
143
144type function void_fn() runs on HLR_ConnHdlr;
145
146/***********************************************************************
147 * Main Component
148 ***********************************************************************/
149
150function f_init_vty() runs on test_CT {
151 map(self:VTY, system:VTY);
152 f_vty_set_prompts(VTY);
153 f_vty_transceive(VTY, "enable");
Pau Espin Pedrol0055a292021-02-26 13:08:09 +0100154 f_vty_config(VTY, "mslookup", "no mdns bind");
Harald Welteed380d12018-06-14 13:42:11 +0200155}
156
157private altstep as_Tguard() runs on test_CT {
158 [] g_Tguard.timeout {
159 setverdict(fail, "g_Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200160 mtc.stop;
Harald Welteed380d12018-06-14 13:42:11 +0200161 }
162}
163
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100164/* emulated GSUP client (MSC/SGSN) */
Harald Welteed380d12018-06-14 13:42:11 +0200165function f_init_gsup(charstring id, boolean legacy) runs on test_CT {
166 id := id & "-GSUP";
167 var GsupOps ops := {
168 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
169 }
170
171 ccm_pars := c_IPA_default_ccm_pars;
172 ccm_pars.name := "Osmocom TTCN-3 GSUP Simulator";
Harald Welte4a3242e2018-06-24 22:28:53 +0200173 ccm_pars.ser_nr := "MSC-00-00-00-00-00-00";
Harald Welteed380d12018-06-14 13:42:11 +0200174
175 vc_IPA := IPA_Emulation_CT.create(id & "-IPA");
176 log("legacy= ", legacy);
177 if (not legacy) {
178 log("in not legacy case 1");
179 vc_GSUP := GSUP_Emulation_CT.create(id);
180 }
181
182 map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
183 if (not legacy) {
184 log("in not legacy case 2");
185 connect(vc_GSUP:GSUP, vc_IPA:IPA_GSUP_PORT);
186 connect(vc_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
187 vc_GSUP.start(GSUP_Emulation.main(ops, id));
188 } else {
189 connect(vc_IPA:IPA_GSUP_PORT, self:GSUP);
190 }
191
192 vc_IPA.start(IPA_Emulation.main_client(mp_hlr_ip, mp_hlr_gsup_port, "", -1, ccm_pars));
193
194 /* wait for incoming connection to GSUP port before proceeding */
195 timer T := 10.0;
196 T.start;
197 alt {
Vadim Yanitskiy61564be2020-05-18 20:44:14 +0700198 [not legacy] GSUP_IPA_EVENT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) { }
Vadim Yanitskiya2afacc2020-05-18 21:16:19 +0700199 [legacy] GSUP.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) { }
Harald Welteed380d12018-06-14 13:42:11 +0200200 [] T.timeout {
201 setverdict(fail, "No connection to GSUP Port");
Daniel Willmannafce8662018-07-06 23:11:32 +0200202 mtc.stop;
Harald Welteed380d12018-06-14 13:42:11 +0200203 }
204 }
205}
206
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100207/* emulated GSUP server (second HLR) */
208function f_init_gsup_server(charstring id) runs on test_CT {
209 id := id & "-GSUP-server";
210 var GsupOps ops := {
211 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
212 }
213
214 vc_GSUP_server := GSUP_Emulation_CT.create(id);
215 vc_IPA_server := IPA_Emulation_CT.create(id & "-IPA");
216
217 connect(vc_GSUP_server:GSUP, vc_IPA_server:IPA_GSUP_PORT);
218 map(vc_IPA_server:IPA_PORT, system:IPA_CODEC_PT);
219
220 vc_GSUP_server.start(GSUP_Emulation.main(ops, id));
221 vc_IPA_server.start(IPA_Emulation.main_server(mp_hlr_ts_ip, mp_hlr_ts_port));
222}
223
Oliver Smithdeb80a62019-11-29 16:01:54 +0100224function f_init_mslookup() runs on test_CT {
225 vc_MSLookup_mDNS := MSLookup_mDNS_Emulation_CT.create;
226 vc_MSLookup_mDNS.start(MSLookup_mDNS_Emulation.f_main());
227}
228
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100229function f_init(boolean legacy := true, boolean gsup_server := false) runs on test_CT {
Harald Welteed380d12018-06-14 13:42:11 +0200230
231 /* activate default guard timer to ensure all tests eventually terminate */
232 g_Tguard.start;
233 activate(as_Tguard());
234
235 f_init_gsup("HLR_Test", legacy);
236 f_init_vty();
Oliver Smithdeb80a62019-11-29 16:01:54 +0100237 f_init_mslookup();
Harald Welteed380d12018-06-14 13:42:11 +0200238
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100239 if (gsup_server) {
240 f_init_gsup_server("HLR_Test");
241 }
242
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +0100243 f_ipa_ctrl_start_client(mp_hlr_ip, mp_hlr_ctrl_port);
Harald Welteed380d12018-06-14 13:42:11 +0200244}
245
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100246/*! Start HLR_ConnHdlr from testCT in a separate thread.
247 * \param void_fn function to run inside the thread.
248 * \param gsup_server if true, connect the emulated GSUP server ports to the new HLR_ConnHdlr. Then both the emulated
249 * GSUP client (MSC/SGSN) and server (second HLR) are connected. Explicit addressing with "to" and
250 * "from" must be used, i.e. 'GSUP.receive(tr_GSUP_UL_REQ(...)) from vc_GSUP_server'. */
251function f_start_handler(void_fn fn, HLR_ConnHdlrPars pars, boolean gsup_server := false) runs on test_CT
252return HLR_ConnHdlr {
Harald Welteed380d12018-06-14 13:42:11 +0200253 var HLR_ConnHdlr vc_conn;
254 var charstring id := testcasename();
255
256 vc_conn := HLR_ConnHdlr.create(id);
257 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
258 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
Oliver Smithdeb80a62019-11-29 16:01:54 +0100259 connect(vc_conn:mDNS, vc_MSLookup_mDNS:mDNS);
Harald Welteed380d12018-06-14 13:42:11 +0200260
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100261 if (gsup_server) {
262 connect(vc_conn:GSUP, vc_GSUP_server:GSUP_CLIENT);
263 connect(vc_conn:GSUP_PROC, vc_GSUP_server:GSUP_PROC);
264 vc_conn.start(f_handler_init(fn, id, vc_GSUP_server, vc_GSUP, ccm_pars, pars));
265 } else {
266 vc_conn.start(f_handler_init(fn, id, omit, vc_GSUP, ccm_pars, pars));
267 }
268
Harald Welteed380d12018-06-14 13:42:11 +0200269 return vc_conn;
270}
271
272private function f_handler_init_vty() runs on HLR_ConnHdlr {
273 map(self:VTY, system:VTY);
274 f_vty_set_prompts(VTY);
275 f_vty_transceive(VTY, "enable");
276}
277
278/* first function inside ConnHdlr component; sets g_pars + starts function */
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100279function f_handler_init(void_fn fn, charstring id,
280 template (omit) GSUP_Emulation_CT vc_GSUP_server_test_ct,
281 GSUP_Emulation_CT vc_GSUP_client_test_ct,
282 IPA_CCM_Parameters ccm_pars_client_test_ct,
283 template (omit) HLR_ConnHdlrPars pars := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200284runs on HLR_ConnHdlr
285{
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100286 /* Pass from test_CT for explicit addressing */
287 if (isvalue(vc_GSUP_server_test_ct)) {
288 vc_GSUP_server := valueof(vc_GSUP_server_test_ct);
289 }
290 vc_GSUP_client := vc_GSUP_client_test_ct;
291 ccm_pars_client := ccm_pars_client_test_ct;
292
Harald Welteed380d12018-06-14 13:42:11 +0200293 if (isvalue(pars)) {
294 g_pars := valueof(pars);
Oliver Smith6e81f7e2020-01-29 14:25:41 +0100295 f_create_gsup_expect_explicit(hex2str(g_pars.sub.imsi), vc_GSUP_client);
Harald Welteed380d12018-06-14 13:42:11 +0200296 }
297 f_handler_init_vty();
298 fn.apply();
299}
300
301/***********************************************************************
302 * Subscriber creation via VTY
303 ***********************************************************************/
304
Harald Weltec2c52552018-03-01 21:20:39 +0100305template (value) HlrSubscriber t_SubNoAuth(hexstring imsi, hexstring msisdn) := {
306 imsi := imsi,
307 msisdn := msisdn,
308 aud2g := omit,
309 aud3g := omit
310}
311
312const OCT16 c_KI_DEFAULT := '000102030405060708090a0b0c0d0e0f'O;
313const OCT16 c_K_DEFAULT := '101112131415161718191a1b1c1d1e1f'O;
314const OCT16 c_OP_DEFAULT := '202122232425262728292a2b2c2d2e2f'O;
315//const OCT16 c_OPC_DEFAULT := '303132333435363738393a3b3c3d3f'O;
316
317template (value) HlrSubscriber t_Sub2G(hexstring imsi, hexstring msisdn, charstring algo) := {
318 imsi := imsi,
319 msisdn := msisdn,
320 aud2g := {
321 algo := algo,
322 ki := c_KI_DEFAULT
323 },
324 aud3g := omit
325}
326
327template (value) HlrSubscriber t_Sub3G(hexstring imsi, hexstring msisdn, charstring algo, boolean is_opc) := {
328 imsi := imsi,
329 msisdn := msisdn,
330 aud2g := omit,
331 aud3g := {
332 algo := algo,
333 k := c_K_DEFAULT,
334 op := c_OP_DEFAULT,
335 op_is_opc := is_opc
336 }
337}
338
339template (value) HlrSubscriber t_Sub2G3G(hexstring imsi, hexstring msisdn, charstring algo2g, charstring algo3g, boolean is_opc) := {
340 imsi := imsi,
341 msisdn := msisdn,
342 aud2g := {
343 algo := algo2g,
344 ki := c_KI_DEFAULT
345 },
346 aud3g := {
347 algo := algo3g,
348 k := c_K_DEFAULT,
349 op := c_OP_DEFAULT,
350 op_is_opc := is_opc
351 }
352}
353
354/* generate a variety of subscribers with different parameters */
355function f_gen_subs() runs on test_CT return HlrSubscriberList {
356 var HlrSubscriber sub;
357 var HlrSubscriberList sl := {};
358
359 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
360 sl := sl & { sub };
361
362 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v2"));
363 sl := sl & { sub };
364
365 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v3"));
366 sl := sl & { sub };
367
368 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", false));
369 sl := sl & { sub };
370
371 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", true));
372 sl := sl & { sub };
373
374 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
375 "comp128v1", "milenage", false));
376 sl := sl & { sub };
377
378 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
379 "comp128v2", "milenage", false));
380 sl := sl & { sub };
381
382 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
383 "comp128v3", "milenage", false));
384 sl := sl & { sub };
385
386 return sl;
387}
Harald Welteaf7c3182019-08-22 12:40:22 +0200388function f_gen_3G_subs() runs on test_CT return HlrSubscriberList {
389 var HlrSubscriber sub;
390 var HlrSubscriberList sl := {};
391
392 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", false));
393 sl := sl & { sub };
394
395 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "milenage", true));
396 sl := sl & { sub };
397
398 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
399 "comp128v1", "milenage", false));
400 sl := sl & { sub };
401
402 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
403 "comp128v2", "milenage", false));
404 sl := sl & { sub };
405
406 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
407 "comp128v3", "milenage", false));
408 sl := sl & { sub };
409
410 return sl;
411}
Harald Weltec2c52552018-03-01 21:20:39 +0100412
Harald Welteed380d12018-06-14 13:42:11 +0200413function f_vty_transceive_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
414 var charstring ret := f_vty_transceive_ret(pt, cmd);
415 if (not match(ret, exp_ret)) {
416 setverdict(fail, "Non-matching VTY response: ", ret);
Daniel Willmannafce8662018-07-06 23:11:32 +0200417 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100418 }
419}
420
Oliver Smith141620d2019-06-07 12:27:33 +0200421function f_vty_transceive_nomatch(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
422 var charstring ret := f_vty_transceive_ret(pt, cmd);
423 if (match(ret, exp_ret)) {
424 setverdict(fail, "Matching VTY response: ", ret, ", should *not* have matched: ", exp_ret);
425 mtc.stop;
426 }
427}
428
Harald Welte70296062018-03-01 22:42:03 +0100429private template (value) charstring t_subscr_prefix(hexstring imsi) :=
430 "subscriber imsi " & hex2str(imsi) & " ";
431
Harald Weltec2c52552018-03-01 21:20:39 +0100432/* create a given subscriber using the VTY */
Harald Welteed380d12018-06-14 13:42:11 +0200433function f_vty_subscr_create(TELNETasp_PT VTY, HlrSubscriber sub) {
Harald Welte70296062018-03-01 22:42:03 +0100434 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100435 f_vty_transceive_match(VTY, prefix & "create", pattern "% Created subscriber *");
436 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(sub.msisdn),
437 pattern "% Updated subscriber *");
438 if (ispresent(sub.aud2g)) {
439 f_vty_transceive_match(VTY, prefix & "update aud2g " & sub.aud2g.algo &
440 " ki " & oct2str(sub.aud2g.ki),
441 pattern "");
442 } else {
443 f_vty_transceive_match(VTY, prefix & "update aud2g none", pattern "");
444 }
445
446 if (ispresent(sub.aud3g)) {
447 var charstring op_mode := "op";
448 if (sub.aud3g.op_is_opc) {
449 op_mode := "opc";
450 }
451 f_vty_transceive_match(VTY, prefix & "update aud3g " & sub.aud3g.algo &
452 " k " & oct2str(sub.aud3g.k) & " " & op_mode & " " &
453 oct2str(sub.aud3g.op), pattern "");
454 } else {
455 f_vty_transceive_match(VTY, prefix & "update aud3g none", pattern "");
456 }
457}
458
Harald Welteed380d12018-06-14 13:42:11 +0200459function f_vty_subscr_update_msisdn(TELNETasp_PT VTY, HlrSubscriber sub, hexstring new_msisdn) {
Harald Welte09b3c502018-03-01 22:42:22 +0100460 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
461 f_vty_transceive_match(VTY, prefix & "update msisdn " & hex2str(new_msisdn),
462 pattern "% Updated subscriber *");
463}
464
Harald Weltec2c52552018-03-01 21:20:39 +0100465/* perform 'delete' on subscriber */
Harald Welteed380d12018-06-14 13:42:11 +0200466function f_vty_subscr_delete(TELNETasp_PT VTY, HlrSubscriber sub) {
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 & "delete",
469 pattern "% Deleted subscriber for IMSI *");
470}
471
472/* perform 'show' on subscriber; match result with pattern 'exp' */
Harald Welteed380d12018-06-14 13:42:11 +0200473function f_vty_subscr_show(TELNETasp_PT VTY, HlrSubscriber sub, template charstring exp) {
Harald Welte70296062018-03-01 22:42:03 +0100474 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
Harald Weltec2c52552018-03-01 21:20:39 +0100475 f_vty_transceive_match(VTY, prefix & "show", exp);
476}
477
Oliver Smith141620d2019-06-07 12:27:33 +0200478/* perform 'show' on subscriber; result must not match with pattern 'exp' */
479function f_vty_subscr_show_nomatch(TELNETasp_PT VTY, HlrSubscriber sub, template charstring exp) {
480 var charstring prefix := valueof(t_subscr_prefix(sub.imsi));
481 f_vty_transceive_nomatch(VTY, prefix & "show", exp);
482}
Harald Weltec2c52552018-03-01 21:20:39 +0100483
Harald Welteed380d12018-06-14 13:42:11 +0200484/***********************************************************************
485 * Helper functions for ConnHdlr
486 ***********************************************************************/
487
Harald Weltec2c52552018-03-01 21:20:39 +0100488/* perform SendAuthInfo for given imsi, return the GSUP response/error */
Harald Welteaf7c3182019-08-22 12:40:22 +0200489function f_perform_SAI(hexstring imsi, template (omit) integer exp_err_cause := omit,
Alexander Couzens92696442020-01-10 07:57:16 +0100490 boolean is_eps := false, template (omit) integer num_auth_tuple := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200491runs on HLR_ConnHdlr return GSUP_PDU {
Alexander Couzens92696442020-01-10 07:57:16 +0100492 var template GSUP_PDU sai_msg;
Harald Weltec2c52552018-03-01 21:20:39 +0100493 var GSUP_PDU ret;
494 timer T := 3.0;
495 var boolean exp_fail := false;
496 if (not istemplatekind(exp_err_cause, "omit")) {
497 exp_fail := true;
498 }
499
Harald Welteaf7c3182019-08-22 12:40:22 +0200500 if (is_eps) {
Alexander Couzens92696442020-01-10 07:57:16 +0100501 sai_msg := ts_GSUP_SAI_REQ_EPS(imsi);
Harald Welteaf7c3182019-08-22 12:40:22 +0200502 } else {
Alexander Couzens92696442020-01-10 07:57:16 +0100503 sai_msg := ts_GSUP_SAI_REQ(imsi);
Harald Welteaf7c3182019-08-22 12:40:22 +0200504 }
Alexander Couzens92696442020-01-10 07:57:16 +0100505 if (not istemplatekind(num_auth_tuple, "omit")) {
506 sai_msg.ies := valueof(sai_msg.ies) & {
507 valueof(ts_GSUP_IE_NUM_VECTORS_REQ(int2oct(valueof(num_auth_tuple), 1)))
508 };
509 }
510 GSUP.send(sai_msg);
511
Harald Weltec2c52552018-03-01 21:20:39 +0100512 T.start;
513 alt {
514 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, exp_err_cause)) -> value ret {
515 setverdict(pass);
516 }
517 [exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
518 setverdict(fail, "Unexpected SAI ERROR Cause");
519 }
520 [exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
521 setverdict(fail, "Unexpected SAI.res for unknown IMSI");
522 }
523 [not exp_fail] GSUP.receive(tr_GSUP_SAI_ERR(imsi, ?)) -> value ret {
524 setverdict(fail, "Unexpected SAI ERROR");
525 }
526 [not exp_fail] GSUP.receive(tr_GSUP_SAI_RES(imsi)) -> value ret {
527 setverdict(pass);
528 }
529 [] GSUP.receive { repeat; }
530 [] T.timeout {
531 setverdict(fail, "Timeout waiting for SAI response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200532 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100533 }
534 }
535 return ret;
536}
537
Alexander Couzens25d28492023-04-26 19:30:04 +0200538/* return_isd -> return the Insert Subscriber Data instead of the Update Location Result */
Harald Weltec2c52552018-03-01 21:20:39 +0100539function f_perform_UL(hexstring imsi, template hexstring msisdn,
Oliver Smith62a1c632020-01-15 15:58:54 +0100540 template (omit) integer exp_err_cause := omit,
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100541 GSUP_CnDomain dom := OSMO_GSUP_CN_DOMAIN_PS,
542 template (omit) octetstring source_name := omit)
Alexander Couzens25d28492023-04-26 19:30:04 +0200543runs on HLR_ConnHdlr return GSUP_PDUs {
544 var GSUP_PDU pdu;
545 var GSUP_PDU isd;
546 var GSUP_PDUs ret;
Harald Weltec2c52552018-03-01 21:20:39 +0100547 timer T := 3.0;
548 var boolean exp_fail := false;
549 var boolean isd_done := false;
550 if (not istemplatekind(exp_err_cause, "omit")) {
551 exp_fail := true;
552 }
553
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100554 GSUP.send(valueof(ts_GSUP_UL_REQ(imsi, dom, source_name := source_name)));
Harald Weltec2c52552018-03-01 21:20:39 +0100555 T.start;
556 alt {
Alexander Couzens25d28492023-04-26 19:30:04 +0200557 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, exp_err_cause, destination_name := source_name)) -> value pdu {
Harald Weltec2c52552018-03-01 21:20:39 +0100558 setverdict(pass);
559 }
Alexander Couzens25d28492023-04-26 19:30:04 +0200560 [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?, destination_name := source_name)) -> value pdu {
Harald Weltec2c52552018-03-01 21:20:39 +0100561 setverdict(fail, "Unexpected UL ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100562 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100563 }
Alexander Couzens25d28492023-04-26 19:30:04 +0200564 [exp_fail] GSUP.receive(tr_GSUP_UL_RES(imsi, destination_name := source_name)) -> value pdu {
Harald Weltec2c52552018-03-01 21:20:39 +0100565 setverdict(fail, "Unexpected UL.res for unknown IMSI");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100566 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100567 }
Alexander Couzens25d28492023-04-26 19:30:04 +0200568 [exp_fail] GSUP.receive(tr_GSUP_ISD_REQ(imsi, destination_name := source_name)) -> value pdu {
Harald Weltec2c52552018-03-01 21:20:39 +0100569 setverdict(fail, "Unexpected ISD.req in error case");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100570 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100571 }
Alexander Couzens25d28492023-04-26 19:30:04 +0200572 [not exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?, destination_name := source_name)) -> value pdu {
Harald Weltec2c52552018-03-01 21:20:39 +0100573 setverdict(fail, "Unexpected UL ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100574 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100575 }
Alexander Couzens25d28492023-04-26 19:30:04 +0200576 [not exp_fail and not isd_done] GSUP.receive(tr_GSUP_ISD_REQ(imsi, msisdn, destination_name := source_name)) -> value isd {
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100577 GSUP.send(ts_GSUP_ISD_RES(imsi, source_name := source_name));
Harald Weltec2c52552018-03-01 21:20:39 +0100578 isd_done := true;
Harald Welte8f0c9332018-03-01 23:38:40 +0100579 repeat;
Harald Weltec2c52552018-03-01 21:20:39 +0100580 }
Alexander Couzens25d28492023-04-26 19:30:04 +0200581 [not exp_fail and isd_done] GSUP.receive(tr_GSUP_UL_RES(imsi, destination_name := source_name)) -> value pdu {
Harald Weltec2c52552018-03-01 21:20:39 +0100582 setverdict(pass);
583 }
584 [] GSUP.receive { repeat; }
585 [] T.timeout {
586 setverdict(fail, "Timeout waiting for UL response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200587 mtc.stop;
Harald Weltec2c52552018-03-01 21:20:39 +0100588 }
589 }
Alexander Couzens25d28492023-04-26 19:30:04 +0200590
591 ret := { pdu };
592 if (isd_done) {
593 ret := ret & { isd };
594 }
595
Harald Weltec2c52552018-03-01 21:20:39 +0100596 return ret;
597}
598
Oliver Smithb51a53f2020-01-29 15:06:54 +0100599/* Perform Location Update with IMSI that is unknown to OsmoHLR. Let it ask for the HLR that knows the IMSI via
600 * mslookup. The TTCN-3 testsuite pretends to be the home HLR, that knows the IMSI. The proxy HLR connects to the
601 * home HLR and forwards GSUP messages, until LU is complete.
602 * Make sure to let a timer run while calling this function (see TC_MSLookup_GSUP_proxy). */
603function f_perform_UL_proxy(hexstring imsi, hexstring msisdn, GSUP_CnDomain dom := OSMO_GSUP_CN_DOMAIN_PS)
604runs on HLR_ConnHdlr {
605 var MSLookup_mDNS mdns_msg;
606 var integer id;
607 var charstring domain := "gsup.hlr." & hex2str(imsi) & ".imsi.mdns.osmocom.org";
608 var octetstring destination_name := char2oct(ccm_pars_client.ser_nr) & '00'O; /* TS-MSC IPA name */
609
610 /* Testing the HLR as proxy. The MSC asking the proxy and the home HLR are both enacted by TTCN3 (TS).
611 * MSC=vc_GSUP_client <---> osmo-hlr as proxy <---> vc_GSUP_server=home HLR
612 * GSUP.send(..) to vc_GSUP_client ---> osmo-hlr ---> GSUP.receive(..) from vc_GSUP_server
613 * GSUP.receive(..) from vc_GSUP_client <--- osmo-hlr <--- GSUP.send(..) to vc_GSUP_server */
614
615 /* [GSUP] TS-MSC => HLR proxy: Update Location Request with unknown IMSI */
616 GSUP.send(ts_GSUP_UL_REQ(imsi, dom)) to vc_GSUP_client;
617
618 /* [GSUP] TS-HLR: expect GSUP messages with that IMSI */
619 f_create_gsup_expect_explicit(hex2str(imsi), vc_GSUP_server);
620
621 /* [mDNS] TS-HLR <= HLR proxy: query for GSUP server who knows the IMSI */
622 mDNS.receive(tr_MSLookup_mDNS_query(domain)) -> value mdns_msg;
623
624 /* [mDNS] TS-HLR => HLR proxy: result with IP/port of TS GSUP server */
625 id := mdns_msg.dnsMessage.header.id;
626 mDNS.send(ts_MSLookup_mDNS_result_IPv4(id, domain, f_enc_IPv4(mp_hlr_ts_ip), mp_hlr_ts_port));
627
628 /* [GSUP] TS-HLR <=> HLR proxy <=> TS-MSC: finish up UL */
629 GSUP.receive(tr_GSUP_UL_REQ(imsi)) from vc_GSUP_server;
630 GSUP.send(ts_GSUP_ISD_REQ(imsi, msisdn, destination_name)) to vc_GSUP_server;
631 GSUP.receive(tr_GSUP_ISD_REQ(imsi, g_pars.sub.msisdn)) from vc_GSUP_client;
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100632 GSUP.send(ts_GSUP_ISD_RES(imsi, destination_name := destination_name)) to vc_GSUP_server;
Oliver Smithb51a53f2020-01-29 15:06:54 +0100633 GSUP.receive(tr_GSUP_ISD_RES(imsi)) from vc_GSUP_client;
634 GSUP.send(ts_GSUP_UL_RES(imsi, destination_name)) to vc_GSUP_server;
635 GSUP.receive(tr_GSUP_UL_RES(imsi)) from vc_GSUP_client;
636}
637
Harald Welte958f8b42018-03-01 23:40:17 +0100638/* perform PurgeMS for given imsi, return the GSUP response/error */
639function f_perform_PURGE(hexstring imsi, GSUP_CnDomain cn_dom,
640 template (omit) integer exp_err_cause := omit)
Harald Welteed380d12018-06-14 13:42:11 +0200641runs on HLR_ConnHdlr return GSUP_PDU {
Harald Welte958f8b42018-03-01 23:40:17 +0100642 var GSUP_PDU ret;
643 timer T := 3.0;
644 var boolean exp_fail := false;
645 if (not istemplatekind(exp_err_cause, "omit")) {
646 exp_fail := true;
647 }
648
649 GSUP.send(valueof(ts_GSUP_PURGE_MS_REQ(imsi, cn_dom)));
650 T.start;
651 alt {
652 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, exp_err_cause)) -> value ret {
653 setverdict(pass);
654 }
655 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
656 setverdict(fail, "Unexpected PURGE ERROR Cause");
657 }
658 [exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
659 setverdict(fail, "Unexpected PURGE.res for unknown IMSI");
660 }
661 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_ERR(imsi, ?)) -> value ret {
662 setverdict(fail, "Unexpected PURGE ERROR");
663 }
664 [not exp_fail] GSUP.receive(tr_GSUP_PURGE_MS_RES(imsi)) -> value ret {
665 setverdict(pass);
666 }
667 [] GSUP.receive { repeat; }
668 [] T.timeout {
669 setverdict(fail, "Timeout waiting for PURGE response");
Daniel Willmannafce8662018-07-06 23:11:32 +0200670 mtc.stop;
Harald Welte958f8b42018-03-01 23:40:17 +0100671 }
672 }
673 return ret;
674}
675
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200676function f_SS_xceive(hexstring imsi, OCT4 sid, GSUP_SessionState state, octetstring ss,
677 template (omit) integer exp_err_cause := omit)
678runs on HLR_ConnHdlr return GSUP_PDU {
679 var GSUP_PDU ret;
680 timer T := 3.0;
681 var boolean exp_fail := false;
682 if (not istemplatekind(exp_err_cause, "omit")) {
683 exp_fail := true;
684 }
685
686 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(imsi, sid, state, ss)));
687 T.start;
688 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700689 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, exp_err_cause)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200690 setverdict(pass);
691 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700692 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200693 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
694 }
695 [exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
696 setverdict(fail, "Unexpected PROC_SS.res for unknown IMSI");
697 }
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700698 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200699 setverdict(fail, "Unexpected PROC_SS ERROR");
700 }
701 [not exp_fail] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, ?, ?)) -> value ret {
702 setverdict(pass);
703 }
704 [] GSUP.receive { repeat; }
705 [] T.timeout {
706 setverdict(fail, "Timeout waiting for PROC_SS response");
707 self.stop;
708 }
709 }
710 return ret;
711}
712
713private function f_SS_expect(hexstring imsi, OCT4 sid, GSUP_SessionState state,
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100714 template SS_FacilityInformation facility := *,
715 template octetstring destination_name := omit)
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200716runs on HLR_ConnHdlr return GSUP_PDU {
717 var GSUP_PDU ret;
718 timer T := 3.0;
719 var boolean exp_ss := true;
720 if (istemplatekind(facility, "omit")) {
721 exp_ss := false;
722 }
723 T.start;
724 alt {
Vadim Yanitskiy21c42332018-11-29 00:18:05 +0700725 [] GSUP.receive(tr_GSUP_PROC_SS_ERR(imsi, sid, ?, ?)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200726 setverdict(fail, "Unexpected PROC_SS ERROR Cause");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100727 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200728 }
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100729 [not exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit, destination_name := destination_name)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200730 setverdict(pass);
731 }
732 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, omit)) -> value ret {
733 setverdict(fail, "Unexpected PROC_SS.res without SS IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100734 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200735 }
736/*
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100737 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, decmatch facility, destination_name := destination_name)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200738 setverdict(pass);
739 }
740*/
741
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100742 [exp_ss] GSUP.receive(tr_GSUP_PROC_SS_RES(imsi, sid, state, ?, destination_name := destination_name)) -> value ret {
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200743 var GSUP_IeValue ss_ie;
744 f_gsup_find_ie(ret, OSMO_GSUP_SS_INFO_IE, ss_ie);
745 var SS_FacilityInformation dec_fac := dec_SS_FacilityInformation(ss_ie.ss_info);
746 log("pattern: ", facility);
747 if (match(dec_fac, facility)) {
748 setverdict(pass);
749 } else {
750 setverdict(fail, "Unexpected PROC_SS.res with non-matching facility IE");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100751 mtc.stop;
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200752 }
753 }
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100754 [] GSUP.receive {
755 setverdict(fail, "Unexpected GSUP");
756 mtc.stop;
757 }
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200758 [] T.timeout {
759 setverdict(fail, "Timeout waiting for PROC_SS response");
760 self.stop;
761 }
762 }
763
764 return ret;
765}
766
Oliver Smith936dbe62019-06-04 15:54:17 +0200767function f_perform_CHECK_IMEI(hexstring imsi, hexstring imei,
768 template (omit) integer exp_err_cause := omit,
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100769 template (omit) GSUP_IMEIResult result := omit,
770 template (omit) octetstring source_name := omit)
Oliver Smith936dbe62019-06-04 15:54:17 +0200771runs on HLR_ConnHdlr {
772 var GSUP_PDU pdu;
773 timer T := 3.0;
774 var boolean exp_fail := false;
775 if (not istemplatekind(exp_err_cause, "omit")) {
776 exp_fail := true;
777 }
778
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100779 GSUP.send(valueof(ts_GSUP_CHECK_IMEI_REQ(imsi, imei, source_name := source_name)));
Oliver Smith936dbe62019-06-04 15:54:17 +0200780 T.start;
781 alt {
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100782 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, exp_err_cause, destination_name := source_name)) -> value pdu {
Oliver Smith936dbe62019-06-04 15:54:17 +0200783 setverdict(pass);
784 }
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100785 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?, destination_name := source_name)) -> value pdu {
Oliver Smith936dbe62019-06-04 15:54:17 +0200786 setverdict(fail, "Unexpected CHECK IMEI ERROR Cause: ", pdu);
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100787 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200788 }
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100789 [exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?, destination_name := source_name)) -> value pdu {
Oliver Smith936dbe62019-06-04 15:54:17 +0200790 setverdict(fail, "Unexpected CHECK IMEI RES instead of ERR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100791 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200792 }
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100793 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_ERR(imsi, ?, destination_name := source_name)) -> value pdu {
Oliver Smith936dbe62019-06-04 15:54:17 +0200794 setverdict(fail, "Unexpected CHECK IMEI ERROR");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100795 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200796 }
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100797 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, result, destination_name := source_name)) -> value pdu {
Oliver Smith936dbe62019-06-04 15:54:17 +0200798 setverdict(pass);
799 }
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100800 [not exp_fail] GSUP.receive(tr_GSUP_CHECK_IMEI_RES(imsi, ?, destination_name := source_name)) -> value pdu {
Oliver Smith936dbe62019-06-04 15:54:17 +0200801 setverdict(fail, "Unexpected CHECK IMEI RES");
Neels Hofmeyrc0c1aca2019-11-11 03:40:46 +0100802 mtc.stop;
Oliver Smith936dbe62019-06-04 15:54:17 +0200803 }
804 [] GSUP.receive { repeat; }
805 [] T.timeout {
806 setverdict(fail, "Timeout waiting for CHECK IMEI response");
807 mtc.stop;
808 }
809 }
810}
811
812
Harald Welte4ea1f8a2018-06-12 09:26:10 +0200813
Harald Welte958f8b42018-03-01 23:40:17 +0100814
Harald Welteed380d12018-06-14 13:42:11 +0200815/***********************************************************************
816 * Testcases
817 ***********************************************************************/
818
819/* 23.003 Section 2.2 clearly states that an IMSI with less
820 * than 5 digits is impossible. Even 5 digits is still questionable */
821private function f_TC_gsup_sai_err_invalid_imsi() runs on HLR_ConnHdlr {
Harald Weltec2c52552018-03-01 21:20:39 +0100822 var GSUP_PDU res;
Harald Welteed380d12018-06-14 13:42:11 +0200823 res := f_perform_SAI(g_pars.sub.imsi, 96); /* Invalid Mandatory information */
824 setverdict(pass);
825}
826testcase TC_gsup_sai_err_invalid_imsi() runs on test_CT {
827 var HLR_ConnHdlr vc_conn;
828 var HLR_ConnHdlrPars pars := valueof(t_Pars('0123'H));
829 f_init(false);
830 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_invalid_imsi), pars);
831 vc_conn.done;
832}
Harald Weltec2c52552018-03-01 21:20:39 +0100833
Harald Weltec2c52552018-03-01 21:20:39 +0100834
Harald Welteed380d12018-06-14 13:42:11 +0200835private function f_TC_gsup_sai_err_unknown_imsi() runs on HLR_ConnHdlr {
836 var GSUP_PDU res;
837 res := f_perform_SAI(g_pars.sub.imsi, 2);
Harald Weltec2c52552018-03-01 21:20:39 +0100838 setverdict(pass);
839}
840
Harald Welte3f662762018-03-02 10:48:20 +0100841testcase TC_gsup_sai_err_unknown_imsi() runs on test_CT {
Harald Welteed380d12018-06-14 13:42:11 +0200842 var HLR_ConnHdlr vc_conn;
843 var HLR_ConnHdlrPars pars := valueof(t_Pars(f_rnd_imsi('26242'H)));
844 f_init(false);
845 vc_conn := f_start_handler(refers(f_TC_gsup_sai_err_unknown_imsi), pars);
846 vc_conn.done;
Harald Welte3f662762018-03-02 10:48:20 +0100847}
848
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100849function f_start_handler_per_sub(void_fn fn, HlrSubscriberList sl, boolean via_proxy := false) runs on test_CT {
Harald Welteed380d12018-06-14 13:42:11 +0200850 for (var integer i := 0; i < sizeof(sl); i := i+1) {
851 var HlrSubscriber sub := sl[i];
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100852 var HLR_ConnHdlrPars pars;
853 if (via_proxy) {
854 pars := valueof(t_Pars_sub_via_proxy(sub));
855 } else {
856 pars := valueof(t_Pars_sub(sub));
857 }
Harald Welteed380d12018-06-14 13:42:11 +0200858 var HLR_ConnHdlr vc_conn;
859
860 f_vty_subscr_create(VTY, sub);
861 vc_conn := f_start_handler(fn, pars);
862 vc_conn.done;
863 f_vty_subscr_delete(VTY, sub);
864 }
865}
Harald Welte3f662762018-03-02 10:48:20 +0100866
Harald Weltec2c52552018-03-01 21:20:39 +0100867/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
Harald Welteed380d12018-06-14 13:42:11 +0200868private function f_TC_gsup_sai() runs on HLR_ConnHdlr {
869 var GSUP_PDU res;
870 res := f_perform_SAI(g_pars.sub.imsi);
Harald Welte4b612042019-12-03 20:08:57 +0100871 if (ispresent(g_pars.sub.aud3g)) {
872 f_ensure_amf_separation_bit(res, '0'B);
873 }
Alexander Couzens92696442020-01-10 07:57:16 +0100874
875 f_count_auth_tuples(res, mp_default_num_auth_tuples);
Harald Welteed380d12018-06-14 13:42:11 +0200876 setverdict(pass);
877}
Harald Weltec2c52552018-03-01 21:20:39 +0100878testcase TC_gsup_sai() runs on test_CT {
879 var HlrSubscriberList sl;
880 var GSUP_PDU res;
881
Harald Welteed380d12018-06-14 13:42:11 +0200882 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +0100883
884 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +0200885 f_start_handler_per_sub(refers(f_TC_gsup_sai), sl);
Harald Weltec2c52552018-03-01 21:20:39 +0100886
887 setverdict(pass);
888}
889
Alexander Couzens92696442020-01-10 07:57:16 +0100890/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
891private function f_TC_gsup_sai_num_auth_vectors() runs on HLR_ConnHdlr {
892 var GSUP_PDU res;
893 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 1);
894 f_count_auth_tuples(res, 1);
895 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 4);
896 f_count_auth_tuples(res, 4);
897 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 5);
898 f_count_auth_tuples(res, 5);
899 res := f_perform_SAI(g_pars.sub.imsi, num_auth_tuple := 254);
900 f_count_auth_tuples(res, 5);
901 setverdict(pass);
902}
903testcase TC_gsup_sai_num_auth_vectors() runs on test_CT {
904 var HlrSubscriberList sl;
905 var GSUP_PDU res;
906
907 f_init(false);
908
909 sl := f_gen_subs();
910 f_start_handler_per_sub(refers(f_TC_gsup_sai_num_auth_vectors), sl);
911
912 setverdict(pass);
913}
914
Harald Welteaf7c3182019-08-22 12:40:22 +0200915private function f_ensure_amf_separation_bit(GSUP_PDU res, BIT1 sep_bit)
916{
917 for (var integer i := 0; i < lengthof(res.ies); i := i+1) {
918 var GSUP_IE tuple := res.ies[i];
919 if (tuple.tag != OSMO_GSUP_AUTH_TUPLE_IE) {
920 continue;
921 }
922 var GSUP_IeValue autn;
923 if (f_gsup_find_nested_ie(tuple.val.auth_tuple, OSMO_GSUP_AUTN_IE, autn) == false) {
924 setverdict(fail, "Couldn't find AUTN IE in tuple ", i);
925 mtc.stop;
926 }
927 var bitstring amf := oct2bit(substr(autn.autn, 6, 2));
928 if (amf[0] != sep_bit) {
929 setverdict(fail, "AMF bit 0 (separation bit) must be ", sep_bit," but was not");
930 mtc.stop;
931 }
932 }
933}
934
Alexander Couzens92696442020-01-10 07:57:16 +0100935private function f_count_auth_tuples(GSUP_PDU res, template (omit) integer expected_auth_tuples := omit)
936{
937 var integer auth_tuples := 0;
938 for (var integer i := 0; i < lengthof(res.ies); i := i+1) {
939 var GSUP_IE tuple := res.ies[i];
940 if (tuple.tag == OSMO_GSUP_AUTH_TUPLE_IE) {
941 auth_tuples := auth_tuples + 1;
942 }
943 }
944
945 if ((not istemplatekind(expected_auth_tuples, "omit")) and
946 not match(auth_tuples, valueof(expected_auth_tuples))) {
947 setverdict(fail,
948 "Did not received expected number of auth tuples. Expected ",
949 mp_default_num_auth_tuples,
950 " but received ", auth_tuples);
951 }
952}
953
Harald Welteaf7c3182019-08-22 12:40:22 +0200954/* test SAI for a number of different subscriber cases (algo, 2g/3g, ...) */
955private function f_TC_gsup_sai_eps() runs on HLR_ConnHdlr {
956 var GSUP_PDU res;
957 res := f_perform_SAI(g_pars.sub.imsi, is_eps := true);
958 f_ensure_amf_separation_bit(res, '1'B);
959
960 /* TODO: match if tuple[s] matches expectation */
961 setverdict(pass);
962}
963testcase TC_gsup_sai_eps() runs on test_CT {
964 var HlrSubscriberList sl;
965 var GSUP_PDU res;
966
967 f_init(false);
968
969 sl := f_gen_3G_subs();
970 f_start_handler_per_sub(refers(f_TC_gsup_sai_eps), sl);
971
972 setverdict(pass);
973}
974
975
Harald Weltec2c52552018-03-01 21:20:39 +0100976/* test UL for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +0200977private function f_TC_ul_unknown_imsi() runs on HLR_ConnHdlr {
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100978 f_perform_UL(g_pars.sub.imsi, ?, 2, source_name := g_pars.source_name);
Harald Weltec2c52552018-03-01 21:20:39 +0100979 setverdict(pass);
980}
Harald Welteed380d12018-06-14 13:42:11 +0200981testcase TC_gsup_ul_unknown_imsi() runs on test_CT {
982 var hexstring imsi := f_rnd_imsi('26242'H);
983 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
984 var HLR_ConnHdlr vc_conn;
Harald Weltec2c52552018-03-01 21:20:39 +0100985
Harald Welteed380d12018-06-14 13:42:11 +0200986 f_init(false);
987 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
988 vc_conn.done;
989}
Neels Hofmeyrb2168512019-11-11 03:40:26 +0100990testcase TC_gsup_ul_unknown_imsi_via_proxy() runs on test_CT {
991 var hexstring imsi := f_rnd_imsi('26242'H);
992 var HLR_ConnHdlrPars pars := valueof(t_Pars_via_proxy(imsi));
993 var HLR_ConnHdlr vc_conn;
994
995 f_init(false);
996 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
997 vc_conn.done;
998}
Harald Welteed380d12018-06-14 13:42:11 +0200999
1000/* test UL for a number of different subscriber cases (algo, 2g/3g, ...) */
1001private function f_TC_gsup_ul() runs on HLR_ConnHdlr {
Alexander Couzens25d28492023-04-26 19:30:04 +02001002 var GSUP_PDUs res;
Neels Hofmeyrb2168512019-11-11 03:40:26 +01001003 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn, source_name := g_pars.source_name);
Harald Welteed380d12018-06-14 13:42:11 +02001004 setverdict(pass);
1005}
Alexander Couzens25d28492023-04-26 19:30:04 +02001006
Harald Weltec2c52552018-03-01 21:20:39 +01001007testcase TC_gsup_ul() runs on test_CT {
1008 var HlrSubscriberList sl;
Alexander Couzens25d28492023-04-26 19:30:04 +02001009 var GSUP_PDUs res;
Harald Weltec2c52552018-03-01 21:20:39 +01001010
Harald Welteed380d12018-06-14 13:42:11 +02001011 f_init(false);
Harald Weltec2c52552018-03-01 21:20:39 +01001012 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +02001013 f_start_handler_per_sub(refers(f_TC_gsup_ul), sl);
Harald Weltec2c52552018-03-01 21:20:39 +01001014
1015 setverdict(pass);
1016}
Neels Hofmeyrb2168512019-11-11 03:40:26 +01001017testcase TC_gsup_ul_via_proxy() runs on test_CT {
1018 var HlrSubscriberList sl;
1019 var GSUP_PDU res;
1020
1021 f_init(false);
1022 sl := f_gen_subs();
1023 f_start_handler_per_sub(refers(f_TC_gsup_ul), sl, via_proxy := true);
1024
1025 setverdict(pass);
1026}
Harald Weltec2c52552018-03-01 21:20:39 +01001027
Alexander Couzens25d28492023-04-26 19:30:04 +02001028private function f_TC_gsup_ul_subscriber_data() runs on HLR_ConnHdlr {
1029 var GSUP_PDUs pdus;
1030 var GSUP_PDU isd;
1031 log("GSUP ul subscriber_data", isd);
1032 pdus := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn, source_name := g_pars.source_name);
1033 isd := pdus[1];
1034
1035 template GSUP_IEs tr_pdp_info_internet := {
1036 tr_GSUP_IE_PDP_CONTEXT_ID('01'O),
1037 tr_GSUP_IE_APN(str2apn("internet"))
1038 }
1039 template GSUP_IEs tr_pdp_info_wildcard := {
1040 tr_GSUP_IE_PDP_CONTEXT_ID('02'O),
1041 tr_GSUP_IE_APN(str2apn("*"))
1042 }
1043
1044 /* Search for PDP info 'internet', '*' */
1045 var boolean found := false;
1046 var GSUP_IeValue ievalue;
1047 var GSUP_IEs pdp_info;
1048 found := f_gsup_find_nested_ie_multiple(isd.ies, OSMO_GSUP_PDP_INFO_IE, 0, ievalue);
1049 if (not found) {
1050 setverdict(fail, "Multiple APNs: Coulnd't find first PDP Info IE in: ", isd);
1051 return;
1052 }
1053 pdp_info := ievalue.pdp_info;
1054 if (not match(pdp_info, tr_pdp_info_internet)) {
1055 setverdict(fail, "Multiple APNs: first PDP Info doesn't match: ", pdp_info, "on Template: ", tr_pdp_info_internet);
1056 return;
1057 }
1058
1059 /* wildcard '*' */
1060 found := f_gsup_find_nested_ie_multiple(isd.ies, OSMO_GSUP_PDP_INFO_IE, 1, ievalue);
1061 if (not found) {
1062 setverdict(fail, "Multiple APNs: Coulnd't find second PDP Info IE in: ", isd);
1063 return;
1064 }
1065 pdp_info := ievalue.pdp_info;
1066 if (not match(pdp_info, tr_pdp_info_wildcard)) {
1067 setverdict(fail, "Multiple APNs: second PDP Info doesn't match: ", pdp_info, "on Template: ", tr_pdp_info_wildcard);
1068 return;
1069 }
1070
1071 setverdict(pass);
1072}
1073
1074testcase TC_gsup_ul_subscriber_data() runs on test_CT {
1075 /* Do a GSUP Update Location Request to get a Insert Subscriber Data Request (ISD).
1076 * Check for multiple APN in the ISD:
1077 * SGSN -> HLR: Update Location Request
1078 * SGSN <- HLR: Insert Subscriber Data Request (Check the TLV)
1079 * SGSN -> HLR: Insert Subscriber Data Result
1080 * SGSN <- HLR: Update Location Result
1081 */
1082 var HlrSubscriberList sl;
1083
1084 f_init(false);
1085 f_vty_config2(VTY, {"hlr", "ps"} , "no pdp-profiles default");
1086 f_vty_config2(VTY, {"hlr", "ps", "pdp-profiles default", "profile 1"}, "apn internet");
1087 f_vty_config2(VTY, {"hlr", "ps", "pdp-profiles default", "profile 2"}, "apn *");
1088 sl := f_gen_subs();
1089 f_start_handler_per_sub(refers(f_TC_gsup_ul_subscriber_data), sl);
1090
1091 setverdict(pass);
1092}
1093
Harald Weltec2c52552018-03-01 21:20:39 +01001094/* Test only the VTY commands */
1095testcase TC_vty() runs on test_CT {
1096 var HlrSubscriber sub;
1097
1098 f_init();
1099
1100 /* we're not using f_gen_subs() here as the expect pattern for the 'show' are different
1101 * from case to case */
1102 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
Harald Welteed380d12018-06-14 13:42:11 +02001103 f_vty_subscr_create(VTY, sub);
1104 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*");
1105 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +01001106
1107 sub := valueof(t_Sub3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
1108 "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +02001109 f_vty_subscr_create(VTY, sub);
1110 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *3G auth: MILENAGE*");
1111 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +01001112
1113 sub := valueof(t_Sub2G3G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9),
1114 "comp128v1", "milenage", false));
Harald Welteed380d12018-06-14 13:42:11 +02001115 f_vty_subscr_create(VTY, sub);
1116 f_vty_subscr_show(VTY, sub, pattern "*IMSI: *2G auth: COMP128v1*3G auth: MILENAGE*");
1117 f_vty_subscr_delete(VTY, sub);
Harald Weltec2c52552018-03-01 21:20:39 +01001118
1119 setverdict(pass);
1120}
1121
Harald Welte09b3c502018-03-01 22:42:22 +01001122/* VTY changes to MSISDN should result in ISD to current VLR */
Harald Welteed380d12018-06-14 13:42:11 +02001123private function f_TC_vty_msisdn_isd() runs on HLR_ConnHdlr {
Harald Welte09b3c502018-03-01 22:42:22 +01001124 var hexstring new_msisdn;
Alexander Couzens25d28492023-04-26 19:30:04 +02001125 var GSUP_PDUs res;
Harald Welte09b3c502018-03-01 22:42:22 +01001126 timer T := 5.0;
1127
Harald Welte09b3c502018-03-01 22:42:22 +01001128 /* Create Subscriber */
Harald Welteed380d12018-06-14 13:42:11 +02001129 f_vty_subscr_create(VTY, g_pars.sub);
Harald Welte09b3c502018-03-01 22:42:22 +01001130
1131 /* Perform UpdateLocation (VLR now known to HLR) */
Harald Welteed380d12018-06-14 13:42:11 +02001132 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +01001133
1134 /* Then change IMSI via VTY */
1135 new_msisdn := '49161'H & f_rnd_hexstring(7, 9);
Harald Welteed380d12018-06-14 13:42:11 +02001136 f_vty_subscr_update_msisdn(VTY, g_pars.sub, new_msisdn);
Harald Welte09b3c502018-03-01 22:42:22 +01001137 /* And expect InsertSubscriberData as result */
1138 T.start;
1139 alt {
Harald Welteed380d12018-06-14 13:42:11 +02001140 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, new_msisdn)) {
1141 GSUP.send(ts_GSUP_ISD_RES(g_pars.sub.imsi));
1142 g_pars.sub.msisdn := new_msisdn;
Harald Welte09b3c502018-03-01 22:42:22 +01001143 setverdict(pass);
1144 }
Harald Welteed380d12018-06-14 13:42:11 +02001145 [] GSUP.receive(tr_GSUP_ISD_REQ(g_pars.sub.imsi, g_pars.sub.msisdn)) {
Stefan Sperling7c096872018-04-09 11:24:22 +02001146 log("received ISD req with old MSISDN");
1147 setverdict(fail);
1148 }
Harald Welte09b3c502018-03-01 22:42:22 +01001149 [] GSUP.receive { repeat; }
1150 [] T.timeout {
1151 setverdict(fail, "Timeout waiting for ISD.req");
1152 }
1153 }
1154}
Harald Welteed380d12018-06-14 13:42:11 +02001155testcase TC_vty_msisdn_isd() runs on test_CT {
1156 var HlrSubscriber sub;
1157 var HLR_ConnHdlr vc_conn;
1158
1159 f_init(false);
1160
1161 /* Create Subscriber */
1162 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H), '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
1163
1164 vc_conn := f_start_handler(refers(f_TC_vty_msisdn_isd), valueof(t_Pars_sub(sub)));
1165 vc_conn.done;
1166}
Harald Welte09b3c502018-03-01 22:42:22 +01001167
Harald Welte958f8b42018-03-01 23:40:17 +01001168/* Test PURGE MS for CS services */
Harald Welteed380d12018-06-14 13:42:11 +02001169private function f_TC_gsup_purge_cs() runs on HLR_ConnHdlr {
Alexander Couzens25d28492023-04-26 19:30:04 +02001170 var GSUP_PDUs res;
1171 var GSUP_PDU pdu;
Harald Welteed380d12018-06-14 13:42:11 +02001172 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
Alexander Couzens25d28492023-04-26 19:30:04 +02001173 pdu := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS);
Harald Welteed380d12018-06-14 13:42:11 +02001174}
Harald Welte958f8b42018-03-01 23:40:17 +01001175testcase TC_gsup_purge_cs() runs on test_CT {
1176 var HlrSubscriberList sl;
1177 var GSUP_PDU res;
1178
Harald Welteed380d12018-06-14 13:42:11 +02001179 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +01001180 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +02001181 f_start_handler_per_sub(refers(f_TC_gsup_purge_cs), sl);
Harald Welte958f8b42018-03-01 23:40:17 +01001182
1183 setverdict(pass);
1184}
1185
1186/* Test PURGE MS for PS services */
Harald Welteed380d12018-06-14 13:42:11 +02001187private function f_TC_gsup_purge_ps() runs on HLR_ConnHdlr {
Alexander Couzens25d28492023-04-26 19:30:04 +02001188 var GSUP_PDUs res;
1189 var GSUP_PDU pdu;
Harald Welteed380d12018-06-14 13:42:11 +02001190 res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
Alexander Couzens25d28492023-04-26 19:30:04 +02001191 pdu := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_PS);
Harald Welteed380d12018-06-14 13:42:11 +02001192}
Harald Welte958f8b42018-03-01 23:40:17 +01001193testcase TC_gsup_purge_ps() runs on test_CT {
1194 var HlrSubscriberList sl;
Harald Welte958f8b42018-03-01 23:40:17 +01001195
Harald Welteed380d12018-06-14 13:42:11 +02001196 f_init(false);
Harald Welte958f8b42018-03-01 23:40:17 +01001197 sl := f_gen_subs();
Harald Welteed380d12018-06-14 13:42:11 +02001198 f_start_handler_per_sub(refers(f_TC_gsup_purge_ps), sl);
Harald Welte958f8b42018-03-01 23:40:17 +01001199
1200 setverdict(pass);
1201}
1202
1203/* Test PURGEG MS procedure for unknown IMSI */
Harald Welteed380d12018-06-14 13:42:11 +02001204
1205private function f_TC_gsup_purge_unknown() runs on HLR_ConnHdlr {
1206 var GSUP_PDU res;
1207 res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS, 2);
1208}
Harald Welte958f8b42018-03-01 23:40:17 +01001209testcase TC_gsup_purge_unknown() runs on test_CT {
1210 var hexstring imsi := '2345743413463'H;
Harald Welteed380d12018-06-14 13:42:11 +02001211 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1212 var HLR_ConnHdlr vc_conn;
Harald Welte958f8b42018-03-01 23:40:17 +01001213
Harald Welteed380d12018-06-14 13:42:11 +02001214 f_init(false);
1215 vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
1216 vc_conn.done;
Harald Welte958f8b42018-03-01 23:40:17 +01001217
1218 setverdict(pass);
1219}
1220
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001221import from HLR_EUSE all;
1222
1223/* Test for USSD request to undefined/unrouted short-code. Expect ss-NotAvailable(18) */
1224private function f_TC_mo_ussd_unknown() runs on HLR_ConnHdlr {
1225 var GSUP_PDU res;
1226 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1227 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1228 ussd_string := "*#200#");
1229 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1230 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001231 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1232 OSMO_GSUP_SESSION_STATE_END,
1233 tr_SS_FACILITY_RETURN_ERROR(1, 18));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001234}
1235testcase TC_mo_ussd_unknown() runs on test_CT {
1236 var HlrSubscriberList sl;
1237 var HLR_ConnHdlr vc_conn;
1238
1239 f_init(false);
1240 sl := f_gen_subs();
1241 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1242 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1243 pars.ussd.sid := f_rnd_octstring(4);
1244 f_vty_subscr_create(VTY, pars.sub);
1245 vc_conn := f_start_handler(refers(f_TC_mo_ussd_unknown), pars);
1246 vc_conn.done;
1247 }
1248}
1249
1250/* Test for USSD request to currently disconnected EUSE. Expect ss-SystemFailure(34) */
1251private function f_TC_mo_ussd_euse_disc() runs on HLR_ConnHdlr {
1252 var GSUP_PDU res;
1253 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1254 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1255 ussd_string := "*100#");
1256 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1257 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001258 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1259 OSMO_GSUP_SESSION_STATE_END,
1260 tr_SS_FACILITY_RETURN_ERROR(1, 34));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001261}
1262testcase TC_mo_ussd_euse_disc() runs on test_CT {
1263 var HlrSubscriberList sl;
1264 var HLR_ConnHdlr vc_conn;
1265
1266 f_init(false);
1267 sl := f_gen_subs();
1268 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1269 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1270 pars.ussd.sid := f_rnd_octstring(4);
1271 f_vty_subscr_create(VTY, pars.sub);
1272 vc_conn := f_start_handler(refers(f_TC_mo_ussd_euse_disc), pars);
1273 vc_conn.done;
1274 }
1275}
1276
1277/* Test for USSD request to internal own-imsi IUSE. */
1278private function f_TC_mo_ussd_iuse_imsi() runs on HLR_ConnHdlr {
1279 var GSUP_PDU res;
1280 var charstring resp_str;
1281 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1282 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1283 ussd_string := "*#101#");
1284 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
Neels Hofmeyrb2168512019-11-11 03:40:26 +01001285 OSMO_GSUP_SESSION_STATE_BEGIN, ss,
1286 source_name := g_pars.source_name)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001287 resp_str := "Your IMSI is " & hex2str(g_pars.sub.imsi);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001288 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1289 OSMO_GSUP_SESSION_STATE_END,
1290 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
Neels Hofmeyrb2168512019-11-11 03:40:26 +01001291 f_encGSM7bit(resp_str)),
1292 destination_name := g_pars.source_name);
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001293}
1294testcase TC_mo_ussd_iuse_imsi() runs on test_CT {
1295 var HlrSubscriberList sl;
1296 var HLR_ConnHdlr vc_conn;
1297
1298 f_init(false);
1299 sl := f_gen_subs();
1300 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1301 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1302 pars.ussd.sid := f_rnd_octstring(4);
1303 f_vty_subscr_create(VTY, pars.sub);
1304 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_imsi), pars);
1305 vc_conn.done;
1306 }
1307}
Neels Hofmeyrb2168512019-11-11 03:40:26 +01001308testcase TC_mo_ussd_iuse_imsi_via_proxy() runs on test_CT {
1309 var HlrSubscriberList sl;
1310 var HLR_ConnHdlr vc_conn;
1311
1312 f_init(false);
1313 sl := f_gen_subs();
1314 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1315 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub_via_proxy(sl[i]));
1316 pars.ussd.sid := f_rnd_octstring(4);
1317 f_vty_subscr_create(VTY, pars.sub);
1318 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_imsi), pars);
1319 vc_conn.done;
1320 }
1321}
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001322
1323/* Test for USSD request to internal own-msisdn IUSE. */
1324private function f_TC_mo_ussd_iuse_msisdn() runs on HLR_ConnHdlr {
1325 var GSUP_PDU res;
1326 var charstring resp_str;
1327 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1328 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1329 ussd_string := "*#100#");
1330 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
Neels Hofmeyrb2168512019-11-11 03:40:26 +01001331 OSMO_GSUP_SESSION_STATE_BEGIN, ss,
1332 source_name := g_pars.source_name)));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001333 resp_str := "Your extension is " & hex2str(g_pars.sub.msisdn);
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001334 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1335 OSMO_GSUP_SESSION_STATE_END,
1336 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
Neels Hofmeyrb2168512019-11-11 03:40:26 +01001337 f_encGSM7bit(resp_str)),
1338 destination_name := g_pars.source_name);
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001339}
1340testcase TC_mo_ussd_iuse_msisdn() runs on test_CT {
1341 var HlrSubscriberList sl;
1342 var HLR_ConnHdlr vc_conn;
1343
1344 f_init(false);
1345 sl := f_gen_subs();
1346 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1347 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1348 pars.ussd.sid := f_rnd_octstring(4);
1349 f_vty_subscr_create(VTY, pars.sub);
1350 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_msisdn), pars);
1351 vc_conn.done;
1352 }
1353}
Neels Hofmeyrb2168512019-11-11 03:40:26 +01001354testcase TC_mo_ussd_iuse_msisdn_via_proxy() runs on test_CT {
1355 var HlrSubscriberList sl;
1356 var HLR_ConnHdlr vc_conn;
1357
1358 f_init(false);
1359 sl := f_gen_subs();
1360 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1361 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub_via_proxy(sl[i]));
1362 pars.ussd.sid := f_rnd_octstring(4);
1363 f_vty_subscr_create(VTY, pars.sub);
1364 vc_conn := f_start_handler(refers(f_TC_mo_ussd_iuse_msisdn), pars);
1365 vc_conn.done;
1366 }
1367}
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001368
1369/* Test routing of USSD to EUSE by a specific route */
1370private function f_TC_mo_ussd_100() runs on HLR_ConnHdlr {
1371 var GSUP_PDU res;
1372 /* invoke / invoke id 1 / processUSS-req */
1373 //var octetstring ss := 'a11202010102013b300a04010f0405aa180c3602'O;
1374 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1375 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1376 ussd_string := "*100#");
1377 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1378 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001379 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1380 OSMO_GSUP_SESSION_STATE_END,
1381 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1382 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001383}
1384testcase TC_mo_ussd_euse() runs on test_CT {
1385 var HlrSubscriberList sl;
1386 var HLR_ConnHdlr vc_conn;
1387
1388 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1389 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
1390
1391 f_init(false);
1392 sl := f_gen_subs();
1393 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1394 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1395 pars.ussd.sid := f_rnd_octstring(4);
1396 f_vty_subscr_create(VTY, pars.sub);
1397 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100), pars);
1398 vc_conn.done;
1399 }
1400
1401 vc_EUSE.stop;
1402}
1403
1404/* Test routing of USSD to EUSE by a specific route, with CONTINUE */
1405private function f_TC_mo_ussd_100_continue() runs on HLR_ConnHdlr {
1406 var GSUP_PDU res;
1407 /* Simulate BEGIN from MS/MSC */
1408 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1409 ussd_string := "*100#");
1410 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1411 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
1412 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001413 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1414 OSMO_GSUP_SESSION_STATE_CONTINUE,
1415 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1416 f_encGSM7bit("*100#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001417
1418 /* Simulate CONTINUE from MS/MSC */
1419 ss := f_USSD_FACILITY_IE_INVOKE(op_code := SS_OP_CODE_PROCESS_USS_REQ,
1420 ussd_string := "mahlzeit");
1421 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1422 OSMO_GSUP_SESSION_STATE_CONTINUE, ss)));
1423
1424 /* expect echo response from EUSE */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001425 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1426 OSMO_GSUP_SESSION_STATE_END,
1427 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1428 f_encGSM7bit("mahlzeit")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001429}
1430testcase TC_mo_ussd_euse_continue() runs on test_CT {
1431 var HlrSubscriberList sl;
1432 var HLR_ConnHdlr vc_conn;
1433
1434 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1435 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar",
1436 refers(f_ss_echo_continue)));
1437
1438 f_init(false);
1439 sl := f_gen_subs();
1440 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1441 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1442 pars.ussd.sid := f_rnd_octstring(4);
1443 f_vty_subscr_create(VTY, pars.sub);
1444 vc_conn := f_start_handler(refers(f_TC_mo_ussd_100_continue), pars);
1445 vc_conn.done;
1446 }
1447
1448 vc_EUSE.stop;
1449}
1450
1451
1452/* Test routing of USSD to EUSE by default-route */
1453private function f_TC_mo_ussd_999() runs on HLR_ConnHdlr {
1454 var GSUP_PDU res;
1455 var octetstring ss := f_USSD_FACILITY_IE_INVOKE(
1456 op_code := SS_OP_CODE_PROCESS_USS_REQ,
1457 ussd_string := "*999#");
1458 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(g_pars.sub.imsi, g_pars.ussd.sid,
1459 OSMO_GSUP_SESSION_STATE_BEGIN, ss)));
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001460 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1461 OSMO_GSUP_SESSION_STATE_END,
1462 tr_SS_USSD_FACILITY_RETURN_RESULT(1, 59, SS_USSD_DEFAULT_DCS,
1463 f_encGSM7bit("*999#")));
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001464}
1465testcase TC_mo_ussd_euse_defaultroute() runs on test_CT {
1466 var HlrSubscriberList sl;
1467 var HLR_ConnHdlr vc_conn;
1468
1469 var HLR_EUSE_CT vc_EUSE := HLR_EUSE_CT.create("EUSE-" & testcasename());
1470 vc_EUSE.start(HLR_EUSE.f_main_mo(mp_hlr_ip, mp_hlr_gsup_port, "foobar", refers(f_ss_echo)));
1471
1472 f_init(false);
1473 f_vty_config(VTY, "hlr", "ussd default-route external foobar");
1474
1475 sl := f_gen_subs();
1476 for (var integer i := 0; i < sizeof(sl); i := i+1) {
1477 var HLR_ConnHdlrPars pars := valueof(t_Pars_sub(sl[i]));
1478 pars.ussd.sid := f_rnd_octstring(4);
1479 f_vty_subscr_create(VTY, pars.sub);
1480 vc_conn := f_start_handler(refers(f_TC_mo_ussd_999), pars);
1481 vc_conn.done;
1482 }
1483
1484 f_vty_config(VTY, "hlr", "no ussd default-route");
1485 vc_EUSE.stop;
1486}
1487
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001488/**
1489 * Test "Structured" Supplementary Services
1490 *
1491 * NOTE: at the moment, OsmoHLR doesn't support "structured" SS,
1492 * so such requests are being rejected (actually ReturnError
1493 * with GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED).
1494 */
1495private function f_TC_mo_sss_reject() runs on HLR_ConnHdlr {
1496 var SS_FacilityInformation ss_req;
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001497 var GSUP_PDU res;
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001498
1499 /* Prepare '*#21#' SS request */
1500 ss_req := valueof(ts_SS_FACILITY_INVOKE(
1501 invoke_id := 0,
1502 op_code := SS_OP_CODE_INTERROGATE_SS,
1503 ss_code := '21'O));
1504
1505 /* Send it towards HLR */
1506 GSUP.send(valueof(ts_GSUP_PROC_SS_REQ(
1507 g_pars.sub.imsi,
1508 g_pars.ussd.sid,
1509 OSMO_GSUP_SESSION_STATE_BEGIN,
1510 enc_SS_FacilityInformation(ss_req))));
1511
1512 /* Expect ReturnError with FACILITY_NOT_SUPPORTED */
Vadim Yanitskiy06e53c52019-03-28 15:08:24 +07001513 res := f_SS_expect(g_pars.sub.imsi, g_pars.ussd.sid,
1514 OSMO_GSUP_SESSION_STATE_END,
1515 tr_SS_FACILITY_RETURN_ERROR(0, 21));
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07001516}
1517testcase TC_mo_sss_reject() runs on test_CT {
1518 var HLR_ConnHdlrPars pars;
1519 var HLR_ConnHdlr vc_conn;
1520 var HlrSubscriber sub;
1521
1522 f_init(false);
1523
1524 /* Create a random subscriber */
1525 sub := valueof(t_Sub2G(f_rnd_imsi('26242'H),
1526 '49161'H & f_rnd_hexstring(7, 9), "comp128v1"));
1527 pars := valueof(t_Pars_sub(sub));
1528 pars.ussd.sid := f_rnd_octstring(4);
1529
1530 f_vty_subscr_create(VTY, sub);
1531 vc_conn := f_start_handler(refers(f_TC_mo_sss_reject), pars);
1532 vc_conn.done;
1533 f_vty_subscr_delete(VTY, sub);
1534}
1535
Harald Welte4ea1f8a2018-06-12 09:26:10 +02001536
1537/* TODO USSD:
1538 * MO USSD for IMSI of non-existant subscriber
1539 * MT USSD from EUSE
1540 * timeout cases
1541 */
1542
Oliver Smith936dbe62019-06-04 15:54:17 +02001543
1544/* Test Check IMEI */
1545private function f_TC_gsup_check_imei() runs on HLR_ConnHdlr {
1546 /* store-imei disabled */
1547 f_vty_config(VTY, "hlr", "no store-imei");
Neels Hofmeyrb2168512019-11-11 03:40:26 +01001548 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK,
1549 source_name := g_pars.source_name);
Oliver Smith936dbe62019-06-04 15:54:17 +02001550 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1551
1552 /* store-imei enabled */
1553 f_vty_config(VTY, "hlr", "store-imei");
Neels Hofmeyrb2168512019-11-11 03:40:26 +01001554 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK,
1555 source_name := g_pars.source_name);
Oliver Smith936dbe62019-06-04 15:54:17 +02001556 f_vty_subscr_show(VTY, g_pars.sub, pattern "*IMEI: *12345678901234*");
1557}
1558testcase TC_gsup_check_imei() runs on test_CT {
1559 var HlrSubscriberList sl;
1560
1561 f_init(false);
1562 sl := f_gen_subs();
1563 f_start_handler_per_sub(refers(f_TC_gsup_check_imei), sl);
1564
1565 setverdict(pass);
1566}
Neels Hofmeyrb2168512019-11-11 03:40:26 +01001567testcase TC_gsup_check_imei_via_proxy() runs on test_CT {
1568 var HlrSubscriberList sl;
1569
1570 f_init(false);
1571 sl := f_gen_subs();
1572 f_start_handler_per_sub(refers(f_TC_gsup_check_imei), sl, via_proxy := true);
1573
1574 setverdict(pass);
1575}
Oliver Smith936dbe62019-06-04 15:54:17 +02001576
1577/* Test Check IMEI with invalid IMEI length */
1578private function f_TC_gsup_check_imei_invalid_len() runs on HLR_ConnHdlr {
1579 /* IMEI too long */
1580 f_perform_CHECK_IMEI(g_pars.sub.imsi, '111456789012345F'H, 96 /* Invalid Mandatory Information */);
1581 f_perform_CHECK_IMEI(g_pars.sub.imsi, '2224567890123456'H, 96 /* Invalid Mandatory Information */);
1582
1583 /* IMEI too short */
1584 f_perform_CHECK_IMEI(g_pars.sub.imsi, '3334567890123F'H, 96 /* Invalid Mandatory Information */);
1585 f_perform_CHECK_IMEI(g_pars.sub.imsi, '444456789012'H, 96 /* Invalid Mandatory Information */);
1586 f_perform_CHECK_IMEI(g_pars.sub.imsi, ''H, 96 /* Invalid Mandatory Information */);
1587}
1588testcase TC_gsup_check_imei_invalid_len() runs on test_CT {
1589 var HlrSubscriberList sl;
1590
1591 f_init(false);
1592 sl := f_gen_subs();
1593 f_start_handler_per_sub(refers(f_TC_gsup_check_imei_invalid_len), sl);
1594
1595 setverdict(pass);
1596}
1597
1598/* Test Check IMEI with unknown IMSI */
1599private function f_TC_gsup_check_imei_unknown_imsi() runs on HLR_ConnHdlr {
1600 f_vty_config(VTY, "hlr", "no store-imei");
1601 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1602
1603 /* Check again with store-imei set (different code path) */
1604 f_vty_config(VTY, "hlr", "store-imei");
1605 f_perform_CHECK_IMEI(g_pars.sub.imsi, '22245678901234'H, 96 /* Invalid Mandatory Information */);
1606
1607 setverdict(pass);
1608}
1609testcase TC_gsup_check_imei_unknown_imsi() runs on test_CT {
1610 var hexstring imsi := f_rnd_imsi('26242'H);
1611 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1612 var HLR_ConnHdlr vc_conn;
1613
1614 f_init(false);
1615 vc_conn := f_start_handler(refers(f_TC_gsup_check_imei_unknown_imsi), pars);
1616 vc_conn.done;
1617}
1618
Oliver Smith1b257802019-06-11 09:43:42 +02001619/* Test create-subscriber-on-demand during Check IMEI (OsmoMSC would be set to "check-imei-rqd early") */
1620private function f_TC_subscr_create_on_demand_check_imei_early() runs on HLR_ConnHdlr {
Alexander Couzens25d28492023-04-26 19:30:04 +02001621 var GSUP_PDUs res; /* save various return values to prevent ttcn3 compiler warnings */
Oliver Smith1b257802019-06-11 09:43:42 +02001622 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1623
1624 /* Random MSISDN and CS+PS NAM (LU must pass) */
1625 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1626 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1627 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1628 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1629 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1630 res := f_perform_UL(g_pars.sub.imsi, ?);
1631 f_vty_subscr_delete(VTY, g_pars.sub);
1632
1633 /* Random MSISDN and PS NAM (LU must pass) */
1634 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1635 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1636 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1637 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1638 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1639 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1640 res := f_perform_UL(g_pars.sub.imsi, ?);
1641 f_vty_subscr_delete(VTY, g_pars.sub);
1642
1643 /* Random MSISDN and CS NAM (LU must fail) */
1644 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1645 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1646 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1647 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1648 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1649 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1650 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1651 f_vty_subscr_delete(VTY, g_pars.sub);
1652
1653 /* Random MSISDN and no NAM (LU must fail) */
1654 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1655 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1656 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1657 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*");
1658 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1659 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1660 f_vty_subscr_delete(VTY, g_pars.sub);
1661
1662 /* No MSISDN and no NAM (LU must fail) */
1663 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1664 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1665 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1666 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1667 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1668 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1669 f_vty_subscr_delete(VTY, g_pars.sub);
1670
1671 /* No MSISDN and CS+PS NAM (LU must pass) */
1672 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1673 f_perform_CHECK_IMEI(g_pars.sub.imsi, '12345678901234'H, result := OSMO_GSUP_IMEI_RESULT_ACK);
1674 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1675 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1676 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1677 res := f_perform_UL(g_pars.sub.imsi, omit);
1678 f_vty_subscr_delete(VTY, g_pars.sub);
1679
1680 setverdict(pass);
1681}
1682testcase TC_subscr_create_on_demand_check_imei_early() runs on test_CT {
1683 var hexstring imsi := f_rnd_imsi('26242'H);
1684 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1685 var HLR_ConnHdlr vc_conn;
1686
1687 f_init(false);
1688 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_check_imei_early), pars);
1689 vc_conn.done;
1690}
1691
1692/* Test create-subscriber-on-demand during LU (Location Update) */
1693private function f_TC_subscr_create_on_demand_ul() runs on HLR_ConnHdlr {
Alexander Couzens25d28492023-04-26 19:30:04 +02001694 var GSUP_PDUs res;
Oliver Smith1b257802019-06-11 09:43:42 +02001695 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1696
1697 /* Random MSISDN and CS+PS NAM (LU must pass) */
1698 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
1699 res := f_perform_UL(g_pars.sub.imsi, ?);
1700 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1701 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1702 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1703 f_vty_subscr_delete(VTY, g_pars.sub);
1704
1705 /* Random MSISDN and PS NAM (LU must pass) */
1706 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 ps");
1707 res := f_perform_UL(g_pars.sub.imsi, ?);
1708 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1709 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1710 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*");
1711 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*PS disabled*");
1712 f_vty_subscr_delete(VTY, g_pars.sub);
1713
1714 /* Random MSISDN and CS NAM (LU must fail) */
1715 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs");
1716 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1717 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1718 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1719 f_vty_subscr_show(VTY, g_pars.sub, pattern "*PS disabled*");
1720 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*CS disabled*");
1721 f_vty_subscr_delete(VTY, g_pars.sub);
1722
1723 /* Random MSISDN and no NAM (LU must fail) */
1724 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 none");
1725 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1726 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1727 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d\n*");
1728 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1729 f_vty_subscr_delete(VTY, g_pars.sub);
1730
1731 /* No MSISDN and no NAM (LU must fail) */
1732 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn none");
1733 res := f_perform_UL(g_pars.sub.imsi, ?, 7 /* GPRS services not allowed */);
1734 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1735 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1736 f_vty_subscr_show(VTY, g_pars.sub, pattern "*CS disabled*PS disabled*");
1737 f_vty_subscr_delete(VTY, g_pars.sub);
1738
1739 /* No MSISDN and CS+PS NAM (LU must pass) */
1740 f_vty_config(VTY, "hlr", "subscriber-create-on-demand no-msisdn cs+ps");
1741 res := f_perform_UL(g_pars.sub.imsi, omit);
1742 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1743 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: none*");
1744 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1745 f_vty_subscr_delete(VTY, g_pars.sub);
1746
1747 setverdict(pass);
1748}
1749testcase TC_subscr_create_on_demand_ul() runs on test_CT {
1750 var hexstring imsi := f_rnd_imsi('26242'H);
1751 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1752 var HLR_ConnHdlr vc_conn;
1753
1754 f_init(false);
1755 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_ul), pars);
1756 vc_conn.done;
1757}
1758
1759/* Test create-subscriber-on-demand during SAI (SendAuthInfo) */
1760private function f_TC_subscr_create_on_demand_sai() runs on HLR_ConnHdlr {
Alexander Couzens25d28492023-04-26 19:30:04 +02001761 var GSUP_PDUs res;
1762 var GSUP_PDU pdu;
Oliver Smith1b257802019-06-11 09:43:42 +02001763 var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
1764
1765 /* HLR creates the subscriber on demand. Then the IMSI is known, but there is no auth data, so the HLR returns
1766 * the "slightly inaccurate cause 'IMSI Unknown' via GSUP". The MS is able to do a LU afterwards. */
1767 f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
Alexander Couzens25d28492023-04-26 19:30:04 +02001768 pdu := f_perform_SAI(g_pars.sub.imsi, 2 /* IMSI Unknown */ );
Oliver Smith1b257802019-06-11 09:43:42 +02001769
1770 /* Verify that it was created before the LU */
1771 f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
1772 f_vty_subscr_show(VTY, g_pars.sub, pattern "*MSISDN: \d\d\d*"); /* last line, hence not matching "\d\d\d\n" */
1773 f_vty_subscr_show_nomatch(VTY, g_pars.sub, pattern "*[CP]S disabled*");
1774
1775 /* Location update */
1776 res := f_perform_UL(g_pars.sub.imsi, ?);
1777 f_vty_subscr_delete(VTY, g_pars.sub);
1778 setverdict(pass);
1779}
1780testcase TC_subscr_create_on_demand_sai() runs on test_CT {
1781 var hexstring imsi := f_rnd_imsi('26242'H);
1782 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1783 var HLR_ConnHdlr vc_conn;
1784
1785 f_init(false);
1786 vc_conn := f_start_handler(refers(f_TC_subscr_create_on_demand_sai), pars);
1787 vc_conn.done;
1788}
1789
Oliver Smithdeb80a62019-11-29 16:01:54 +01001790/* Send an mslookup mDNS request to the home HLR, asking about a service that is not "gsup.hlr". (Hence the "_other" in
1791 * the test name, service "gsup.hlr" has different code paths, see related tests). */
1792private function f_TC_MSLookup_mDNS_service_other_home() runs on HLR_ConnHdlr {
1793 timer T;
1794 var MSLookup_mDNS vl_rmsg;
1795 var integer id := f_rnd_int(65535); /* mDNS packet ID */
1796 var hexstring msisdn := '49161'H & f_rnd_hexstring(7, 9);
1797 var charstring domain := "sip.voice." & hex2str(msisdn) & ".msisdn.mdns.osmocom.org";
1798
1799 /* Create subscriber */
1800 g_pars.sub.msisdn := msisdn;
1801 f_vty_subscr_create(VTY, g_pars.sub);
1802
1803 /* Send mDNS query, expect timeout */
1804 mDNS.send(ts_MSLookup_mDNS_query(id, domain));
1805 T.start(1.0);
1806 alt {
1807 [] mDNS.receive(tr_MSLookup_mDNS_result_IPv4(id, domain, '42424242'O, 5060)) {
1808 setverdict(fail, "OsmoHLR answered to mDNS query before subscriber did LU");
1809 }
1810 [] mDNS.receive(MSLookup_mDNS:?) -> value vl_rmsg {
1811 repeat;
1812 }
1813 [] T.timeout {
1814 }
1815 }
1816
1817 /* Location update */
1818 f_perform_UL(g_pars.sub.imsi, msisdn, dom := OSMO_GSUP_CN_DOMAIN_CS);
1819
1820 /* Send mDNS query again, expect result */
1821 mDNS.send(ts_MSLookup_mDNS_query(id, domain));
1822 T.start(1.0);
1823 alt {
1824 [] mDNS.receive(tr_MSLookup_mDNS_result_IPv4(id, domain, '42424242'O, 5060)) {
1825 setverdict(pass);
1826 }
1827 [] mDNS.receive(MSLookup_mDNS:?) -> value vl_rmsg {
1828 repeat;
1829 }
1830 [] T.timeout {
1831 setverdict(fail, "OsmoHLR did not answer to mDNS query");
1832 }
1833 }
1834
1835 f_vty_subscr_delete(VTY, g_pars.sub);
1836}
1837testcase TC_MSLookup_mDNS_service_other_home() runs on test_CT {
1838 var hexstring imsi := f_rnd_imsi('26242'H);
1839 var HLR_ConnHdlr vc_conn;
1840 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1841
1842 f_init(false);
1843 f_vty_config(VTY, "mslookup", "mdns bind");
1844 f_vty_config2(VTY, {"mslookup", "server"}, "service sip.voice at 66.66.66.66 5060");
1845
1846 vc_conn := f_start_handler(refers(f_TC_MSLookup_mDNS_service_other_home), pars);
1847 vc_conn.done;
1848}
1849
Oliver Smithb51a53f2020-01-29 15:06:54 +01001850/* Let OsmoHLR act as proxy between MSC and another HLR during UL */
1851private function f_TC_MSLookup_GSUP_proxy() runs on HLR_ConnHdlr {
1852 f_perform_UL_proxy(g_pars.sub.imsi, g_pars.sub.msisdn, OSMO_GSUP_CN_DOMAIN_CS);
1853 setverdict(pass);
1854}
1855testcase TC_MSLookup_GSUP_proxy() runs on test_CT {
1856 var hexstring imsi := f_rnd_imsi('26242'H);
1857 var hexstring msisdn := '49161'H & f_rnd_hexstring(7, 9);
1858 var HLR_ConnHdlr vc_conn;
1859 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi, msisdn));
1860
1861 f_init(false, true);
1862 f_vty_config(VTY, "mslookup", "mdns bind");
1863 vc_conn := f_start_handler(refers(f_TC_MSLookup_GSUP_proxy), pars, true);
1864
1865 timer T := 3.0;
1866 T.start;
1867 alt {
1868 [] vc_conn.done {}
1869 [] T.timeout { setverdict(fail, "Timeout"); mtc.stop; };
1870 }
1871}
1872
Oliver Smith18b48082020-01-30 10:34:47 +01001873/* Request "gsup.hlr" service right after creating subscriber from the home HLR. "TC_MSLookup_mDNS_service_other_home"
1874 * is similar, but does not query the "gsup.hlr" service. The "gsup.hlr" service has a different code path in OsmoHLR:
1875 * - it exists without being explicitly configured and returns the IP and port of the HLR's own GSUP server
1876 * - the request is answered, even if the subscriber is not attached to the HLR (for Location Update via proxy) */
1877private function f_TC_MSLookup_mDNS_service_GSUP_HLR_home() runs on HLR_ConnHdlr {
1878 timer T;
1879 var MSLookup_mDNS vl_rmsg;
1880 var integer id := f_rnd_int(65535); /* mDNS packet ID */
1881 var charstring domain := "gsup.hlr." & hex2str(g_pars.sub.imsi) & ".imsi.mdns.osmocom.org";
1882
1883 /* Create subscriber */
1884 g_pars.sub.msisdn := '133713381339'H;
1885 f_vty_subscr_create(VTY, g_pars.sub);
1886
1887 /* Send mDNS query, expect result */
1888 mDNS.send(ts_MSLookup_mDNS_query(id, domain));
1889 T.start(1.0);
1890 alt {
1891 [] mDNS.receive(tr_MSLookup_mDNS_result_IPv4(id, domain, f_enc_IPv4(mp_hlr_ip), mp_hlr_gsup_port)) {
1892 setverdict(pass);
1893 }
1894 [] mDNS.receive(MSLookup_mDNS:?) -> value vl_rmsg {
1895 repeat;
1896 }
1897 [] T.timeout {
1898 setverdict(fail, "OsmoHLR did not answer to mDNS query");
1899 }
1900 }
1901
1902 f_vty_subscr_delete(VTY, g_pars.sub);
1903}
1904testcase TC_MSLookup_mDNS_service_GSUP_HLR_home() runs on test_CT {
1905 var hexstring imsi := f_rnd_imsi('26242'H);
1906 var HLR_ConnHdlr vc_conn;
1907 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
1908
1909 f_init(false);
1910 f_vty_config(VTY, "mslookup", "mdns bind");
1911
1912 vc_conn := f_start_handler(refers(f_TC_MSLookup_mDNS_service_GSUP_HLR_home), pars);
1913 vc_conn.done;
1914}
1915
Oliver Smithda83c832020-01-30 15:10:20 +01001916/* Ask proxy HLR about gsup.hlr service, and expect no answer. */
1917private function f_TC_MSLookup_mDNS_service_GSUP_HLR_proxy() runs on HLR_ConnHdlr {
1918 timer T;
1919 var integer id := f_rnd_int(65535); /* mDNS packet ID */
1920 var charstring domain := "gsup.hlr." & hex2str(g_pars.sub.imsi) & ".imsi.mdns.osmocom.org";
1921
1922 f_perform_UL_proxy(g_pars.sub.imsi, g_pars.sub.msisdn, OSMO_GSUP_CN_DOMAIN_CS);
1923
1924 /* Send mDNS query, expect timeout */
1925 mDNS.send(ts_MSLookup_mDNS_query(id, domain));
1926 T.start(1.0);
1927 alt {
1928 [] mDNS.receive(tr_MSLookup_mDNS_result_IPv4(id, domain, f_enc_IPv4(mp_hlr_ip), mp_hlr_gsup_port)) {
1929 setverdict(fail, "mslookup result received from proxy HLR for gsup.hlr service");
1930 }
1931 [] mDNS.receive(MSLookup_mDNS:?) {
1932 repeat;
1933 }
1934 [] T.timeout {
1935 setverdict(pass);
1936 }
1937 }
1938}
1939testcase TC_MSLookup_mDNS_service_GSUP_HLR_proxy() runs on test_CT {
1940 var hexstring imsi := f_rnd_imsi('26242'H);
1941 var hexstring msisdn := '49161'H & f_rnd_hexstring(7, 9);
1942 var HLR_ConnHdlr vc_conn;
1943 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi, msisdn));
1944
1945 f_init(false, true);
1946 f_vty_config(VTY, "mslookup", "mdns bind");
1947 vc_conn := f_start_handler(refers(f_TC_MSLookup_mDNS_service_GSUP_HLR_proxy), pars, true);
1948
1949 timer T := 3.0;
1950 T.start;
1951 alt {
1952 [] vc_conn.done {}
1953 [] T.timeout { setverdict(fail, "Timeout"); mtc.stop; };
1954 }
1955}
1956
Oliver Smith421ea892020-01-30 15:53:50 +01001957/* Ask proxy HLR about configured sip.voice service, and expect result. */
1958private function f_TC_MSLookup_mDNS_service_other_proxy() runs on HLR_ConnHdlr {
1959 timer T;
1960 var integer id := f_rnd_int(65535); /* mDNS packet ID */
1961 var charstring domain := "sip.voice." & hex2str(g_pars.sub.msisdn) & ".msisdn.mdns.osmocom.org";
1962
1963 f_perform_UL_proxy(g_pars.sub.imsi, g_pars.sub.msisdn, OSMO_GSUP_CN_DOMAIN_CS);
1964
1965 /* Send mDNS query, expect result */
1966 mDNS.send(ts_MSLookup_mDNS_query(id, domain));
1967 T.start(1.0);
1968 alt {
1969 [] mDNS.receive(tr_MSLookup_mDNS_result_IPv4(id, domain, f_enc_IPv4("66.66.66.66"), 5060)) {
1970 setverdict(pass);
1971 }
1972 [] mDNS.receive(MSLookup_mDNS:?) {
1973 repeat;
1974 }
1975 [] T.timeout {
1976 setverdict(fail, "Timeout");
1977 }
1978 }
1979}
1980testcase TC_MSLookup_mDNS_service_other_proxy() runs on test_CT {
1981 var hexstring imsi := f_rnd_imsi('26242'H);
1982 var hexstring msisdn := '49161'H & f_rnd_hexstring(7, 9);
1983 var HLR_ConnHdlr vc_conn;
1984 var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi, msisdn));
1985
1986 f_init(false, true);
1987 f_vty_config(VTY, "mslookup", "mdns bind");
1988 f_vty_config2(VTY, {"mslookup", "server"}, "service sip.voice at 66.66.66.66 5060");
1989 vc_conn := f_start_handler(refers(f_TC_MSLookup_mDNS_service_other_proxy), pars, true);
1990
1991 timer T := 3.0;
1992 T.start;
1993 alt {
1994 [] vc_conn.done {}
1995 [] T.timeout { setverdict(fail, "Timeout"); mtc.stop; };
1996 }
1997}
1998
Alexander Couzens4cbd2072023-09-01 17:25:18 +02001999
2000/* strchr similar to C's/posix strchr but returns the position of the first matching.
2001 * if the char c isn't found it returns -1.
2002 */
2003function strchr(in charstring s, in charstring c) return integer {
2004 for (var integer i := 0; i < lengthof(s); i := i+1) {
2005 if (s[i] == c) {
2006 return i;
2007 }
2008 }
2009 return -1;
2010}
2011
2012/* str2apn returns octetstring
2013 * internet -> '08'O & char2oct("internet")
2014 * internet.foo -> '08'O & char2oct("internet") & '03'O & char2oct("foo")
2015 * internet.-> '08'O & char2oct("internet")
2016 */
2017function str2apn(in charstring apn) return octetstring {
2018 var octetstring result := ''O;
2019 var charstring remain := apn;
2020 var integer pos := strchr(remain, ".");
2021
2022 while (pos != -1) {
2023 /* ends on a dot. e.g. "internet.", we must ignore the ending dot and this is then the last element */
2024 if (pos == 0) {
2025 /* it's not allowed to start with a dot. */
2026 return ''O;
2027 }
2028
2029 if (pos + 1 == lengthof(remain)) {
2030 /* remove the dot */
2031 remain := substr(remain, 0, pos)
2032 break;
2033 }
2034
2035 result := result & int2oct(pos, 1) & char2oct(substr(remain, 0, pos));
2036 remain := substr(remain, pos + 1, lengthof(remain) - pos - 1);
2037 pos := strchr(remain, ".");
2038 }
2039 /* last element */
2040 var integer len := lengthof(remain);
2041 result := result & int2oct(len, 1) & char2oct(remain);
2042 return result;
2043}
2044
2045private function test_assert(boolean term) {
2046 if (term == false) {
2047 setverdict(fail, "Values mismatch");
2048 }
2049}
2050
2051private function test_str2apn() {
2052 test_assert(str2apn("internet") == '08'O & char2oct("internet"));
2053 test_assert(str2apn("internet.") == '08'O & char2oct("internet"));
2054 test_assert(str2apn("internet.foo") == '08'O & char2oct("internet") & '03'O & char2oct("foo"));
2055 test_assert(str2apn(".internet.foo") == ''O);
2056}
2057
Harald Weltec2c52552018-03-01 21:20:39 +01002058/* TODO:
2059 * UL with ISD error
2060 * UL with ISD timeout
Harald Weltec2c52552018-03-01 21:20:39 +01002061 * LOCATION CANCEL
2062 * AUTH FAIL REP
2063 * DELETE DATA after hlr_subscr_nam() change
2064 * correctness
2065 ** wrong message type
2066 ** wrong length of PDU
2067 ** too short message
2068 ** missing IMSI IE
2069
2070 */
2071
Harald Weltedf327232017-12-28 22:51:51 +01002072control {
2073 execute( TC_gsup_sai_err_invalid_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01002074 execute( TC_gsup_sai() );
Alexander Couzens92696442020-01-10 07:57:16 +01002075 execute( TC_gsup_sai_num_auth_vectors() );
Harald Welteaf7c3182019-08-22 12:40:22 +02002076 execute( TC_gsup_sai_eps() );
Harald Weltec2c52552018-03-01 21:20:39 +01002077 execute( TC_gsup_ul_unknown_imsi() );
Neels Hofmeyrb2168512019-11-11 03:40:26 +01002078 execute( TC_gsup_ul_unknown_imsi_via_proxy() );
Harald Welte3f662762018-03-02 10:48:20 +01002079 execute( TC_gsup_sai_err_unknown_imsi() );
Harald Weltec2c52552018-03-01 21:20:39 +01002080 execute( TC_gsup_ul() );
Neels Hofmeyrb2168512019-11-11 03:40:26 +01002081 execute( TC_gsup_ul_via_proxy() );
Alexander Couzens25d28492023-04-26 19:30:04 +02002082 execute( TC_gsup_ul_subscriber_data() );
Harald Weltec2c52552018-03-01 21:20:39 +01002083 execute( TC_vty() );
Harald Welte09b3c502018-03-01 22:42:22 +01002084 execute( TC_vty_msisdn_isd() );
Harald Welte958f8b42018-03-01 23:40:17 +01002085 execute( TC_gsup_purge_cs() );
2086 execute( TC_gsup_purge_ps() );
2087 execute( TC_gsup_purge_unknown() );
Harald Welte4ea1f8a2018-06-12 09:26:10 +02002088
2089 execute( TC_mo_ussd_unknown() );
2090 execute( TC_mo_ussd_euse_disc() );
2091 execute( TC_mo_ussd_iuse_imsi() );
Neels Hofmeyrb2168512019-11-11 03:40:26 +01002092 execute( TC_mo_ussd_iuse_imsi_via_proxy() );
Harald Welte4ea1f8a2018-06-12 09:26:10 +02002093 execute( TC_mo_ussd_iuse_msisdn() );
Neels Hofmeyrb2168512019-11-11 03:40:26 +01002094 execute( TC_mo_ussd_iuse_msisdn_via_proxy() );
Harald Welte4ea1f8a2018-06-12 09:26:10 +02002095 execute( TC_mo_ussd_euse() );
2096 execute( TC_mo_ussd_euse_continue() );
2097 execute( TC_mo_ussd_euse_defaultroute() );
Vadim Yanitskiyeffab7c2018-11-28 06:02:22 +07002098
2099 /* "Structured" Supplementary Services */
2100 execute( TC_mo_sss_reject() );
Oliver Smith936dbe62019-06-04 15:54:17 +02002101
2102 execute( TC_gsup_check_imei() );
Neels Hofmeyrb2168512019-11-11 03:40:26 +01002103 execute( TC_gsup_check_imei_via_proxy() );
Oliver Smith936dbe62019-06-04 15:54:17 +02002104 execute( TC_gsup_check_imei_invalid_len() );
2105 execute( TC_gsup_check_imei_unknown_imsi() );
Oliver Smith1b257802019-06-11 09:43:42 +02002106 execute( TC_subscr_create_on_demand_check_imei_early() );
2107 execute( TC_subscr_create_on_demand_ul() );
2108 execute( TC_subscr_create_on_demand_sai() );
Oliver Smithdeb80a62019-11-29 16:01:54 +01002109
Pau Espin Pedrol0055a292021-02-26 13:08:09 +01002110 execute( TC_MSLookup_mDNS_service_other_home() );
2111 execute( TC_MSLookup_GSUP_proxy() );
2112 execute( TC_MSLookup_mDNS_service_GSUP_HLR_home() );
2113 execute( TC_MSLookup_mDNS_service_GSUP_HLR_proxy() );
2114 execute( TC_MSLookup_mDNS_service_other_proxy() );
Harald Weltedf327232017-12-28 22:51:51 +01002115};
2116
2117};