blob: d619068de7ab8e17e15695dc134e5c9f8cbe475e [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;
Daniel Willmann191e0d92018-01-17 12:44:35 +010013import from MGCP_Emulation all;
Harald Welte28d943e2017-11-25 15:00:50 +010014import from SDP_Types all;
15
Harald Weltec1a2fff2017-12-17 11:06:19 +010016import from RSL_Emulation all;
17import from RSL_Types all;
18
19import from MobileL3_Types all;
20import from MobileL3_CommonIE_Types all;
21//import from MobileL3_RRM_Types all;
22import from L3_Templates all;
23
24
Harald Welte28d943e2017-11-25 15:00:50 +010025/* this component represents a single subscriber connection at the MSC.
26 * There is a 1:1 mapping between SCCP connections and BSSAP_ConnHdlr components.
27 * We inherit all component variables, ports, functions, ... from BSSAP_ConnHdlr */
Daniel Willmann191e0d92018-01-17 12:44:35 +010028type component MSC_ConnHdlr extends BSSAP_ConnHdlr, RSL_DchanHdlr, MGCP_ConnHdlr {
Harald Welte28d943e2017-11-25 15:00:50 +010029 /* SCCP Connecction Identifier for the underlying SCCP connection */
30 var integer g_sccp_conn_id;
31
Harald Weltec1a2fff2017-12-17 11:06:19 +010032 /* procedure port back to our parent (BSSMAP_Emulation_CT) for control */
33 port BSSMAPEM_PROC_PT BSSMAPEM;
Harald Welte28d943e2017-11-25 15:00:50 +010034
Harald Weltec1a2fff2017-12-17 11:06:19 +010035 var MSC_State g_state := MSC_STATE_NONE;
Harald Welte28d943e2017-11-25 15:00:50 +010036}
37
38/* Callback function from general BSSMAP_Emulation whenever a connectionless
39 * BSSMAP message arrives. Can retunr a PDU_BSSAP that should be sent in return */
40private function UnitdataCallback(PDU_BSSAP bssap)
41runs on BSSMAP_Emulation_CT return template PDU_BSSAP {
42 var template PDU_BSSAP resp := omit;
43
Harald Weltec1a2fff2017-12-17 11:06:19 +010044 /* answer all RESET with a RESET ACK */
Harald Welte28d943e2017-11-25 15:00:50 +010045 if (match(bssap, tr_BSSMAP_Reset)) {
46 resp := ts_BSSMAP_ResetAck;
47 }
48
49 return resp;
50}
51
52const BssmapOps MSC_BssmapOps := {
Harald Weltec1a2fff2017-12-17 11:06:19 +010053 create_cb := refers(BSSMAP_Emulation.ExpectedCreateCallback),
Harald Welte0b476062018-01-21 19:07:32 +010054 unitdata_cb := refers(UnitdataCallback),
55 decode_dtap := false,
56 role_ms := false
Harald Welte28d943e2017-11-25 15:00:50 +010057}
58
Daniel Willmann191e0d92018-01-17 12:44:35 +010059const MGCPOps MSC_MGCPOps := {
60 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback)
61}
62
Harald Welte28d943e2017-11-25 15:00:50 +010063type enumerated MSC_State {
64 MSC_STATE_NONE,
65 MSC_STATE_WAIT_ASS_COMPL,
66 MSC_STATE_WAIT_CRCX_ACK,
67 MSC_STATE_WAIT_MDCX_ACK,
68 MSC_STATE_WAIT_CLEAR_COMPL,
69 MSC_STATE_WAIT_DLCX_ACK
70}
71
Harald Weltec1a2fff2017-12-17 11:06:19 +010072/* register an expect with the BSSMAP core */
Daniel Willmann191e0d92018-01-17 12:44:35 +010073private function f_create_bssmap_exp(octetstring l3_enc) runs on MSC_ConnHdlr {
Harald Weltec1a2fff2017-12-17 11:06:19 +010074 BSSMAPEM.call(BSSMAPEM_register:{l3_enc, self}) {
75 [] BSSMAPEM.getreply(BSSMAPEM_register:{?, ?}) {};
Harald Welte28d943e2017-11-25 15:00:50 +010076 }
77}
78
Harald Weltec1a2fff2017-12-17 11:06:19 +010079type record TestHdlrParams {
80 OCT1 ra,
81 GsmFrameNumber fn,
82 hexstring imsi,
83 RslLinkId link_id
84};
85
86template (value) TestHdlrParams t_def_TestHdlrPars := {
87 ra := '23'O,
88 fn := 23,
89 imsi := '001019876543210'H,
90 link_id := valueof(ts_RslLinkID_DCCH(0))
91}
92
93function f_create_chan_and_exp(TestHdlrParams pars) runs on MSC_ConnHdlr {
94 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(pars.imsi));
Harald Welte6ed6bf92018-01-24 21:09:15 +010095 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
Harald Weltec1a2fff2017-12-17 11:06:19 +010096 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
97
98 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
99 RSL_Emulation.f_chan_est(pars.ra, l3_enc, pars.link_id, pars.fn);
Daniel Willmann191e0d92018-01-17 12:44:35 +0100100 f_create_bssmap_exp(l3_enc);
Harald Weltec1a2fff2017-12-17 11:06:19 +0100101}
102
103function f_rsl_reply(template PDU_ML3_MS_NW l3, RSL_Message orig) runs on MSC_ConnHdlr {
104 var RslChannelNr chan_nr := orig.ies[0].body.chan_nr;
Harald Welte1a40de62017-12-23 02:28:34 +0100105 var RslLinkId link_id;
Harald Welte8d5eead2017-12-17 18:56:45 +0100106 if (orig.msg_type == RSL_MT_ENCR_CMD) {
107 link_id := orig.ies[2].body.link_id;
108 } else {
109 link_id := orig.ies[1].body.link_id;
110 }
Harald Weltec1a2fff2017-12-17 11:06:19 +0100111 RSL.send(ts_RSL_DATA_IND(chan_nr, link_id, enc_PDU_ML3_MS_NW(valueof(l3))));
112}
113
Harald Welte38b2a102017-12-23 02:42:58 +0100114function f_cipher_mode(OCT1 alg, OCT8 key, template OCT16 kc128 := omit, boolean exp_fail := false)
115runs on MSC_ConnHdlr {
Harald Welte73cd2712017-12-17 00:44:52 +0100116 var PDU_BSSAP bssap;
117 var RSL_Message rsl;
118
119 if (isvalue(kc128)) {
120 BSSAP.send(ts_BSSMAP_CipherModeCmdKc128(alg, key, valueof(kc128)));
121 } else {
122 BSSAP.send(ts_BSSMAP_CipherModeCmd(alg, key));
123 }
124 alt {
125 /* RSL/UE Side */
126 [] RSL.receive(tr_RSL_ENCR_CMD(g_chan_nr, ?, alg, key)) -> value rsl {
127 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[3].body.l3_info.payload);
128 log("Rx L3 from net: ", l3);
129 if (ischosen(l3.msgs.rrm.cipheringModeCommand)) {
130 f_rsl_reply(ts_RRM_CiphModeCompl, rsl);
131 }
132 repeat;
133 }
134 [] BSSAP.receive(tr_BSSMAP_CipherModeCompl) -> value bssap {
135 // bssap.bssmap.cipherModeComplete.chosenEncryptionAlgorithm.algoritmhIdentifier
Harald Welte38b2a102017-12-23 02:42:58 +0100136 if (exp_fail == true) {
137 setverdict(fail, "Unexpected Cipher Mode Complete");
138 } else {
139 setverdict(pass);
140 }
Harald Welte73cd2712017-12-17 00:44:52 +0100141 }
142 [] BSSAP.receive(tr_BSSMAP_CipherModeRej) -> value bssap {
Harald Welte38b2a102017-12-23 02:42:58 +0100143 if (exp_fail == false) {
144 setverdict(fail, "Ciphering Mode Reject");
145 } else {
146 setverdict(pass);
147 }
Harald Welte73cd2712017-12-17 00:44:52 +0100148 }
149 }
150}
151
Harald Weltec1a2fff2017-12-17 11:06:19 +0100152/* establish a channel fully, expecting an assignment matching 'exp' */
153function f_establish_fully(TestHdlrParams pars, PDU_BSSAP ass_cmd, template PDU_BSSAP exp_ass_cpl)
154runs on MSC_ConnHdlr return PDU_BSSAP {
155 var PDU_BSSAP bssap;
156 var RSL_Message rsl;
Daniel Willmannaeea76f2018-01-17 15:23:45 +0100157 var MgcpCommand cmd;
Harald Weltec1a2fff2017-12-17 11:06:19 +0100158 timer T := 10.0;
159 var boolean exp_compl := ischosen(exp_ass_cpl.pdu.bssmap.assignmentComplete);
Harald Welte82d2b872017-12-16 23:36:23 +0100160 var boolean crcx_seen := false;
161 var boolean rr_modify_seen := false;
Daniel Willmann21ea2392018-01-17 15:22:32 +0100162 var ExpectCriteria mgcpcrit := {
163 connid := omit,
164 endpoint := omit,
165 transid := omit
166 };
Daniel Willmanna3d192f2018-01-17 17:58:50 +0100167 var SDP_Message sdp;
Harald Weltec1a2fff2017-12-17 11:06:19 +0100168
Daniel Willmannaeea76f2018-01-17 15:23:45 +0100169 mgcp_conn_id := f_mgcp_alloc_conn_id();
Harald Weltec1a2fff2017-12-17 11:06:19 +0100170 f_create_chan_and_exp(pars);
171 /* we should now have a COMPL_L3 at the MSC */
172
173 BSSAP.receive(tr_BSSMAP_ComplL3);
Daniel Willmann21ea2392018-01-17 15:22:32 +0100174 f_create_mgcp_expect(mgcpcrit);
Harald Weltec1a2fff2017-12-17 11:06:19 +0100175 BSSAP.send(ass_cmd);
Daniel Willmanna3d192f2018-01-17 17:58:50 +0100176 MGCP.receive(tr_CRCX) -> value cmd;
177 sdp := valueof(ts_SDP("127.0.0.1", "127.0.0.1", "foo", "21", 1000, { "98" },
178 {valueof(ts_SDP_rtpmap(98, "AMR/8000")),
179 valueof(ts_SDP_ptime(20)) } ));
180 MGCP.send(ts_CRCX_ACK(cmd.line.trans_id, mgcp_conn_id, sdp))
181
Harald Weltec1a2fff2017-12-17 11:06:19 +0100182 alt {
183 /* if we receive exactly what we expected, always return + pass */
184 [] BSSAP.receive(exp_ass_cpl) -> value bssap {
185 setverdict(pass);
186 return bssap;
187 }
Harald Welte82d2b872017-12-16 23:36:23 +0100188 [rr_modify_seen == false] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
Harald Weltec1a2fff2017-12-17 11:06:19 +0100189 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
190 log("Rx L3 from net: ", l3);
191 if (ischosen(l3.msgs.rrm.channelModeModify)) {
192 f_rsl_reply(ts_RRM_ModeModifyAck(l3.msgs.rrm.channelModeModify.channelDescription,
193 l3.msgs.rrm.channelModeModify.channelMode), rsl);
Harald Welte82d2b872017-12-16 23:36:23 +0100194 rr_modify_seen := true;
Harald Weltec1a2fff2017-12-17 11:06:19 +0100195 }
196 repeat;
197 }
Harald Welte82d2b872017-12-16 23:36:23 +0100198 [rr_modify_seen] RSL.receive(tr_RSL_MsgTypeD(RSL_MT_MODE_MODIFY_REQ)) -> value rsl {
Harald Weltec1a2fff2017-12-17 11:06:19 +0100199 RSL.send(ts_RSL_MODE_MODIFY_ACK(g_chan_nr));
200 repeat;
201 }
Harald Welte82d2b872017-12-16 23:36:23 +0100202 [crcx_seen == false] RSL.receive(tr_RSL_IPA_CRCX(g_chan_nr)) -> value rsl {
Harald Weltec1a2fff2017-12-17 11:06:19 +0100203 RSL.send(ts_RSL_IPA_CRCX_ACK(g_chan_nr, 1, 1, 1, 1));
Harald Welte82d2b872017-12-16 23:36:23 +0100204 crcx_seen := true;
Harald Weltec1a2fff2017-12-17 11:06:19 +0100205 repeat;
206 }
Daniel Willmann191e0d92018-01-17 12:44:35 +0100207 /* mgw CRCX goes here */
208
Harald Welte82d2b872017-12-16 23:36:23 +0100209 [crcx_seen] RSL.receive(tr_RSL_IPA_MDCX(g_chan_nr, ?)) -> value rsl{
Harald Weltec1a2fff2017-12-17 11:06:19 +0100210 RSL.send(ts_RSL_IPA_MDCX_ACK(g_chan_nr, 1, 1, 1, 1));
211 repeat;
212 }
Daniel Willmann191e0d92018-01-17 12:44:35 +0100213 /* mgw MGCX goes here */
214
Harald Weltec1a2fff2017-12-17 11:06:19 +0100215 [exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentComplete) {
216 setverdict(fail, "Received non-matching ASSIGNMENT COMPLETE");
217 }
218 [exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentFail) {
219 setverdict(fail, "Received unexpected ASSIGNMENT FAIL");
220 }
221 [not exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentComplete) {
222 setverdict(fail, "Received unexpected ASSIGNMENT COMPLETE");
223 }
224 [not exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentFail) {
225 setverdict(fail, "Received non-matching ASSIGNMENT FAIL");
226 }
227 [] T.timeout {
228 setverdict(inconc, "Timeout waiting for ASSIGNMENT COMPLETE");
229 }
230 }
231
232 self.stop;
233}
234
235
Harald Welte28d943e2017-11-25 15:00:50 +0100236}