blob: 3cf16573dcd1db8a1870256990eb1b36ee640ed6 [file] [log] [blame]
Harald Welte96a33b02018-02-04 10:36:22 +01001module SGSN_Tests {
2
3import from General_Types all;
4import from Osmocom_Types all;
5import from NS_Types all;
6import from NS_Emulation all;
7import from BSSGP_Types all;
8import from BSSGP_Emulation all;
Harald Welte5ac31492018-02-15 20:39:13 +01009import from Osmocom_Gb_Types all;
10
11import from MobileL3_CommonIE_Types all;
12import from MobileL3_GMM_SM_Types all;
13import from MobileL3_Types all;
14import from L3_Templates all;
15import from L3_Common all;
16
17import from GSUP_Emulation all;
18import from GSUP_Types all;
19import from IPA_Emulation all;
20
Harald Weltebd194722018-02-16 22:11:08 +010021import from TELNETasp_PortType all;
22import from Osmocom_VTY_Functions all;
23
Harald Welte5ac31492018-02-15 20:39:13 +010024modulepar {
25 /* IP/port on which we run our internal GSUP/HLR emulation */
26 charstring mp_hlr_ip := "127.0.0.1";
27 integer mp_hlr_port := 4222;
28};
29
30type record GbInstance {
31 NS_CT vc_NS,
32 BSSGP_CT vc_BSSGP,
33 BssgpConfig cfg
34};
Harald Welte96a33b02018-02-04 10:36:22 +010035
36type component test_CT {
Harald Welte5ac31492018-02-15 20:39:13 +010037 var GbInstance g_gb[3];
Harald Welte96a33b02018-02-04 10:36:22 +010038
Harald Welte5ac31492018-02-15 20:39:13 +010039 var GSUP_Emulation_CT vc_GSUP;
40 var IPA_Emulation_CT vc_GSUP_IPA;
41 /* only to get events from IPA underneath GSUP */
42 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte96a33b02018-02-04 10:36:22 +010043
Harald Weltebd194722018-02-16 22:11:08 +010044 port TELNETasp_PT SGSNVTY;
45
Harald Welte96a33b02018-02-04 10:36:22 +010046 var boolean g_initialized := false;
47};
48
Harald Welte5ac31492018-02-15 20:39:13 +010049type component BSSGP_ConnHdlr extends BSSGP_Client_CT, GSUP_ConnHdlr {
50 var BSSGP_ConnHdlrPars g_pars;
Harald Welte62e29582018-02-16 21:17:11 +010051 timer g_Tguard;
Harald Welte5ac31492018-02-15 20:39:13 +010052}
53
54type record SGSN_ConnHdlrNetworkPars {
55 boolean expect_ptmsi,
56 boolean expect_auth,
57 boolean expect_ciph
58};
59
60type record BSSGP_ConnHdlrPars {
61 /* IMEI of the simulated ME */
62 hexstring imei,
63 /* IMEI of the simulated MS */
64 hexstring imsi,
65 /* MSISDN of the simulated MS (probably unused) */
66 hexstring msisdn,
67 /* P-TMSI allocated to the simulated MS */
68 OCT4 p_tmsi optional,
Harald Welte04683d02018-02-16 22:43:45 +010069 OCT3 p_tmsi_sig optional,
Harald Welte5ac31492018-02-15 20:39:13 +010070 /* TLLI of the simulated MS */
71 OCT4 tlli,
Harald Weltef70997d2018-02-17 10:11:19 +010072 OCT4 tlli_old optional,
Harald Welte5ac31492018-02-15 20:39:13 +010073 RoutingAreaIdentificationV ra optional,
74 BssgpCellId bssgp_cell_id,
75 AuthVector vec optional,
Harald Welte62e29582018-02-16 21:17:11 +010076 SGSN_ConnHdlrNetworkPars net,
77 float t_guard
Harald Welte5ac31492018-02-15 20:39:13 +010078};
79
Harald Welte5ac31492018-02-15 20:39:13 +010080private function f_init_gb(inout GbInstance gb) runs on test_CT {
81 gb.vc_NS := NS_CT.create;
82 gb.vc_BSSGP := BSSGP_CT.create;
83 /* connect lower end of BSSGP emulation with NS upper port */
84 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
85 /* connect lower end of NS emulation to NS codec port (on top of IPL4) */
86 map(gb.vc_NS:NSCP, system:NS_CODEC_PORT);
87
88 gb.vc_NS.start(NSStart());
89 gb.vc_BSSGP.start(BssgpStart(gb.cfg));
90}
91
92private function f_init_gsup(charstring id) runs on test_CT {
93 id := id & "-GSUP";
94 var GsupOps ops := {
95 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
96 };
97
98 vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
99 vc_GSUP := GSUP_Emulation_CT.create(id);
100
101 map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
102 connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
103 /* we use this hack to get events like ASP_IPA_EVENT_UP */
104 connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
105
106 vc_GSUP.start(GSUP_Emulation.main(ops, id));
107 vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
108
109 /* wait for incoming connection to GSUP port before proceeding */
110 timer T := 10.0;
111 T.start;
112 alt {
113 [] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
114 [] T.timeout {
115 setverdict(fail, "No connection to GSUP Port");
116 self.stop;
117 }
118 }
119}
120
Harald Weltebd194722018-02-16 22:11:08 +0100121private function f_init_vty() runs on test_CT {
122 map(self:SGSNVTY, system:SGSNVTY);
123 f_vty_set_prompts(SGSNVTY);
124 f_vty_transceive(SGSNVTY, "enable");
125 f_vty_config(SGSNVTY, "sgsn", "auth-policy remote");
126}
127
128
Harald Welte96a33b02018-02-04 10:36:22 +0100129function f_init() runs on test_CT {
130 if (g_initialized == true) {
131 return;
132 }
133 g_initialized := true;
Harald Welte5ac31492018-02-15 20:39:13 +0100134 g_gb[0].cfg := {
135 nsei := 96,
136 bvci := 196,
137 cell_id := {
138 ra_id := {
139 lai := {
140 mcc_mnc := '26242F'H, lac := 13135},
141 rac := 0
142 },
143 cell_id := 20960
144 },
145 sgsn_role := false
146 };
Harald Welte96a33b02018-02-04 10:36:22 +0100147
Harald Welte5ac31492018-02-15 20:39:13 +0100148 f_init_gb(g_gb[0]);
149 f_init_gsup("SGSN_Test");
Harald Weltebd194722018-02-16 22:11:08 +0100150 f_init_vty();
Harald Welte5ac31492018-02-15 20:39:13 +0100151}
Harald Welte96a33b02018-02-04 10:36:22 +0100152
Harald Welte5ac31492018-02-15 20:39:13 +0100153type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
154
155/* helper function to create, connect and start a BSSGP_ConnHdlr component */
Harald Welte62e29582018-02-16 21:17:11 +0100156function f_start_handler(void_fn fn, charstring id, GbInstance gb, integer imsi_suffix,
157 float t_guard := 30.0)
Harald Welte5ac31492018-02-15 20:39:13 +0100158runs on test_CT return BSSGP_ConnHdlr {
159 var BSSGP_ConnHdlr vc_conn;
160 var SGSN_ConnHdlrNetworkPars net_pars := {
161 expect_ptmsi := true,
162 expect_auth := true,
163 expect_ciph := false
164 };
165 var BSSGP_ConnHdlrPars pars := {
166 imei := f_gen_imei(imsi_suffix),
167 imsi := f_gen_imsi(imsi_suffix),
168 msisdn := f_gen_msisdn(imsi_suffix),
169 p_tmsi := omit,
Harald Welte04683d02018-02-16 22:43:45 +0100170 p_tmsi_sig := omit,
Harald Welte14a0f942018-02-16 20:42:23 +0100171 tlli := f_gprs_tlli_random(),
Harald Weltef70997d2018-02-17 10:11:19 +0100172 tlli_old := omit,
Harald Welte5ac31492018-02-15 20:39:13 +0100173 ra := omit,
174 bssgp_cell_id := gb.cfg.cell_id,
175 vec := omit,
Harald Welte62e29582018-02-16 21:17:11 +0100176 net := net_pars,
177 t_guard := t_guard
Harald Welte5ac31492018-02-15 20:39:13 +0100178 };
179
180 vc_conn := BSSGP_ConnHdlr.create(id);
181 connect(vc_conn:BSSGP, gb.vc_BSSGP:BSSGP_SP);
182 connect(vc_conn:BSSGP_PROC, gb.vc_BSSGP:BSSGP_PROC);
183
184 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
185 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
186
187 vc_conn.start(f_handler_init(fn, id, pars));
188 return vc_conn;
189}
190
Harald Welte62e29582018-02-16 21:17:11 +0100191private altstep as_Tguard() runs on BSSGP_ConnHdlr {
192 [] g_Tguard.timeout {
193 setverdict(fail, "Tguard timeout");
194 self.stop;
195 }
196}
197
Harald Welte5ac31492018-02-15 20:39:13 +0100198/* first function called in every ConnHdlr */
199private function f_handler_init(void_fn fn, charstring id, BSSGP_ConnHdlrPars pars)
200runs on BSSGP_ConnHdlr {
201 /* do some common stuff like setting up g_pars */
202 g_pars := pars;
203
204 /* register with BSSGP core */
205 f_bssgp_client_register(g_pars.imsi, g_pars.tlli, g_pars.bssgp_cell_id);
206 /* tell GSUP dispatcher to send this IMSI to us */
207 f_create_gsup_expect(hex2str(g_pars.imsi));
208
Harald Welte62e29582018-02-16 21:17:11 +0100209 g_Tguard.start(pars.t_guard);
210 activate(as_Tguard());
211
Harald Welte5ac31492018-02-15 20:39:13 +0100212 /* call the user-supplied test case function */
213 fn.apply(id);
214 f_bssgp_client_unregister(g_pars.imsi);
Harald Welte96a33b02018-02-04 10:36:22 +0100215}
216
217/* TODO:
Harald Welte96a33b02018-02-04 10:36:22 +0100218 * Detach without Attach
219 * SM procedures without attach / RAU
220 * ATTACH / RAU
221 ** with / without authentication
222 ** with / without P-TMSI allocation
Harald Welte96a33b02018-02-04 10:36:22 +0100223 ** reject from HLR on SAI
224 ** reject from HLR on UL
225 * re-transmissions of LLC frames
226 * PDP Context activation
227 ** with different GGSN config in SGSN VTY
228 ** with different PDP context type (v4/v6/v46)
229 ** timeout from GGSN
230 ** reject from GGSN
231 */
232
233testcase TC_wait_ns_up() runs on test_CT {
234 f_init();
235 f_sleep(20.0);
236}
237
Harald Welte5ac31492018-02-15 20:39:13 +0100238altstep as_mm_identity() runs on BSSGP_ConnHdlr {
239 var MobileIdentityLV mi;
240 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ID_REQ('001'B))) {
241 mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
242 BSSGP.send(ts_GMM_ID_RESP(mi));
243 repeat;
244 }
245 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ID_REQ('010'B))) {
246 mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
247 BSSGP.send(ts_GMM_ID_RESP(mi));
248 repeat;
249 }
250}
Harald Welte96a33b02018-02-04 10:36:22 +0100251
Harald Welte311ec272018-02-17 09:40:03 +0100252/* perform GMM authentication (if expected) */
Harald Welte5ac31492018-02-15 20:39:13 +0100253function f_gmm_auth () runs on BSSGP_ConnHdlr {
254 var BssgpDecoded bd;
255 var PDU_L3_MS_SGSN l3_mo;
256 var PDU_L3_SGSN_MS l3_mt;
257 var default di := activate(as_mm_identity());
258 if (g_pars.net.expect_auth) {
259 g_pars.vec := f_gen_auth_vec_2g();
260 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(g_pars.vec.rand,
261 g_pars.vec.sres,
262 g_pars.vec.kc));
263 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
264 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
265 BSSGP.receive(tr_BD_L3_MT(tr_GMM_AUTH_REQ(g_pars.vec.rand))) -> value bd;
266 l3_mt := bd.l3_mt;
267 var BIT4 ac_ref := l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.acReferenceNumber.valueField;
268 l3_mo := valueof(ts_GMM_AUTH_RESP_2G(ac_ref, g_pars.vec.sres));
269 if (ispresent(l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.imeisvRequest) and
270 l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.imeisvRequest.valueField == '001'B) {
271 l3_mo.msgs.gprs_mm.authenticationAndCipheringResponse.imeisv :=
272 valueof(ts_MI_IMEISV_TLV(g_pars.imei & '0'H));
273 }
274 BSSGP.send(l3_mo);
Harald Welte76dee092018-02-16 22:12:59 +0100275 } else {
276 /* wait for identity procedure */
277 f_sleep(1.0);
Harald Welte5ac31492018-02-15 20:39:13 +0100278 }
Harald Welte76dee092018-02-16 22:12:59 +0100279
Harald Welte5ac31492018-02-15 20:39:13 +0100280 deactivate(di);
281}
282
Harald Weltef70997d2018-02-17 10:11:19 +0100283function f_upd_ptmsi_and_tlli(OCT4 p_tmsi) runs on BSSGP_ConnHdlr {
284 g_pars.p_tmsi := p_tmsi;
285 /* update TLLI */
286 g_pars.tlli_old := g_pars.tlli;
287 g_pars.tlli := g_pars.p_tmsi or4b 'c0000000'O;
288 f_bssgp_client_llgmm_assign(g_pars.tlli_old, g_pars.tlli);
289}
290
Harald Welte04683d02018-02-16 22:43:45 +0100291function f_process_attach_accept(PDU_GMM_AttachAccept aa) runs on BSSGP_ConnHdlr {
292 /* mandatory IE */
293 g_pars.ra := aa.routingAreaIdentification;
294 if (ispresent(aa.allocatedPTMSI)) {
295 if (not g_pars.net.expect_ptmsi) {
296 setverdict(fail, "unexpected P-TMSI allocation");
297 self.stop;
298 }
Harald Weltef70997d2018-02-17 10:11:19 +0100299 f_upd_ptmsi_and_tlli(aa.allocatedPTMSI.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets);
Harald Welte04683d02018-02-16 22:43:45 +0100300 }
301 if (ispresent(aa.msIdentity)) {
302 setverdict(fail, "unexpected TMSI allocation in non-combined attach");
303 self.stop;
304 }
305 /* P-TMSI.sig */
306 if (ispresent(aa.ptmsiSignature)) {
307 g_pars.p_tmsi_sig := aa.ptmsiSignature.valueField;
308 }
309 /* updateTimer */
310 // aa.readyTimer
311 /* T3302, T3319, T3323, T3312_ext, T3324 */
312}
313
Harald Welte91636de2018-02-17 10:16:14 +0100314function f_process_rau_accept(PDU_GMM_RoutingAreaUpdateAccept ra) runs on BSSGP_ConnHdlr {
315 /* mandatory IE */
316 g_pars.ra := ra.routingAreaId;
317 if (ispresent(ra.allocatedPTMSI)) {
318 if (not g_pars.net.expect_ptmsi) {
319 setverdict(fail, "unexpected P-TMSI allocation");
320 self.stop;
321 }
322 f_upd_ptmsi_and_tlli(ra.allocatedPTMSI.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets);
323 }
324 if (ispresent(ra.msIdentity)) {
325 setverdict(fail, "unexpected TMSI allocation in non-combined attach");
326 self.stop;
327 }
328 /* P-TMSI.sig */
329 if (ispresent(ra.ptmsiSignature)) {
330 g_pars.p_tmsi_sig := ra.ptmsiSignature.valueField;
331 }
332 /* updateTimer */
333 // aa.readyTimer
334 /* T3302, T3319, T3323, T3312_ext, T3324 */
335}
336
337
Harald Welte5a4fa042018-02-16 20:59:21 +0100338function f_random_RAI(HEX0_3n mcc := '262'H, HEX0_3n mnc := '42'H) return RoutingAreaIdentificationV {
339 return f_RAI(mcc, mnc, f_rnd_octstring(2), f_rnd_octstring(1));
340}
341
Harald Welte23178c52018-02-17 09:36:33 +0100342/* return a MobileIdentityLV: P-TMSI if we have one, IMSI otherwise */
343private function f_mi_get_lv() runs on BSSGP_ConnHdlr return MobileIdentityLV {
344 if (ispresent(g_pars.p_tmsi)) {
345 return valueof(ts_MI_TMSI_LV(g_pars.p_tmsi));
346 } else {
347 return valueof(ts_MI_IMSI_LV(g_pars.imsi));
348 }
349}
350
Harald Welte311ec272018-02-17 09:40:03 +0100351private function f_gmm_gsup_lu_isd() runs on BSSGP_ConnHdlr {
352 /* Expect MSC to perform LU with HLR */
353 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
354 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
355 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
356 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
357}
358
Harald Welte5ac31492018-02-15 20:39:13 +0100359private function f_TC_attach(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100360 var BssgpDecoded bd;
Harald Welte5a4fa042018-02-16 20:59:21 +0100361 var RoutingAreaIdentificationV old_ra := f_random_RAI();
Harald Welte5ac31492018-02-15 20:39:13 +0100362
Harald Welte23178c52018-02-17 09:36:33 +0100363 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5ac31492018-02-15 20:39:13 +0100364 f_gmm_auth();
365 /* Expect MSC to perform LU with HLR */
Harald Welte311ec272018-02-17 09:40:03 +0100366 f_gmm_gsup_lu_isd();
Harald Welte5ac31492018-02-15 20:39:13 +0100367
Harald Welte04683d02018-02-16 22:43:45 +0100368 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
369 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
370 }
371 /* FIXME: Extract P-TMSI, if any. Only send Complete if necessary */
Harald Welte5ac31492018-02-15 20:39:13 +0100372 BSSGP.send(ts_GMM_ATTACH_COMPL);
Harald Welte5a4fa042018-02-16 20:59:21 +0100373 setverdict(pass);
Harald Welte5ac31492018-02-15 20:39:13 +0100374}
375
376testcase TC_attach() runs on test_CT {
377 var BSSGP_ConnHdlr vc_conn;
378 f_init();
379 f_sleep(1.0);
380 vc_conn := f_start_handler(refers(f_TC_attach), testcasename(), g_gb[0], 1);
381 vc_conn.done;
382}
383
Harald Welte5b7c8122018-02-16 21:48:17 +0100384/* MS never responds to ID REQ, expect ATTACH REJECT */
385private function f_TC_attach_auth_id_timeout(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte5b7c8122018-02-16 21:48:17 +0100386 var RoutingAreaIdentificationV old_ra := f_random_RAI();
387
Harald Welte23178c52018-02-17 09:36:33 +0100388 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5b7c8122018-02-16 21:48:17 +0100389 alt {
Harald Welte1967d472018-02-16 21:54:21 +0100390 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ID_REQ(?))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100391 /* don't send ID Response */
392 repeat;
393 }
Harald Welte1967d472018-02-16 21:54:21 +0100394 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT('09'O))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100395 setverdict(pass);
396 }
Harald Welte1967d472018-02-16 21:54:21 +0100397 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100398 setverdict(fail, "Wrong Attach Reject Cause");
399 }
400 }
401}
402testcase TC_attach_auth_id_timeout() runs on test_CT {
403 var BSSGP_ConnHdlr vc_conn;
404 f_init();
405 vc_conn := f_start_handler(refers(f_TC_attach_auth_id_timeout), testcasename(), g_gb[0], 2, 40.0);
406 vc_conn.done;
407}
408
409/* HLR never responds to SAI REQ, expect ATTACH REJECT */
410private function f_TC_attach_auth_sai_timeout(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte5b7c8122018-02-16 21:48:17 +0100411 var RoutingAreaIdentificationV old_ra := f_random_RAI();
412
Harald Welte23178c52018-02-17 09:36:33 +0100413 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5b7c8122018-02-16 21:48:17 +0100414 alt {
415 [] as_mm_identity();
416 [] GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi)); { }
417 }
418 /* don't send SAI-response from HLR */
Harald Welte1967d472018-02-16 21:54:21 +0100419 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?)));
Harald Welte5b7c8122018-02-16 21:48:17 +0100420 setverdict(pass);
421}
422testcase TC_attach_auth_sai_timeout() runs on test_CT {
423 var BSSGP_ConnHdlr vc_conn;
424 f_init();
425 vc_conn := f_start_handler(refers(f_TC_attach_auth_sai_timeout), testcasename(), g_gb[0], 3);
426 vc_conn.done;
427}
428
Harald Weltefe253882018-02-17 09:25:00 +0100429/* HLR rejects SAI, expect ATTACH REJECT */
430private function f_TC_attach_auth_sai_reject(charstring id) runs on BSSGP_ConnHdlr {
Harald Weltefe253882018-02-17 09:25:00 +0100431 var RoutingAreaIdentificationV old_ra := f_random_RAI();
432
Harald Welte23178c52018-02-17 09:36:33 +0100433 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Weltefe253882018-02-17 09:25:00 +0100434 alt {
435 [] as_mm_identity();
436 [] GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi)); {
437 GSUP.send(ts_GSUP_SAI_ERR(g_pars.imsi, 23));
438 }
439 }
440 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?)));
441 setverdict(pass);
442}
443testcase TC_attach_auth_sai_reject() runs on test_CT {
444 var BSSGP_ConnHdlr vc_conn;
445 f_init();
Harald Welteb7c14e92018-02-17 09:29:16 +0100446 vc_conn := f_start_handler(refers(f_TC_attach_auth_sai_reject), testcasename(), g_gb[0], 4);
Harald Weltefe253882018-02-17 09:25:00 +0100447 vc_conn.done;
448}
449
Harald Welte5b7c8122018-02-16 21:48:17 +0100450/* HLR never responds to UL REQ, expect ATTACH REJECT */
451private function f_TC_attach_gsup_lu_timeout(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100452 var BssgpDecoded bd;
Harald Welte5b7c8122018-02-16 21:48:17 +0100453 var RoutingAreaIdentificationV old_ra := f_random_RAI();
454
Harald Welte23178c52018-02-17 09:36:33 +0100455 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5b7c8122018-02-16 21:48:17 +0100456 f_gmm_auth();
457 /* Expect MSC to perform LU with HLR */
458 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
459 /* Never follow-up with ISD_REQ or UL_RES */
460 alt {
Harald Welte1967d472018-02-16 21:54:21 +0100461 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100462 setverdict(pass);
463 }
Harald Welte04683d02018-02-16 22:43:45 +0100464 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
465 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
Harald Welte5b7c8122018-02-16 21:48:17 +0100466 setverdict(fail);
467 }
468 }
469}
470testcase TC_attach_gsup_lu_timeout() runs on test_CT {
471 var BSSGP_ConnHdlr vc_conn;
472 f_init();
473 f_sleep(1.0);
Harald Welteb7c14e92018-02-17 09:29:16 +0100474 vc_conn := f_start_handler(refers(f_TC_attach_gsup_lu_timeout), testcasename(), g_gb[0], 5);
Harald Welte5b7c8122018-02-16 21:48:17 +0100475 vc_conn.done;
476}
477
Harald Welteb7c14e92018-02-17 09:29:16 +0100478/* HLR rejects UL REQ, expect ATTACH REJECT */
479private function f_TC_attach_gsup_lu_reject(charstring id) runs on BSSGP_ConnHdlr {
480 var BssgpDecoded bd;
Harald Welteb7c14e92018-02-17 09:29:16 +0100481 var RoutingAreaIdentificationV old_ra := f_random_RAI();
482
Harald Welte23178c52018-02-17 09:36:33 +0100483 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welteb7c14e92018-02-17 09:29:16 +0100484 f_gmm_auth();
485 /* Expect MSC to perform LU with HLR */
486 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
487 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 0));
488 }
489 alt {
490 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
491 setverdict(pass);
492 }
493 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
494 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
495 setverdict(fail);
496 }
497 }
498}
499testcase TC_attach_gsup_lu_reject() runs on test_CT {
500 var BSSGP_ConnHdlr vc_conn;
501 f_init();
502 f_sleep(1.0);
503 vc_conn := f_start_handler(refers(f_TC_attach_gsup_lu_reject), testcasename(), g_gb[0], 6);
504 vc_conn.done;
505}
506
507
Harald Welte3823e2e2018-02-16 21:53:48 +0100508/* Attempt of combined GPRS + IMSI attach: network should ACK only GPRS attach */
509private function f_TC_attach_combined(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100510 var BssgpDecoded bd;
Harald Welte3823e2e2018-02-16 21:53:48 +0100511 var RoutingAreaIdentificationV old_ra := f_random_RAI();
512
Harald Welte23178c52018-02-17 09:36:33 +0100513 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, true, false, omit, omit));
Harald Welte3823e2e2018-02-16 21:53:48 +0100514 f_gmm_auth();
515 /* Expect MSC to perform LU with HLR */
Harald Welte311ec272018-02-17 09:40:03 +0100516 f_gmm_gsup_lu_isd();
Harald Welte3823e2e2018-02-16 21:53:48 +0100517
Harald Welte04683d02018-02-16 22:43:45 +0100518 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
519 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
520 }
Harald Welte3823e2e2018-02-16 21:53:48 +0100521 BSSGP.send(ts_GMM_ATTACH_COMPL);
522 setverdict(pass);
523}
Harald Welte3823e2e2018-02-16 21:53:48 +0100524testcase TC_attach_combined() runs on test_CT {
525 var BSSGP_ConnHdlr vc_conn;
526 f_init();
527 f_sleep(1.0);
Harald Welteb7c14e92018-02-17 09:29:16 +0100528 vc_conn := f_start_handler(refers(f_TC_attach_combined), testcasename(), g_gb[0], 7);
Harald Welte3823e2e2018-02-16 21:53:48 +0100529 vc_conn.done;
530}
531
Harald Welte76dee092018-02-16 22:12:59 +0100532/* Attempt of GPRS ATTACH in 'accept all' mode */
533private function f_TC_attach_accept_all(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100534 var BssgpDecoded bd;
Harald Welte76dee092018-02-16 22:12:59 +0100535 var RoutingAreaIdentificationV old_ra := f_random_RAI();
536
537 g_pars.net.expect_auth := false;
538
Harald Welte23178c52018-02-17 09:36:33 +0100539 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte76dee092018-02-16 22:12:59 +0100540 f_gmm_auth();
Harald Welte04683d02018-02-16 22:43:45 +0100541 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
542 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
543 }
Harald Welte76dee092018-02-16 22:12:59 +0100544 BSSGP.send(ts_GMM_ATTACH_COMPL);
545 setverdict(pass);
546}
547testcase TC_attach_accept_all() runs on test_CT {
548 var BSSGP_ConnHdlr vc_conn;
549 f_init();
550 f_sleep(1.0);
551 f_vty_config(SGSNVTY, "sgsn", "auth-policy accept-all");
Harald Welteb7c14e92018-02-17 09:29:16 +0100552 vc_conn := f_start_handler(refers(f_TC_attach_accept_all), testcasename(), g_gb[0], 8);
Harald Welte76dee092018-02-16 22:12:59 +0100553 vc_conn.done;
554}
Harald Welte5b7c8122018-02-16 21:48:17 +0100555
Harald Welteb2124b22018-02-16 22:26:56 +0100556/* Attempt of GPRS ATTACH in 'accept all' mode */
557private function f_TC_attach_closed_foreign(charstring id) runs on BSSGP_ConnHdlr {
Harald Welteb2124b22018-02-16 22:26:56 +0100558 var RoutingAreaIdentificationV old_ra := f_random_RAI();
559
560 /* Simulate a foreign IMSI */
561 g_pars.imsi := '001010123456789'H;
562 f_bssgp_client_register(g_pars.imsi, g_pars.tlli, g_pars.bssgp_cell_id);
563
564 g_pars.net.expect_auth := false;
565
Harald Welte23178c52018-02-17 09:36:33 +0100566 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welteb2124b22018-02-16 22:26:56 +0100567 alt {
568 [] as_mm_identity();
569 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT('07'O))) {
570 setverdict(pass);
571 }
572 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
573 setverdict(pass);
574 }
575 }
576}
577testcase TC_attach_closed() runs on test_CT {
578 var BSSGP_ConnHdlr vc_conn;
579 f_init();
580 f_sleep(1.0);
581 f_vty_config(SGSNVTY, "sgsn", "auth-policy closed");
582 /* test with foreign IMSI: Must Reject */
Harald Welteb7c14e92018-02-17 09:29:16 +0100583 vc_conn := f_start_handler(refers(f_TC_attach_closed_foreign), testcasename(), g_gb[0], 9);
Harald Welteb2124b22018-02-16 22:26:56 +0100584 vc_conn.done;
585 /* test with home IMSI: Must Accept */
Harald Welteb7c14e92018-02-17 09:29:16 +0100586 vc_conn := f_start_handler(refers(f_TC_attach_accept_all), testcasename(), g_gb[0], 10);
Harald Welteb2124b22018-02-16 22:26:56 +0100587 vc_conn.done;
588}
589
Harald Welte04683d02018-02-16 22:43:45 +0100590/* Routing Area Update from Unknown TLLI -> REJECT */
591private function f_TC_rau_unknown(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100592 var RoutingAreaIdentificationV old_ra := f_random_RAI();
593
Harald Welte23178c52018-02-17 09:36:33 +0100594 BSSGP.send(ts_GMM_RAU_REQ(f_mi_get_lv(), GPRS_UPD_T_RA, old_ra, false, omit, omit));
Harald Welte04683d02018-02-16 22:43:45 +0100595 alt {
596 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_RAU_REJECT('0a'O))) {
597 setverdict(pass);
598 }
599 /* FIXME: Expect XID RESET? */
600 [] BSSGP.receive { repeat; }
601 }
602}
603testcase TC_rau_unknown() runs on test_CT {
604 var BSSGP_ConnHdlr vc_conn;
605 f_init();
606 f_sleep(1.0);
Harald Welteb7c14e92018-02-17 09:29:16 +0100607 vc_conn := f_start_handler(refers(f_TC_rau_unknown), testcasename(), g_gb[0], 11);
Harald Welte04683d02018-02-16 22:43:45 +0100608 vc_conn.done;
609}
610
Harald Welte91636de2018-02-17 10:16:14 +0100611private function f_TC_attach_rau(charstring id) runs on BSSGP_ConnHdlr {
612 var BssgpDecoded bd;
613
614 /* first perform regular attach */
615 f_TC_attach(id);
616
617 /* then send RAU */
618 BSSGP.send(ts_GMM_RAU_REQ(f_mi_get_lv(), GPRS_UPD_T_RA, g_pars.ra, false, omit, omit));
619 alt {
620 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_RAU_ACCEPT)) -> value bd {
621 f_process_rau_accept(bd.l3_mt.msgs.gprs_mm.routingAreaUpdateAccept);
622 setverdict(pass);
623 }
624 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_RAU_REJECT)) {
625 setverdict(fail, "Unexpected RAU Reject");
626 }
627 [] BSSGP.receive { repeat; }
628 }
629}
630testcase TC_attach_rau() runs on test_CT {
631 var BSSGP_ConnHdlr vc_conn;
632 f_init();
633 f_sleep(1.0);
634 vc_conn := f_start_handler(refers(f_TC_attach_rau), testcasename(), g_gb[0], 12);
635 vc_conn.done;
636}
Harald Welte04683d02018-02-16 22:43:45 +0100637
Harald Welte6abb9fe2018-02-17 15:24:48 +0100638/* general GPRS DETACH helper */
639function f_detach_mo(BIT3 detach_type, boolean power_off, boolean expect_purge) runs on BSSGP_ConnHdlr {
640 var BssgpDecoded bd;
641 timer T := 5.0;
642 BSSGP.send(ts_GMM_DET_REQ_MO(detach_type, power_off));
643 if (expect_purge) {
644 GSUP.receive(tr_GSUP_PURGE_MS_REQ(g_pars.imsi, OSMO_GSUP_CN_DOMAIN_PS));
645 GSUP.send(ts_GSUP_PURGE_MS_RES(g_pars.imsi));
646 }
647 T.start;
648 alt {
649 [not expect_purge] GSUP.receive(tr_GSUP_PURGE_MS_REQ(?)) {
650 setverdict(fail, "Unexpected GSUP PURGE MS for unregistered TLLI");
651 }
652 [power_off] BSSGP.receive(tr_BD_L3_MT(tr_GMM_DET_ACCEPT_MT)) -> value bd {
653 g_pars.ra := omit;
654 setverdict(fail, "Unexpected ATTACH ACCEPT in no-power-off DETACH");
655 /* TODO: check if any PDP contexts are deactivated on network side? */
656 }
657 [power_off] T.timeout {
658 setverdict(pass);
659 }
660 [not power_off] BSSGP.receive(tr_BD_L3_MT(tr_GMM_DET_ACCEPT_MT)) -> value bd {
661 g_pars.ra := omit;
662 setverdict(pass);
663 /* TODO: check if any PDP contexts are deactivated on network side? */
664 }
665 [] BSSGP.receive { repeat; }
666 }
667}
668
669/* IMSI DETACH (non-power-off) for unknown TLLI */
670private function f_TC_detach_unknown_nopoweroff(charstring id) runs on BSSGP_ConnHdlr {
671 f_detach_mo(c_GMM_DTT_MO_GPRS, false, false);
672}
673testcase TC_detach_unknown_nopoweroff() runs on test_CT {
674 var BSSGP_ConnHdlr vc_conn;
675 f_init();
676 f_sleep(1.0);
677 vc_conn := f_start_handler(refers(f_TC_detach_unknown_nopoweroff), testcasename(), g_gb[0], 13);
678 vc_conn.done;
679}
680
681/* IMSI DETACH (power-off) for unknown TLLI */
682private function f_TC_detach_unknown_poweroff(charstring id) runs on BSSGP_ConnHdlr {
683 f_detach_mo(c_GMM_DTT_MO_GPRS, true, false);
684}
685testcase TC_detach_unknown_poweroff() runs on test_CT {
686 var BSSGP_ConnHdlr vc_conn;
687 f_init();
688 f_sleep(1.0);
689 vc_conn := f_start_handler(refers(f_TC_detach_unknown_poweroff), testcasename(), g_gb[0], 14);
690 vc_conn.done;
691}
692
693/* IMSI DETACH (non-power-off) for known TLLI */
694private function f_TC_detach_nopoweroff(charstring id) runs on BSSGP_ConnHdlr {
695 /* first perform regular attach */
696 f_TC_attach(id);
697
698 f_detach_mo(c_GMM_DTT_MO_GPRS, false, true);
699}
700testcase TC_detach_nopoweroff() runs on test_CT {
701 var BSSGP_ConnHdlr vc_conn;
702 f_init();
703 f_sleep(1.0);
704 vc_conn := f_start_handler(refers(f_TC_detach_nopoweroff), testcasename(), g_gb[0], 15);
705 vc_conn.done;
706}
707
708/* IMSI DETACH (power-off) for known TLLI */
709private function f_TC_detach_poweroff(charstring id) runs on BSSGP_ConnHdlr {
710 /* first perform regular attach */
711 f_TC_attach(id);
712
713 f_detach_mo(c_GMM_DTT_MO_GPRS, true, true);
714}
715testcase TC_detach_poweroff() runs on test_CT {
716 var BSSGP_ConnHdlr vc_conn;
717 f_init();
718 f_sleep(1.0);
719 vc_conn := f_start_handler(refers(f_TC_detach_poweroff), testcasename(), g_gb[0], 16);
720 vc_conn.done;
721}
722
723
Harald Welteb2124b22018-02-16 22:26:56 +0100724
Harald Welte5ac31492018-02-15 20:39:13 +0100725
726control {
Harald Welte5b7c8122018-02-16 21:48:17 +0100727 execute( TC_attach() );
728 execute( TC_attach_auth_id_timeout() );
729 execute( TC_attach_auth_sai_timeout() );
Harald Weltefe253882018-02-17 09:25:00 +0100730 execute( TC_attach_auth_sai_reject() );
Harald Welte5b7c8122018-02-16 21:48:17 +0100731 execute( TC_attach_gsup_lu_timeout() );
Harald Welteb7c14e92018-02-17 09:29:16 +0100732 execute( TC_attach_gsup_lu_reject() );
Harald Welte3823e2e2018-02-16 21:53:48 +0100733 execute( TC_attach_combined() );
Harald Welte76dee092018-02-16 22:12:59 +0100734 execute( TC_attach_accept_all() );
Harald Welteb2124b22018-02-16 22:26:56 +0100735 execute( TC_attach_closed() );
Harald Welte04683d02018-02-16 22:43:45 +0100736 execute( TC_rau_unknown() );
Harald Welte91636de2018-02-17 10:16:14 +0100737 execute( TC_attach_rau() );
Harald Welte6abb9fe2018-02-17 15:24:48 +0100738 execute( TC_detach_unknown_nopoweroff() );
739 execute( TC_detach_unknown_poweroff() );
740 execute( TC_detach_nopoweroff() );
741 execute( TC_detach_poweroff() );
Harald Welte5ac31492018-02-15 20:39:13 +0100742}
Harald Welte96a33b02018-02-04 10:36:22 +0100743
744
745
746}