blob: d1be0efa8b33dad0724eafcadf36c344abe09c97 [file] [log] [blame]
Harald Welte28d943e2017-11-25 15:00:50 +01001module MSC_ConnectionHandler {
2
3import from General_Types all;
4import from Osmocom_Types all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01005import from GSM_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +01006import from SCCPasp_Types all;
7import from BSSAP_Types all;
8import from BSSMAP_Emulation all;
9import from BSSMAP_Templates all;
10
11import from MGCP_Types all;
12import from MGCP_Templates all;
13import from SDP_Types all;
14
Harald Weltec1a2fff2017-12-17 11:06:19 +010015import from RSL_Emulation all;
16import from RSL_Types all;
17
18import from MobileL3_Types all;
19import from MobileL3_CommonIE_Types all;
20//import from MobileL3_RRM_Types all;
21import from L3_Templates all;
22
23
Harald Welte28d943e2017-11-25 15:00:50 +010024/* this component represents a single subscriber connection at the MSC.
25 * There is a 1:1 mapping between SCCP connections and BSSAP_ConnHdlr components.
26 * We inherit all component variables, ports, functions, ... from BSSAP_ConnHdlr */
Harald Weltec1a2fff2017-12-17 11:06:19 +010027type component MSC_ConnHdlr extends BSSAP_ConnHdlr, RSL_DchanHdlr {
Harald Welte28d943e2017-11-25 15:00:50 +010028 /* SCCP Connecction Identifier for the underlying SCCP connection */
29 var integer g_sccp_conn_id;
30
Harald Weltec1a2fff2017-12-17 11:06:19 +010031 /* procedure port back to our parent (BSSMAP_Emulation_CT) for control */
32 port BSSMAPEM_PROC_PT BSSMAPEM;
Harald Welte28d943e2017-11-25 15:00:50 +010033
Harald Weltec1a2fff2017-12-17 11:06:19 +010034 var MSC_State g_state := MSC_STATE_NONE;
Harald Welte28d943e2017-11-25 15:00:50 +010035}
36
37/* Callback function from general BSSMAP_Emulation whenever a connectionless
38 * BSSMAP message arrives. Can retunr a PDU_BSSAP that should be sent in return */
39private function UnitdataCallback(PDU_BSSAP bssap)
40runs on BSSMAP_Emulation_CT return template PDU_BSSAP {
41 var template PDU_BSSAP resp := omit;
42
Harald Weltec1a2fff2017-12-17 11:06:19 +010043 /* answer all RESET with a RESET ACK */
Harald Welte28d943e2017-11-25 15:00:50 +010044 if (match(bssap, tr_BSSMAP_Reset)) {
45 resp := ts_BSSMAP_ResetAck;
46 }
47
48 return resp;
49}
50
51const BssmapOps MSC_BssmapOps := {
Harald Weltec1a2fff2017-12-17 11:06:19 +010052 create_cb := refers(BSSMAP_Emulation.ExpectedCreateCallback),
Harald Welte0b476062018-01-21 19:07:32 +010053 unitdata_cb := refers(UnitdataCallback),
54 decode_dtap := false,
55 role_ms := false
Harald Welte28d943e2017-11-25 15:00:50 +010056}
57
58type enumerated MSC_State {
59 MSC_STATE_NONE,
60 MSC_STATE_WAIT_ASS_COMPL,
61 MSC_STATE_WAIT_CRCX_ACK,
62 MSC_STATE_WAIT_MDCX_ACK,
63 MSC_STATE_WAIT_CLEAR_COMPL,
64 MSC_STATE_WAIT_DLCX_ACK
65}
66
Harald Weltec1a2fff2017-12-17 11:06:19 +010067/* register an expect with the BSSMAP core */
68private function f_create_exp(octetstring l3_enc) runs on MSC_ConnHdlr {
69 BSSMAPEM.call(BSSMAPEM_register:{l3_enc, self}) {
70 [] BSSMAPEM.getreply(BSSMAPEM_register:{?, ?}) {};
Harald Welte28d943e2017-11-25 15:00:50 +010071 }
72}
73
Harald Weltec1a2fff2017-12-17 11:06:19 +010074type record TestHdlrParams {
75 OCT1 ra,
76 GsmFrameNumber fn,
77 hexstring imsi,
78 RslLinkId link_id
79};
80
81template (value) TestHdlrParams t_def_TestHdlrPars := {
82 ra := '23'O,
83 fn := 23,
84 imsi := '001019876543210'H,
85 link_id := valueof(ts_RslLinkID_DCCH(0))
86}
87
88function f_create_chan_and_exp(TestHdlrParams pars) runs on MSC_ConnHdlr {
89 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +010090 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltec1a2fff2017-12-17 11:06:19 +010091 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
92
93 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
94 RSL_Emulation.f_chan_est(pars.ra, l3_enc, pars.link_id, pars.fn);
95 f_create_exp(l3_enc);
96}
97
98function f_rsl_reply(template PDU_ML3_MS_NW l3, RSL_Message orig) runs on MSC_ConnHdlr {
99 var RslChannelNr chan_nr := orig.ies[0].body.chan_nr;
Harald Welte1a40de62017-12-23 02:28:34 +0100100 var RslLinkId link_id;
Harald Welte8d5eead2017-12-17 18:56:45 +0100101 if (orig.msg_type == RSL_MT_ENCR_CMD) {
102 link_id := orig.ies[2].body.link_id;
103 } else {
104 link_id := orig.ies[1].body.link_id;
105 }
Harald Weltec1a2fff2017-12-17 11:06:19 +0100106 RSL.send(ts_RSL_DATA_IND(chan_nr, link_id, enc_PDU_ML3_MS_NW(valueof(l3))));
107}
108
Harald Welte38b2a102017-12-23 02:42:58 +0100109function f_cipher_mode(OCT1 alg, OCT8 key, template OCT16 kc128 := omit, boolean exp_fail := false)
110runs on MSC_ConnHdlr {
Harald Welte73cd2712017-12-17 00:44:52 +0100111 var PDU_BSSAP bssap;
112 var RSL_Message rsl;
113
114 if (isvalue(kc128)) {
115 BSSAP.send(ts_BSSMAP_CipherModeCmdKc128(alg, key, valueof(kc128)));
116 } else {
117 BSSAP.send(ts_BSSMAP_CipherModeCmd(alg, key));
118 }
119 alt {
120 /* RSL/UE Side */
121 [] RSL.receive(tr_RSL_ENCR_CMD(g_chan_nr, ?, alg, key)) -> value rsl {
122 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[3].body.l3_info.payload);
123 log("Rx L3 from net: ", l3);
124 if (ischosen(l3.msgs.rrm.cipheringModeCommand)) {
125 f_rsl_reply(ts_RRM_CiphModeCompl, rsl);
126 }
127 repeat;
128 }
129 [] BSSAP.receive(tr_BSSMAP_CipherModeCompl) -> value bssap {
130 // bssap.bssmap.cipherModeComplete.chosenEncryptionAlgorithm.algoritmhIdentifier
Harald Welte38b2a102017-12-23 02:42:58 +0100131 if (exp_fail == true) {
132 setverdict(fail, "Unexpected Cipher Mode Complete");
133 } else {
134 setverdict(pass);
135 }
Harald Welte73cd2712017-12-17 00:44:52 +0100136 }
137 [] BSSAP.receive(tr_BSSMAP_CipherModeRej) -> value bssap {
Harald Welte38b2a102017-12-23 02:42:58 +0100138 if (exp_fail == false) {
139 setverdict(fail, "Ciphering Mode Reject");
140 } else {
141 setverdict(pass);
142 }
Harald Welte73cd2712017-12-17 00:44:52 +0100143 }
144 }
145}
146
Harald Weltec1a2fff2017-12-17 11:06:19 +0100147/* establish a channel fully, expecting an assignment matching 'exp' */
148function f_establish_fully(TestHdlrParams pars, PDU_BSSAP ass_cmd, template PDU_BSSAP exp_ass_cpl)
149runs on MSC_ConnHdlr return PDU_BSSAP {
150 var PDU_BSSAP bssap;
151 var RSL_Message rsl;
152 timer T := 10.0;
153 var boolean exp_compl := ischosen(exp_ass_cpl.pdu.bssmap.assignmentComplete);
Harald Welte82d2b872017-12-16 23:36:23 +0100154 var boolean crcx_seen := false;
155 var boolean rr_modify_seen := false;
Harald Weltec1a2fff2017-12-17 11:06:19 +0100156
157 f_create_chan_and_exp(pars);
158 /* we should now have a COMPL_L3 at the MSC */
159
160 BSSAP.receive(tr_BSSMAP_ComplL3);
161 BSSAP.send(ass_cmd);
162 alt {
163 /* if we receive exactly what we expected, always return + pass */
164 [] BSSAP.receive(exp_ass_cpl) -> value bssap {
165 setverdict(pass);
166 return bssap;
167 }
Harald Welte82d2b872017-12-16 23:36:23 +0100168 [rr_modify_seen == false] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
Harald Weltec1a2fff2017-12-17 11:06:19 +0100169 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
170 log("Rx L3 from net: ", l3);
171 if (ischosen(l3.msgs.rrm.channelModeModify)) {
172 f_rsl_reply(ts_RRM_ModeModifyAck(l3.msgs.rrm.channelModeModify.channelDescription,
173 l3.msgs.rrm.channelModeModify.channelMode), rsl);
Harald Welte82d2b872017-12-16 23:36:23 +0100174 rr_modify_seen := true;
Harald Weltec1a2fff2017-12-17 11:06:19 +0100175 }
176 repeat;
177 }
Harald Welte82d2b872017-12-16 23:36:23 +0100178 [rr_modify_seen] RSL.receive(tr_RSL_MsgTypeD(RSL_MT_MODE_MODIFY_REQ)) -> value rsl {
Harald Weltec1a2fff2017-12-17 11:06:19 +0100179 RSL.send(ts_RSL_MODE_MODIFY_ACK(g_chan_nr));
180 repeat;
181 }
Harald Welte82d2b872017-12-16 23:36:23 +0100182 [crcx_seen == false] RSL.receive(tr_RSL_IPA_CRCX(g_chan_nr)) -> value rsl {
Harald Weltec1a2fff2017-12-17 11:06:19 +0100183 RSL.send(ts_RSL_IPA_CRCX_ACK(g_chan_nr, 1, 1, 1, 1));
Harald Welte82d2b872017-12-16 23:36:23 +0100184 crcx_seen := true;
Harald Weltec1a2fff2017-12-17 11:06:19 +0100185 repeat;
186 }
Harald Welte82d2b872017-12-16 23:36:23 +0100187 [crcx_seen] RSL.receive(tr_RSL_IPA_MDCX(g_chan_nr, ?)) -> value rsl{
Harald Weltec1a2fff2017-12-17 11:06:19 +0100188 RSL.send(ts_RSL_IPA_MDCX_ACK(g_chan_nr, 1, 1, 1, 1));
189 repeat;
190 }
191 [exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentComplete) {
192 setverdict(fail, "Received non-matching ASSIGNMENT COMPLETE");
193 }
194 [exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentFail) {
195 setverdict(fail, "Received unexpected ASSIGNMENT FAIL");
196 }
197 [not exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentComplete) {
198 setverdict(fail, "Received unexpected ASSIGNMENT COMPLETE");
199 }
200 [not exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentFail) {
201 setverdict(fail, "Received non-matching ASSIGNMENT FAIL");
202 }
203 [] T.timeout {
204 setverdict(inconc, "Timeout waiting for ASSIGNMENT COMPLETE");
205 }
206 }
207
208 self.stop;
209}
210
211
Harald Welte28d943e2017-11-25 15:00:50 +0100212}