blob: 07fefe5560b477ad7dff79e0d422b2bcb7a2c258 [file] [log] [blame]
Harald Welted86cdc62017-11-22 00:45:07 +01001module IPA_Emulation {
2
Harald Weltebdb63702017-12-09 01:15:44 +01003/* This module implements the IPA multiplex protocol on top of TCP, using the IPL4asp
4 * test-port as provider. It implements both client and server roles, as well was the CCM
Pau Espin Pedrol76ba5412019-06-10 11:00:33 +02005 * handshake for establishing the identity of the client to the server.
Harald Welte35bb7162018-01-03 21:07:52 +01006 *
7 * It already knows certain well-known sub-protocols such as A-bis RSL, MGCP and SCCP and
8 * GSUP. IT hence transcodes messages so the user can work with abstract data types rather
9 * than binary messages. It handles multiple packets inside one TCP segment.
10 *
Harald Welte34b5a952019-05-27 11:54:11 +020011 * (C) 2017-2019 by Harald Welte <laforge@gnumonks.org>
12 * contributions by sysmocom - s.f.m.c. GmbH
Harald Welte35bb7162018-01-03 21:07:52 +010013 * All rights reserved.
14 *
15 * Released under the terms of GNU General Public License, Version 2 or
16 * (at your option) any later version.
Harald Welte34b5a952019-05-27 11:54:11 +020017 *
18 * SPDX-License-Identifier: GPL-2.0-or-later
Harald Welte35bb7162018-01-03 21:07:52 +010019 */
Harald Weltebdb63702017-12-09 01:15:44 +010020
Harald Welted86cdc62017-11-22 00:45:07 +010021import from IPA_Types all;
22import from IPA_CodecPort all;
23import from IPA_CodecPort_CtrlFunct all;
24import from IPL4asp_Types all;
Harald Welte12188832017-11-29 11:47:13 +010025import from IPL4asp_PortType all;
Stefan Sperling830dc9d2018-02-12 21:08:28 +010026import from Socket_API_Definitions all;
Harald Welted86cdc62017-11-22 00:45:07 +010027
Harald Weltedf277252018-02-20 15:49:30 +010028#ifdef IPA_EMULATION_SCCP
29import from MTP3asp_Types all;
30import from MTP3asp_PortType all;
31#endif
32
33#ifdef IPA_EMULATION_RSL
34import from RSL_Types all;
35#endif
36
Harald Weltec6826662019-02-06 22:26:46 +010037#ifdef IPA_EMULATION_OML
38import from AbisOML_Types all;
39#endif
40
Harald Weltedf277252018-02-20 15:49:30 +010041#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +010042import from MGCP_Types all;
Harald Weltedf277252018-02-20 15:49:30 +010043#endif
44
45#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +010046import from GSUP_Types all;
Pau Espin Pedrol8f1403a2024-01-18 20:08:43 +010047import from GSUP_Templates all;
Harald Weltedf277252018-02-20 15:49:30 +010048#endif
Harald Weltec82eef42017-11-24 20:40:12 +010049
Harald Welte7460a722018-10-10 12:28:27 +020050#ifdef IPA_EMULATION_RSPRO
51import from RSPRO all;
52import from RSPRO_Types all;
53#endif
54
Harald Welte3286eb32019-08-18 19:36:10 +020055#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +010056import from Osmocom_CTRL_Types all;
Harald Welte3286eb32019-08-18 19:36:10 +020057#endif
Harald Weltea76c4bb2017-12-09 02:06:07 +010058
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +020059#ifdef IPA_EMULATION_OSMO_PCU
60import from PCUIF_Types all;
61#endif
62
Harald Welted86cdc62017-11-22 00:45:07 +010063modulepar {
Harald Welte92632e12017-11-25 02:31:20 +010064 /* Use Osmocom extended IPA mux header */
65 boolean mp_ipa_mgcp_uses_osmo_ext := true;
Harald Welted86cdc62017-11-22 00:45:07 +010066}
Harald Welted86cdc62017-11-22 00:45:07 +010067
Harald Welteb3414b22017-11-23 18:22:10 +010068type enumerated IpaMode {
69 IPA_MODE_CLIENT,
70 IPA_MODE_SERVER
71}
72
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +020073type enumerated IpaInitBehavior {
74 IPA_INIT_SEND_IPA_ID_GET,
75 IPA_INIT_SEND_IPA_ID_ACK
76}
77
Harald Weltec76f29f2017-11-22 12:46:46 +010078type record ASP_IPA_Unitdata {
79 IpaStreamId streamId,
Harald Weltec82eef42017-11-24 20:40:12 +010080 IpaExtStreamId streamIdExt optional,
Harald Weltec76f29f2017-11-22 12:46:46 +010081 octetstring payload
82}
83
Vadim Yanitskiy8701b272020-05-18 20:17:25 +070084type enumerated ASP_IPA_EventType {
Harald Welte0d846a72017-12-07 17:58:28 +010085 ASP_IPA_EVENT_DOWN,
86 ASP_IPA_EVENT_UP,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +070087 ASP_IPA_EVENT_ID_RESP,
Harald Welte0d846a72017-12-07 17:58:28 +010088 ASP_IPA_EVENT_ID_ACK
89}
90
Harald Weltebdb63702017-12-09 01:15:44 +010091/* an event indicating us whether or not a connection is physically up or down,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +070092 * and whether we have received an ID_RESP or ID_ACK */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +070093type record ASP_IPA_Event {
94 ASP_IPA_EventType ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +070095 integer conn_id,
96
97 /* Presence of these fields depends on event type */
98 IpaCcmIdResp id_resp optional // ASP_IPA_EVENT_ID_RESP
Harald Welte0d846a72017-12-07 17:58:28 +010099}
100
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700101template (value) ASP_IPA_Event ts_ASP_IPA_EV(ASP_IPA_EventType ev_type, integer conn_id,
102 template (omit) IpaCcmIdResp id_resp := omit) := {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700103 ev_type := ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700104 conn_id := conn_id,
105 id_resp := id_resp
Vadim Yanitskiy61564be2020-05-18 20:44:14 +0700106}
107
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700108template ASP_IPA_Event tr_ASP_IPA_EV(template ASP_IPA_EventType ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700109 template integer conn_id := ?,
110 template IpaCcmIdResp id_resp := *) := {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700111 ev_type := ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700112 conn_id := conn_id,
113 id_resp := id_resp
Harald Welte0d846a72017-12-07 17:58:28 +0100114}
115
Harald Welte1dd8f372017-11-25 02:25:27 +0100116template ASP_IPA_Unitdata t_ASP_IPA_UD(IpaStreamId sid, octetstring pl,
117 template IpaExtStreamId esid := omit) := {
118 streamId := sid,
119 streamIdExt := esid,
120 payload := pl
121}
122
Harald Weltedf277252018-02-20 15:49:30 +0100123#ifdef IPA_EMULATION_RSL
Harald Weltebdb63702017-12-09 01:15:44 +0100124/* like ASP_IPA_Unitdata, but with RSL_Message abstract type instead of octetstring */
Harald Welte0d846a72017-12-07 17:58:28 +0100125type record ASP_RSL_Unitdata {
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700126 integer conn_id optional,
Harald Welte0d846a72017-12-07 17:58:28 +0100127 IpaStreamId streamId,
128 RSL_Message rsl
129};
130
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700131template (value) ASP_RSL_Unitdata ts_ASP_RSL_UD(template (value) RSL_Message rsl,
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700132 IpaStreamId sid := IPAC_PROTO_RSL_TRX0,
133 template (omit) integer conn_id := omit) := {
134 conn_id := conn_id,
Harald Welte0d846a72017-12-07 17:58:28 +0100135 streamId := sid,
Vadim Yanitskiy6b4856d2020-05-25 21:23:46 +0700136 rsl := rsl
Harald Welte0d846a72017-12-07 17:58:28 +0100137}
138
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700139template ASP_RSL_Unitdata tr_ASP_RSL_UD(template (present) RSL_Message rsl,
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700140 template IpaStreamId sid := IPAC_PROTO_RSL_TRX0,
141 template integer conn_id := *) := {
142 conn_id := conn_id,
Harald Welte7ae019e2017-12-09 00:54:15 +0100143 streamId := sid,
144 rsl := rsl
145}
146
Harald Welte0d846a72017-12-07 17:58:28 +0100147template IpaStreamId t_IpaSidRSL := ( IPAC_PROTO_RSL_TRX0, IPAC_PROTO_RSL_TRX1,
148 IPAC_PROTO_RSL_TRX2, IPAC_PROTO_RSL_TRX3 );
Harald Weltedf277252018-02-20 15:49:30 +0100149#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100150
Harald Weltec6826662019-02-06 22:26:46 +0100151
Harald Weltebdb63702017-12-09 01:15:44 +0100152/* Client port for general IPA messages, not further decoded */
Harald Weltec76f29f2017-11-22 12:46:46 +0100153type port IPA_SP_PT message {
Harald Welte0d846a72017-12-07 17:58:28 +0100154 inout ASP_IPA_Unitdata, ASP_IPA_Event;
Harald Weltec76f29f2017-11-22 12:46:46 +0100155} with { extension "internal" }
156
Harald Weltedf277252018-02-20 15:49:30 +0100157#ifdef IPA_EMULATION_MGCP
Harald Weltebdb63702017-12-09 01:15:44 +0100158/* Client port for MGCP inside IPA */
Harald Weltec82eef42017-11-24 20:40:12 +0100159type port IPA_MGCP_PT message {
160 inout MgcpCommand, MgcpResponse;
161} with { extension "internal" }
Harald Weltedf277252018-02-20 15:49:30 +0100162#endif
Harald Weltec82eef42017-11-24 20:40:12 +0100163
Harald Weltedf277252018-02-20 15:49:30 +0100164#ifdef IPA_EMULATION_RSL
Harald Weltebdb63702017-12-09 01:15:44 +0100165/* Client port for A-bis RSL inside IPA */
Harald Welte0d846a72017-12-07 17:58:28 +0100166type port IPA_RSL_PT message {
167 inout ASP_RSL_Unitdata, ASP_IPA_Event;
168} with { extension "internal" }
Harald Weltedf277252018-02-20 15:49:30 +0100169#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100170
Harald Weltec6826662019-02-06 22:26:46 +0100171#ifdef IPA_EMULATION_OML
172/* Client port for A-bis OML inside IPA */
173type port IPA_OML_PT message {
174 inout OML_PDU, octetstring, ASP_IPA_Event;
175} with { extension "internal" }
176#endif
177
Harald Welte3286eb32019-08-18 19:36:10 +0200178#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +0100179/* Client port for CTRL inside IPA */
180type port IPA_CTRL_PT message {
181 inout CtrlMessage, ASP_IPA_Event;
182} with { extension "internal" }
Harald Welte3286eb32019-08-18 19:36:10 +0200183#endif
Harald Weltea76c4bb2017-12-09 02:06:07 +0100184
Harald Weltedf277252018-02-20 15:49:30 +0100185#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100186/* Client port for CTRL inside IPA */
187type port IPA_GSUP_PT message {
188 inout GSUP_PDU, ASP_IPA_Event;
189} with { extension "internal" }
Harald Weltedf277252018-02-20 15:49:30 +0100190#endif
Harald Weltedf327232017-12-28 22:51:51 +0100191
Harald Welte7460a722018-10-10 12:28:27 +0200192#ifdef IPA_EMULATION_RSPRO
193type port IPA_RSPRO_PT message {
194 inout RsproPDU, ASP_IPA_Event;
195} with { extension "internal" }
196#endif
197
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200198#ifdef IPA_EMULATION_OSMO_PCU
199/* Client port for Osmocom PCU extension inside IPA */
200type port IPA_OSMO_PCU_PT message {
201 inout PCUIF_Message, ASP_IPA_Event;
202} with { extension "internal" }
203#endif
Harald Welte7460a722018-10-10 12:28:27 +0200204
205
Harald Weltedf327232017-12-28 22:51:51 +0100206
Harald Welted86cdc62017-11-22 00:45:07 +0100207type component IPA_Emulation_CT {
208 /* down-facing port to IPA codec port */
209 port IPA_CODEC_PT IPA_PORT;
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100210 /* Down facing port to configure the component */
211 port IPA_CFG_PT CFG_PORT;
212
Harald Weltedf277252018-02-20 15:49:30 +0100213#ifdef IPA_EMULATION_SCCP
Harald Welted86cdc62017-11-22 00:45:07 +0100214 /* up-facing port to SCCP */
215 port MTP3asp_SP_PT MTP3_SP_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100216#endif
217#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100218 /* up-facing port for MGCP */
219 port IPA_MGCP_PT IPA_MGCP_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100220#endif
221#ifdef IPA_EMULATION_RSL
Harald Welte0d846a72017-12-07 17:58:28 +0100222 /* up-facing port for RSL */
223 port IPA_RSL_PT IPA_RSL_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100224#endif
Harald Weltec6826662019-02-06 22:26:46 +0100225#ifdef IPA_EMULATION_OML
226 /* up-facing port for OML */
227 port IPA_OML_PT IPA_OML_PORT;
228#endif
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200229#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +0100230 /* up-facing port for CTRL */
231 port IPA_CTRL_PT IPA_CTRL_PORT;
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200232#endif
Harald Weltedf277252018-02-20 15:49:30 +0100233#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100234 /* up-facing port for GSUP */
235 port IPA_GSUP_PT IPA_GSUP_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100236#endif
Harald Welte7460a722018-10-10 12:28:27 +0200237#ifdef IPA_EMULATION_RSPRO
238 /* up-facing port for RSPRO */
239 port IPA_RSPRO_PT IPA_RSPRO_PORT;
240#endif
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200241#ifdef IPA_EMULATION_OSMO_PCU
242 /* up-facing port for RSPRO */
243 port IPA_OSMO_PCU_PT IPA_OSMO_PCU_PORT;
244#endif
Harald Weltedf327232017-12-28 22:51:51 +0100245
Harald Weltec76f29f2017-11-22 12:46:46 +0100246 /* up-facing port for other streams */
247 port IPA_SP_PT IPA_SP_PORT;
Harald Welted86cdc62017-11-22 00:45:07 +0100248
249 var boolean g_initialized := false;
Harald Weltec82eef42017-11-24 20:40:12 +0100250 /* Are we a BSC/MGW (truel) or MSC (false) */
251 var boolean g_is_bsc_mgw;
Harald Welteb3414b22017-11-23 18:22:10 +0100252
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700253 /* Connection identifier of the client / server itself */
254 var IPL4asp_Types.ConnectionId g_self_conn_id := -1;
255 /* Connection identifier of the last connected client (server only) */
256 var IPL4asp_Types.ConnectionId g_last_conn_id := -1;
257
Harald Welteb3414b22017-11-23 18:22:10 +0100258 var IpaMode g_mode;
Harald Welte2d86aff2018-04-17 11:23:04 +0200259 var boolean g_ccm_enabled;
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200260 var IpaInitBehavior g_init_behavior;
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100261 /* Shall we stop the component once the client disconnects, or keep
262 * running to let next user in ? */
263 var boolean g_server_stop_on_ipa_ev_down := true;
Harald Weltee09921f2017-12-07 17:49:00 +0100264 var IPA_CCM_Parameters g_ccm_pars := c_IPA_default_ccm_pars;
Harald Welted86cdc62017-11-22 00:45:07 +0100265}
266
Harald Weltee21096d2017-12-04 20:45:12 +0100267type record IPA_CCM_Parameters {
268 charstring ser_nr optional,
269 charstring name optional,
270 charstring location1 optional,
271 charstring location2 optional,
272 charstring equip_version optional,
273 charstring sw_version optional,
274 charstring ip_addr optional,
275 charstring mac_addr optional,
276 charstring unit_id optional,
277 charstring osmo_rand optional
278}
279
Harald Weltee09921f2017-12-07 17:49:00 +0100280const IPA_CCM_Parameters c_IPA_default_ccm_pars := {
281 ser_nr := "",
Harald Weltee21096d2017-12-04 20:45:12 +0100282 name := "mahlzeit",
Harald Weltee09921f2017-12-07 17:49:00 +0100283 location1 := "",
284 location2 := "",
285 equip_version := "",
286 sw_version := "",
287 ip_addr := "",
288 mac_addr := "",
Harald Weltee21096d2017-12-04 20:45:12 +0100289 unit_id := "0/1/2",
Harald Weltee09921f2017-12-07 17:49:00 +0100290 osmo_rand := ""
Harald Weltee21096d2017-12-04 20:45:12 +0100291};
292
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100293signature IPA_CFG_disconnect(inout IPL4asp_Types.Result res);
294type port IPA_CFG_PT procedure {
295 inout IPA_CFG_disconnect;
296} with { extension "internal" };
297
298function f_ipa_cfg_disconnect(IPA_CFG_PT pt, inout IPL4asp_Types.Result res) {
299 pt.call(IPA_CFG_disconnect:{res}) {
300 [] pt.getreply(IPA_CFG_disconnect:{?}) -> param (res) {};
301 }
302}
303
Harald Weltebdb63702017-12-09 01:15:44 +0100304/* Function to use to connect as client to a remote IPA Server */
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100305function f_connect(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
306 charstring local_host, IPL4asp_Types.PortNumber local_port,
Harald Weltee09921f2017-12-07 17:49:00 +0100307 IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars) runs on IPA_Emulation_CT {
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100308 var IPL4asp_Types.Result res;
Harald Welted86cdc62017-11-22 00:45:07 +0100309 res := IPA_CodecPort_CtrlFunct.f_IPL4_connect(IPA_PORT, remote_host, remote_port,
310 local_host, local_port, 0, { tcp:={} });
Harald Welte9220f632018-05-23 20:27:02 +0200311 if (not ispresent(res.connId)) {
Stefan Sperling6a90be42018-08-31 15:05:39 +0200312 setverdict(fail, "Could not connect IPA socket from ", local_host, " port ", local_port,
313 " to ", remote_host, " port ", remote_port, "; check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200314 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200315 }
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700316 g_self_conn_id := res.connId;
Harald Weltee21096d2017-12-04 20:45:12 +0100317 g_ccm_pars := ccm_pars;
Harald Weltec82eef42017-11-24 20:40:12 +0100318 g_is_bsc_mgw := true;
Harald Welted86cdc62017-11-22 00:45:07 +0100319}
320
Harald Weltebdb63702017-12-09 01:15:44 +0100321/* Function to use to bind to a local port as IPA server, accepting remote clients */
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100322function f_bind(charstring local_host, IPL4asp_Types.PortNumber local_port,
Harald Weltee09921f2017-12-07 17:49:00 +0100323 IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars) runs on IPA_Emulation_CT {
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100324 var IPL4asp_Types.Result res;
Pau Espin Pedrol76ba5412019-06-10 11:00:33 +0200325 res := IPA_CodecPort_CtrlFunct.f_IPL4_listen(IPA_PORT,
Harald Welteb3414b22017-11-23 18:22:10 +0100326 local_host, local_port, { tcp:={} });
Harald Welte9220f632018-05-23 20:27:02 +0200327 if (not ispresent(res.connId)) {
Maxb7aae8b2019-03-11 15:22:02 +0100328 setverdict(fail, "Could not listen IPA socket ", local_host, ":", local_port, ", check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200329 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200330 }
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700331 g_self_conn_id := res.connId;
Harald Weltee21096d2017-12-04 20:45:12 +0100332 g_ccm_pars := ccm_pars;
Harald Weltec82eef42017-11-24 20:40:12 +0100333 g_is_bsc_mgw := false;
Harald Welteb3414b22017-11-23 18:22:10 +0100334}
335
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100336private function f_close() runs on IPA_Emulation_CT return IPL4asp_Types.Result {
337 var IPL4asp_Types.Result res;
338 select (g_mode) {
339 case (IPA_MODE_CLIENT) {
340 res := IPA_CodecPort_CtrlFunct.f_IPL4_close(IPA_PORT, g_self_conn_id, {tcp := {}});
341 g_self_conn_id := -1;
342 }
343 case (IPA_MODE_SERVER) {
344 res := IPA_CodecPort_CtrlFunct.f_IPL4_close(IPA_PORT, g_last_conn_id, {tcp := {}});
345 g_last_conn_id := -1;
346 }
347 case else {
348 setverdict(fail, "Unknown mode");
349 mtc.stop;
350 }
351 }
352 return res;
353}
354
Harald Weltedf277252018-02-20 15:49:30 +0100355#ifdef IPA_EMULATION_SCCP
Harald Welted86cdc62017-11-22 00:45:07 +0100356template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := {
357 sio := { '10'B, '00'B, '0011'B },
358 opc := opc,
359 dpc := 0,
360 sls := 0,
361 data := data
362}
Harald Weltedf277252018-02-20 15:49:30 +0100363#endif
Harald Welted86cdc62017-11-22 00:45:07 +0100364
365
366private template IpaCcmRespPart t_IdRespPart(IpaCcmIdTag tag, charstring payload) := {
367 len := 0, /* overwritten by codec */
368 tag := tag,
Harald Welte95686e02018-08-02 15:05:43 +0200369 data := char2oct(payload) & '00'O
Harald Welted86cdc62017-11-22 00:45:07 +0100370}
371
Vadim Yanitskiy61564be2020-05-18 20:44:14 +0700372private function f_send_IPA_EVT(template (value) ASP_IPA_Event evt) runs on IPA_Emulation_CT {
Harald Welte2e32e432018-05-24 20:00:00 +0200373 if (IPA_SP_PORT.checkstate("Connected")) {
374 IPA_SP_PORT.send(evt);
375 }
Harald Weltedf277252018-02-20 15:49:30 +0100376#ifdef IPA_EMULATION_RSL
Harald Welte5819b552017-12-09 02:55:46 +0100377 if (IPA_RSL_PORT.checkstate("Connected")) {
378 IPA_RSL_PORT.send(evt);
379 }
Harald Weltedf277252018-02-20 15:49:30 +0100380#endif
Harald Weltec6826662019-02-06 22:26:46 +0100381#ifdef IPA_EMULATION_OML
382 if (IPA_OML_PORT.checkstate("Connected")) {
383 IPA_OML_PORT.send(evt);
384 }
385#endif
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200386#ifdef IPA_EMULATION_CTRL
Harald Welte5819b552017-12-09 02:55:46 +0100387 if (IPA_CTRL_PORT.checkstate("Connected")) {
388 IPA_CTRL_PORT.send(evt);
389 }
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200390#endif
Harald Weltedf277252018-02-20 15:49:30 +0100391#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100392 if (IPA_GSUP_PORT.checkstate("Connected")) {
393 IPA_GSUP_PORT.send(evt);
394 }
Harald Weltedf277252018-02-20 15:49:30 +0100395#endif
Harald Welte7460a722018-10-10 12:28:27 +0200396#ifdef IPA_EMULATION_RSPRO
397 if (IPA_RSPRO_PORT.checkstate("Connected")) {
398 IPA_RSPRO_PORT.send(evt);
399 }
400#endif
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200401#ifdef IPA_EMULATION_OSMO_PCU
402 if (IPA_OSMO_PCU_PORT.checkstate("Connected")) {
403 IPA_OSMO_PCU_PORT.send(evt);
404 }
405#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100406 /* FIXME: to other ports */
407}
408
Harald Welted86cdc62017-11-22 00:45:07 +0100409/* build IPA CCM ID RESP response from IPA CCM GET */
Harald Weltee21096d2017-12-04 20:45:12 +0100410private function f_ccm_make_id_resp(PDU_IPA_CCM get) runs on IPA_Emulation_CT return PDU_IPA_CCM {
Harald Welted86cdc62017-11-22 00:45:07 +0100411 var integer i;
412 var PDU_IPA_CCM resp := {
413 msg_type := IPAC_MSGT_ID_RESP,
414 u := {
415 resp := {}
416 }
417 }
418
Pau Espin Pedrol8768f662023-10-12 17:55:56 +0200419 /* If no Tags were present in the received IPA message, .u = omit */
420 if (not ispresent(get.u)) {
421 return resp;
422 }
423
Harald Welted86cdc62017-11-22 00:45:07 +0100424 for (i := 0; i < sizeof(get.u.get); i := i + 1) {
425 var IpaCcmIdTag tag := get.u.get[i].tag;
426 var charstring foo;
427 select (tag) {
Harald Weltee21096d2017-12-04 20:45:12 +0100428 case (IPAC_IDTAG_SERNR) {
429 foo := g_ccm_pars.ser_nr;
Harald Welted86cdc62017-11-22 00:45:07 +0100430 }
431 case (IPAC_IDTAG_UNITNAME) {
Harald Weltee21096d2017-12-04 20:45:12 +0100432 foo := g_ccm_pars.name;
433 }
434 case (IPAC_IDTAG_LOCATION1) {
435 foo := g_ccm_pars.location1;
436 }
437 case (IPAC_IDTAG_LOCATION2) {
438 foo := g_ccm_pars.location2;
439 }
440 case (IPAC_IDTAG_EQUIPVERS) {
441 foo := g_ccm_pars.equip_version;
442 }
443 case (IPAC_IDTAG_SWVERSION) {
444 foo := g_ccm_pars.sw_version;
445 }
446 case (IPAC_IDTAG_IPADDR) {
447 foo := g_ccm_pars.ip_addr;
448 }
449 case (IPAC_IDTAG_MACADDR) {
450 foo := g_ccm_pars.mac_addr;
451 }
Vadim Yanitskiy44f0c482020-05-24 20:49:29 +0700452 case (IPAC_IDTAG_UNITID) {
Harald Weltee21096d2017-12-04 20:45:12 +0100453 foo := g_ccm_pars.unit_id;
454 }
455 case (IPAC_IDTAG_OSMO_RAND) {
456 foo := g_ccm_pars.osmo_rand;
Harald Welted86cdc62017-11-22 00:45:07 +0100457 }
458 case else {
Harald Weltee21096d2017-12-04 20:45:12 +0100459 foo := "unknown";
Harald Welted86cdc62017-11-22 00:45:07 +0100460 }
461 }
462 resp.u.resp[sizeof(resp.u.resp)] := valueof(t_IdRespPart(tag, foo));
463 }
464
465 return resp;
466}
467
468/* transmit IPA CCM message */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700469private function f_ccm_tx(PDU_IPA_CCM ccm, IPL4asp_Types.ConnectionId conn_id)
470runs on IPA_Emulation_CT {
471 var IPA_Send ipa_tx := valueof(t_IPA_Send(conn_id, IPAC_PROTO_CCM, enc_PDU_IPA_CCM(ccm)));
Harald Welted86cdc62017-11-22 00:45:07 +0100472 log("CCM Tx:", ccm);
473 IPA_PORT.send(ipa_tx);
474}
475
476template PDU_IPA_CCM ts_IPA_PONG := {
477 msg_type := IPAC_MSGT_PONG,
478 u := omit
479}
480
481template PDU_IPA_CCM ts_IPA_ACK := {
482 msg_type := IPAC_MSGT_ID_ACK,
483 u := omit
484}
485
Harald Welteb3414b22017-11-23 18:22:10 +0100486template PDU_IPA_CCM ts_IPA_ID_GET := {
487 msg_type := IPAC_MSGT_ID_GET,
488 u := {
489 get := {
Vadim Yanitskiy40ee56c2020-05-24 20:51:24 +0700490 { 1, IPAC_IDTAG_UNITNAME },
491 { 1, IPAC_IDTAG_UNITID }
Harald Welteb3414b22017-11-23 18:22:10 +0100492 }
493 }
494}
495
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700496template PDU_IPA_CCM tr_IPA_ID_RESP := {
497 msg_type := IPAC_MSGT_ID_RESP,
498 u := {
499 resp := {
500 { ?, IPAC_IDTAG_UNITNAME, ? },
501 { ?, IPAC_IDTAG_UNITID, ? }
502 }
503 }
504}
505
Harald Welted86cdc62017-11-22 00:45:07 +0100506/* receive IPA CCM message */
Harald Welte2d86aff2018-04-17 11:23:04 +0200507private function f_ccm_rx_client(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
Harald Welted86cdc62017-11-22 00:45:07 +0100508 select (ccm.msg_type) {
509 case (IPAC_MSGT_PING) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700510 f_ccm_tx(valueof(ts_IPA_PONG), g_self_conn_id);
Harald Welted86cdc62017-11-22 00:45:07 +0100511 }
512 case (IPAC_MSGT_ID_ACK) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700513 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK, g_self_conn_id));
Harald Welted86cdc62017-11-22 00:45:07 +0100514 }
515 case (IPAC_MSGT_ID_GET) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700516 f_ccm_tx(f_ccm_make_id_resp(ccm), g_self_conn_id);
Harald Welted86cdc62017-11-22 00:45:07 +0100517 }
Harald Welte2d86aff2018-04-17 11:23:04 +0200518 case else {
519 log("Unknown/unsupported IPA CCM message type", ccm);
520 }
521 }
522}
523
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700524private function f_ccm_rx_server(PDU_IPA_CCM ccm, IPL4asp_Types.ConnectionId conn_id)
525runs on IPA_Emulation_CT {
Harald Welte2d86aff2018-04-17 11:23:04 +0200526 select (ccm.msg_type) {
527 case (IPAC_MSGT_PING) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700528 f_ccm_tx(valueof(ts_IPA_PONG), conn_id);
Harald Welte2d86aff2018-04-17 11:23:04 +0200529 }
530 case (IPAC_MSGT_ID_ACK) {
531 /* the IPA server should at some point receive an ID_ACK from the client,
532 * in case of RSL/OML from nanoBTS, this is actually the first message after
533 * the TCP connection is established. Other implementations may differ.
534 * We currently ignore it completely - but actually we should make sure that
535 * one ID_ACK is received by the server at some point */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700536 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK, conn_id));
Harald Welte2d86aff2018-04-17 11:23:04 +0200537 }
Harald Welte3bc387f2018-02-21 12:18:46 +0100538 case (IPAC_MSGT_ID_RESP) {
539 log("IPA ID RESP: ", ccm.u.resp);
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700540
541 /* make sure that the response contains all fields we requested */
542 if (not match(ccm, tr_IPA_ID_RESP)) {
543 log("IPA identity response ", ccm.u.resp, " mismatch");
544 return;
545 }
546
547 /* forward to the upper layers, so they can map conn_id with unit_id */
548 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_ID_RESP, conn_id, ccm.u.resp));
Harald Welte2d86aff2018-04-17 11:23:04 +0200549 /* acknowledge any identity that the client may have sent */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700550 f_ccm_tx(valueof(ts_IPA_ACK), conn_id);
Harald Welte3bc387f2018-02-21 12:18:46 +0100551 }
Harald Welted86cdc62017-11-22 00:45:07 +0100552 case else {
553 log("Unknown/unsupported IPA CCM message type", ccm);
554 }
555 }
556}
557
Harald Weltec76f29f2017-11-22 12:46:46 +0100558private function f_to_asp(IPA_RecvFrom ipa_rx) return ASP_IPA_Unitdata {
559 var ASP_IPA_Unitdata ret := {
560 streamId := ipa_rx.streamId,
Harald Welte2a8f8472017-11-23 21:11:34 +0100561 streamIdExt := ipa_rx.streamIdExt,
Harald Weltec76f29f2017-11-22 12:46:46 +0100562 payload := ipa_rx.msg
563 }
564 return ret;
565}
566
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100567private function f_from_asp(IPL4asp_Types.ConnectionId connId, ASP_IPA_Unitdata ipa_tx) return IPA_Send {
Harald Weltec82eef42017-11-24 20:40:12 +0100568 var IPA_Send ret := valueof(t_IPA_Send(connId, ipa_tx.streamId, ipa_tx.payload,
569 ipa_tx.streamIdExt));
Harald Weltec76f29f2017-11-22 12:46:46 +0100570 return ret;
571}
Harald Welted86cdc62017-11-22 00:45:07 +0100572
Harald Weltedf277252018-02-20 15:49:30 +0100573#ifdef IPA_EMULATION_RSL
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100574private function f_from_rsl(IPL4asp_Types.ConnectionId connId, ASP_RSL_Unitdata rsl_tx) return IPA_Send {
Harald Welte0d846a72017-12-07 17:58:28 +0100575 var octetstring payload := enc_RSL_Message(rsl_tx.rsl);
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700576
577 /* ASP_RSL_Unitdata may (optionally) contain TCP/IP connection ID */
578 if (rsl_tx.conn_id != omit) {
579 connId := rsl_tx.conn_id;
580 }
581
582 return valueof(t_IPA_Send(connId, rsl_tx.streamId, payload));
Harald Welte0d846a72017-12-07 17:58:28 +0100583}
Harald Weltedf277252018-02-20 15:49:30 +0100584#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100585
Harald Weltec6826662019-02-06 22:26:46 +0100586#ifdef IPA_EMULATION_OML
587private function f_from_oml(IPL4asp_Types.ConnectionId connId, OML_PDU oml_tx) return IPA_Send {
588 var octetstring payload := enc_OML_PDU(oml_tx);
589 var IPA_Send ret := valueof(t_IPA_Send(connId, IPAC_PROTO_OML, payload));
590 return ret;
591}
592#endif
593
Harald Weltebdb63702017-12-09 01:15:44 +0100594/* main function to use for a client-side IPA implementation */
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100595function main_client(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
596 charstring local_host, IPL4asp_Types.PortNumber local_port,
Harald Welte2d86aff2018-04-17 11:23:04 +0200597 IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars,
598 boolean ccm_enabled := true) runs on IPA_Emulation_CT {
Harald Welteb3414b22017-11-23 18:22:10 +0100599 g_mode := IPA_MODE_CLIENT;
Harald Welte2d86aff2018-04-17 11:23:04 +0200600 g_ccm_enabled := ccm_enabled;
Harald Weltee09921f2017-12-07 17:49:00 +0100601 f_connect(remote_host, remote_port, local_host, local_port, ccm_pars);
Harald Welte2d86aff2018-04-17 11:23:04 +0200602 if (g_ccm_enabled) {
603 /* we're a client: Send ID_ACK immediately after connect */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700604 f_ccm_tx(valueof(ts_IPA_ACK), g_self_conn_id);
Harald Welte2d86aff2018-04-17 11:23:04 +0200605 }
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700606 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_UP, g_self_conn_id));
Harald Welteb3414b22017-11-23 18:22:10 +0100607 ScanEvents();
608}
609
Harald Weltebdb63702017-12-09 01:15:44 +0100610/* main function to use for a server-side IPA implementation */
Harald Welte2d86aff2018-04-17 11:23:04 +0200611function main_server(charstring local_host, IPL4asp_Types.PortNumber local_port,
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200612 boolean ccm_enabled := true,
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100613 IpaInitBehavior init_behavior := IPA_INIT_SEND_IPA_ID_GET,
614 boolean server_stop_on_ipa_ev_down := true)
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200615runs on IPA_Emulation_CT {
Harald Welteb3414b22017-11-23 18:22:10 +0100616 g_mode := IPA_MODE_SERVER;
Harald Welte2d86aff2018-04-17 11:23:04 +0200617 g_ccm_enabled := ccm_enabled;
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200618 g_init_behavior := init_behavior;
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100619 g_server_stop_on_ipa_ev_down := server_stop_on_ipa_ev_down;
Harald Welteb3414b22017-11-23 18:22:10 +0100620 f_bind(local_host, local_port);
621 ScanEvents();
622}
623
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200624#ifdef IPA_EMULATION_CTRL
Harald Weltedf277252018-02-20 15:49:30 +0100625private function f_ctrl_to_user(octetstring msg) runs on IPA_Emulation_CT {
626 var charstring msg_ch := oct2char(msg);
627 IPA_CTRL_PORT.send(dec_CtrlMessage(msg_ch));
628}
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200629#endif
Harald Weltedf277252018-02-20 15:49:30 +0100630
631#ifdef IPA_EMULATION_GSUP
632private function f_gsup_to_user(octetstring msg) runs on IPA_Emulation_CT {
633 var GSUP_PDU gsup := dec_GSUP_PDU(msg);
634 f_gsup_postprocess_decoded(gsup);
635 IPA_GSUP_PORT.send(gsup);
636}
637#endif
638
Harald Welte7460a722018-10-10 12:28:27 +0200639#ifdef IPA_EMULATION_RSPRO
640private function f_rspro_to_user(octetstring msg) runs on IPA_Emulation_CT {
641 var RsproPDU rspro := dec_RsproPDU(msg);
642 IPA_RSPRO_PORT.send(rspro);
643}
644#endif
645
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200646#ifdef IPA_EMULATION_OSMO_PCU
647private function f_osmo_pcu_to_user(octetstring msg) runs on IPA_Emulation_CT {
648 var PCUIF_Message pcuif_msg := dec_PCUIF_Message(msg);
649 IPA_OSMO_PCU_PORT.send(pcuif_msg);
650}
651#endif
652
Harald Weltedf277252018-02-20 15:49:30 +0100653#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100654private function f_mgcp_to_user(octetstring msg) runs on IPA_Emulation_CT {
655 var charstring msg_ch := oct2char(msg);
656 if (g_is_bsc_mgw) {
657 log("============");
658 log(msg_ch);
659 IPA_MGCP_PORT.send(dec_MgcpCommand(msg_ch));
660 } else {
661 IPA_MGCP_PORT.send(dec_MgcpResponse(msg_ch));
662 }
663}
664
Harald Welte92632e12017-11-25 02:31:20 +0100665private function f_mgcp_to_ud(octetstring payload) runs on IPA_Emulation_CT return ASP_IPA_Unitdata {
666 if (mp_ipa_mgcp_uses_osmo_ext) {
667 return valueof(t_ASP_IPA_UD(IPAC_PROTO_MGCP_OLD, payload));
668 } else {
669 return valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_MGCP));
670 }
671}
Harald Weltedf277252018-02-20 15:49:30 +0100672#endif
Harald Welte92632e12017-11-25 02:31:20 +0100673
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700674/* Resolve TCP/IP connection identifier depending on g_mode */
675private function f_ipa_conn_id() runs on IPA_Emulation_CT
676return IPL4asp_Types.ConnectionId {
677 var IPL4asp_Types.ConnectionId conn_id;
678
679 select (g_mode) {
680 case (IPA_MODE_CLIENT) { conn_id := g_self_conn_id; }
681 case (IPA_MODE_SERVER) { conn_id := g_last_conn_id; }
682 case else {
683 setverdict(fail, "Unknown mode");
684 mtc.stop;
685 }
686 }
687
688 if (conn_id == -1) { /* Just to be sure */
689 setverdict(fail, "Connection is not established");
690 mtc.stop;
691 }
692
693 return conn_id;
694}
695
Harald Weltebdb63702017-12-09 01:15:44 +0100696/* main loop function for both client and server. 'thread' of the component */
Harald Welteb3414b22017-11-23 18:22:10 +0100697private function ScanEvents() runs on IPA_Emulation_CT {
Harald Welted86cdc62017-11-22 00:45:07 +0100698 var IPA_RecvFrom ipa_rx;
Harald Welteb3414b22017-11-23 18:22:10 +0100699 var ASP_Event asp_evt;
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100700 var Socket_API_Definitions.PortEvent port_evt;
Harald Weltedf277252018-02-20 15:49:30 +0100701 var octetstring payload;
Harald Weltedf277252018-02-20 15:49:30 +0100702 var ASP_IPA_Unitdata ipa_ud;
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100703 var IPL4asp_Types.Result res;
Harald Welte3286eb32019-08-18 19:36:10 +0200704#ifdef IPA_EMULATION_CTRL
705 var CtrlMessage ctrl_msg;
706#endif
Harald Weltedf277252018-02-20 15:49:30 +0100707#ifdef IPA_EMULATION_SCCP
708 var ASP_MTP3_TRANSFERreq mtp_req;
709#endif
710#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100711 var MgcpCommand mgcp_cmd;
712 var MgcpResponse mgcp_rsp;
Harald Weltedf277252018-02-20 15:49:30 +0100713#endif
714#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100715 var GSUP_PDU gsup_msg;
Harald Weltedf277252018-02-20 15:49:30 +0100716#endif
717#ifdef IPA_EMULATION_RSL
Harald Welte0d846a72017-12-07 17:58:28 +0100718 var ASP_RSL_Unitdata rsl;
Harald Weltedf277252018-02-20 15:49:30 +0100719#endif
Harald Weltec6826662019-02-06 22:26:46 +0100720#ifdef IPA_EMULATION_OML
721 var OML_PDU oml;
722#endif
Harald Welte7460a722018-10-10 12:28:27 +0200723#ifdef IPA_EMULATION_RSPRO
724 var RsproPDU rspro;
725#endif
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200726#ifdef IPA_EMULATION_OSMO_PCU
727 var PCUIF_Message pcu;
728#endif
Harald Welted86cdc62017-11-22 00:45:07 +0100729
Harald Welte3e6ad892017-12-12 14:39:46 +0100730 /* Set function for dissecting the binary */
731 var f_IPL4_getMsgLen vl_f := refers(f_IPL4_fixedMsgLen);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700732 IPA_CodecPort_CtrlFunct.f_IPL4_setGetMsgLen(IPA_PORT, g_self_conn_id, vl_f, {0, 2, 3, 1, 0});
Harald Welte3e6ad892017-12-12 14:39:46 +0100733
Harald Welted86cdc62017-11-22 00:45:07 +0100734 while (true) {
735 alt {
736 /* Received IPA -> up into SCCP stack */
Harald Welte2d86aff2018-04-17 11:23:04 +0200737 [g_ccm_enabled] IPA_PORT.receive(IPA_RecvFrom:{?,IPAC_PROTO_CCM,omit,?}) -> value ipa_rx {
738 var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg);
739 log("CCM Rx:", ccm);
740 select (g_mode) {
741 case (IPA_MODE_CLIENT) {
742 f_ccm_rx_client(ccm);
743 }
744 case (IPA_MODE_SERVER) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700745 f_ccm_rx_server(ccm, ipa_rx.connId);
Harald Welte2d86aff2018-04-17 11:23:04 +0200746 }
747 case else {
748 setverdict(fail, "Unknown mode");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200749 mtc.stop;
Harald Welte2d86aff2018-04-17 11:23:04 +0200750 }
Harald Weltedf277252018-02-20 15:49:30 +0100751 }
Harald Welte2d86aff2018-04-17 11:23:04 +0200752 }
753 [] IPA_PORT.receive(IPA_RecvFrom:?) -> value ipa_rx {
754 select (ipa_rx.streamId) {
Harald Weltedf277252018-02-20 15:49:30 +0100755#ifdef IPA_EMULATION_SCCP
756 case (IPAC_PROTO_SCCP) {
Harald Welted86cdc62017-11-22 00:45:07 +0100757 var ASP_MTP3_TRANSFERind mtp;
758 mtp := valueof(ts_MTP3_XFER_ind(0, ipa_rx.msg));
759 MTP3_SP_PORT.send(mtp);
Harald Weltedf277252018-02-20 15:49:30 +0100760 }
761#endif
762#ifdef IPA_EMULATION_MGCP
763 case (IPAC_PROTO_MGCP_OLD) {
Harald Weltec82eef42017-11-24 20:40:12 +0100764 f_mgcp_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100765 }
766#endif
767#ifdef IPA_EMULATION_RSL
768 case (t_IpaSidRSL) {
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700769 rsl := valueof(ts_ASP_RSL_UD(
770 rsl := dec_RSL_Message(ipa_rx.msg),
771 sid := ipa_rx.streamId,
772 conn_id := ipa_rx.connId
773 ));
Harald Welte0d846a72017-12-07 17:58:28 +0100774 IPA_RSL_PORT.send(rsl);
Harald Weltedf277252018-02-20 15:49:30 +0100775 }
776#endif
Harald Weltec6826662019-02-06 22:26:46 +0100777#ifdef IPA_EMULATION_OML
778 case (IPAC_PROTO_OML) {
779 oml := dec_OML_PDU(ipa_rx.msg)
780 IPA_OML_PORT.send(oml);
781 }
782#endif
Harald Weltedf277252018-02-20 15:49:30 +0100783 case (IPAC_PROTO_OSMO) {
Harald Weltec82eef42017-11-24 20:40:12 +0100784 select (ipa_rx.streamIdExt) {
Harald Weltedf277252018-02-20 15:49:30 +0100785#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100786 case (IPAC_PROTO_EXT_MGCP) {
787 f_mgcp_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100788 }
789#endif
Harald Welte3286eb32019-08-18 19:36:10 +0200790#ifdef IPA_EMULATION_CTRL
Harald Weltedf277252018-02-20 15:49:30 +0100791 case (IPAC_PROTO_EXT_CTRL) {
Harald Weltea76c4bb2017-12-09 02:06:07 +0100792 f_ctrl_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100793 }
Harald Welte3286eb32019-08-18 19:36:10 +0200794#endif
Harald Weltedf277252018-02-20 15:49:30 +0100795#ifdef IPA_EMULATION_GSUP
796 case (IPAC_PROTO_EXT_GSUP) {
Harald Weltedf327232017-12-28 22:51:51 +0100797 f_gsup_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100798 }
799#endif
Harald Welte7460a722018-10-10 12:28:27 +0200800#ifdef IPA_EMULATION_RSPRO
801 case (IPAC_PROTO_EXT_RSPRO) {
802 f_rspro_to_user(ipa_rx.msg);
803 }
804#endif
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200805#ifdef IPA_EMULATION_OSMO_PCU
806 case (IPAC_PROTO_EXT_OSMO_PCU) {
807 f_osmo_pcu_to_user(ipa_rx.msg);
808 }
809#endif
Harald Weltedf277252018-02-20 15:49:30 +0100810 case else {
Harald Weltec82eef42017-11-24 20:40:12 +0100811 IPA_SP_PORT.send(f_to_asp(ipa_rx));
812 }
Harald Welted86cdc62017-11-22 00:45:07 +0100813 }
Harald Weltedf277252018-02-20 15:49:30 +0100814 }
815 case else {
Harald Weltec76f29f2017-11-22 12:46:46 +0100816 IPA_SP_PORT.send(f_to_asp(ipa_rx));
Harald Welted86cdc62017-11-22 00:45:07 +0100817 }
818 }
819 }
820
Harald Welteb3414b22017-11-23 18:22:10 +0100821 /* server only */
822 [] IPA_PORT.receive(ASP_Event:{connOpened:=?}) -> value asp_evt {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700823 g_last_conn_id := asp_evt.connOpened.connId;
824 log("Established a new IPA connection (conn_id=", g_last_conn_id, ")");
825
826 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_UP, g_last_conn_id));
Harald Welte2d86aff2018-04-17 11:23:04 +0200827 if (g_mode == IPA_MODE_SERVER and g_ccm_enabled) {
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200828 select (g_init_behavior) {
829 case (IPA_INIT_SEND_IPA_ID_GET) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700830 f_ccm_tx(valueof(ts_IPA_ID_GET), g_last_conn_id);
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200831 }
832 case (IPA_INIT_SEND_IPA_ID_ACK) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700833 f_ccm_tx(valueof(ts_IPA_ACK), g_last_conn_id);
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200834 }
835 }
Harald Welteb3414b22017-11-23 18:22:10 +0100836 }
837 }
838
839 [] IPA_PORT.receive(ASP_Event:{connClosed:=?}) -> value asp_evt {
840 log("IPA: Closed");
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700841 g_self_conn_id := -1;
842 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_DOWN, asp_evt.connClosed.connId));
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100843 if (g_mode != IPA_MODE_SERVER or g_server_stop_on_ipa_ev_down) {
844 self.stop;
845 }
Harald Welteb3414b22017-11-23 18:22:10 +0100846 }
847
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100848 [] IPA_PORT.receive(Socket_API_Definitions.PortEvent:{result:={errorCode:=ERROR_SOCKET, connId:=?, os_error_code:=?, os_error_text:=?}}) -> value port_evt {
849 log("PortEvent: ERROR_SOCKET: ", port_evt);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700850 g_self_conn_id := -1;
851 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_DOWN, port_evt.result.connId));
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100852 self.stop;
853 }
854
Harald Weltedf277252018-02-20 15:49:30 +0100855#ifdef IPA_EMULATION_SCCP
Harald Welted86cdc62017-11-22 00:45:07 +0100856 /* Received SCCP -> down into IPA */
857 [] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700858 var IPA_Send ipa_tx := valueof(t_IPA_Send(f_ipa_conn_id(), IPAC_PROTO_SCCP,
Harald Weltec82eef42017-11-24 20:40:12 +0100859 mtp_req.data));
Harald Welted86cdc62017-11-22 00:45:07 +0100860 IPA_PORT.send(ipa_tx);
861 }
Harald Weltedf277252018-02-20 15:49:30 +0100862#endif
Harald Weltec76f29f2017-11-22 12:46:46 +0100863
Harald Weltedf277252018-02-20 15:49:30 +0100864#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100865 /* Received MGCP -> down into IPA */
866 [] IPA_MGCP_PORT.receive(MgcpCommand:?) -> value mgcp_cmd {
Harald Welte92632e12017-11-25 02:31:20 +0100867 payload := char2oct(enc_MgcpCommand(mgcp_cmd));
868 ipa_ud := f_mgcp_to_ud(payload);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700869 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltec82eef42017-11-24 20:40:12 +0100870 }
871 [] IPA_MGCP_PORT.receive(MgcpResponse:?) -> value mgcp_rsp {
Harald Welte1dd8f372017-11-25 02:25:27 +0100872 payload := char2oct(enc_MgcpResponse(mgcp_rsp));
Harald Welte92632e12017-11-25 02:31:20 +0100873 ipa_ud := f_mgcp_to_ud(payload);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700874 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltec82eef42017-11-24 20:40:12 +0100875 }
Harald Weltedf277252018-02-20 15:49:30 +0100876#endif
Harald Weltec82eef42017-11-24 20:40:12 +0100877
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200878#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +0100879 [] IPA_CTRL_PORT.receive(CtrlMessage:?) -> value ctrl_msg {
880 payload := char2oct(enc_CtrlMessage(ctrl_msg));
881 ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_CTRL));
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700882 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltea76c4bb2017-12-09 02:06:07 +0100883 }
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200884#endif
Harald Weltea76c4bb2017-12-09 02:06:07 +0100885
Harald Weltedf277252018-02-20 15:49:30 +0100886#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100887 [] IPA_GSUP_PORT.receive(GSUP_PDU:?) -> value gsup_msg {
Harald Welte2f562b12018-01-24 20:52:38 +0100888 f_gsup_preprocess_encoded(gsup_msg);
Harald Weltedf327232017-12-28 22:51:51 +0100889 payload := enc_GSUP_PDU(gsup_msg);
890 ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_GSUP));
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700891 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltedf327232017-12-28 22:51:51 +0100892 }
Harald Weltedf277252018-02-20 15:49:30 +0100893#endif
Harald Weltedf327232017-12-28 22:51:51 +0100894
Harald Welte7460a722018-10-10 12:28:27 +0200895#ifdef IPA_EMULATION_RSPRO
896 [] IPA_RSPRO_PORT.receive(RsproPDU:?) -> value rspro {
897 payload := enc_RsproPDU(rspro);
898 ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_RSPRO));
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700899 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Welte7460a722018-10-10 12:28:27 +0200900 }
901#endif
902
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200903#ifdef IPA_EMULATION_OSMO_PCU
904 [] IPA_OSMO_PCU_PORT.receive(PCUIF_Message:?) -> value pcu {
905 payload := enc_PCUIF_Message(pcu);
906 ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_OSMO_PCU));
907 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
908 }
909#endif
910
Harald Weltedf277252018-02-20 15:49:30 +0100911#ifdef IPA_EMULATION_RSL
Harald Welte0d846a72017-12-07 17:58:28 +0100912 /* Received RSL -> down into IPA */
913 [] IPA_RSL_PORT.receive(ASP_RSL_Unitdata:?) -> value rsl {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700914 IPA_PORT.send(f_from_rsl(f_ipa_conn_id(), rsl));
Harald Welte0d846a72017-12-07 17:58:28 +0100915 }
Harald Weltedf277252018-02-20 15:49:30 +0100916#endif
Harald Weltec6826662019-02-06 22:26:46 +0100917#ifdef IPA_EMULATION_OML
918 /* Received OML -> down into IPA */
919 [] IPA_OML_PORT.receive(OML_PDU:?) -> value oml {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700920 IPA_PORT.send(f_from_oml(f_ipa_conn_id(), oml));
Harald Weltec6826662019-02-06 22:26:46 +0100921 }
922 [] IPA_OML_PORT.receive(octetstring:?) -> value payload {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700923 IPA_PORT.send(t_IPA_Send(f_ipa_conn_id(), IPAC_PROTO_OML, payload));
Harald Weltec6826662019-02-06 22:26:46 +0100924 }
925#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100926 /* Received MISC (OML/CTRL) -> down into IPA */
Harald Weltec76f29f2017-11-22 12:46:46 +0100927 [] IPA_SP_PORT.receive(ASP_IPA_Unitdata: ?) -> value ipa_ud {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700928 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltec76f29f2017-11-22 12:46:46 +0100929 }
930
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100931 /* Received call to configure/operate the component */
932 [] CFG_PORT.getcall(IPA_CFG_disconnect:{?}) {
933 res := f_close();
934 CFG_PORT.reply(IPA_CFG_disconnect:{res});
935 }
Harald Weltec76f29f2017-11-22 12:46:46 +0100936
Harald Welted86cdc62017-11-22 00:45:07 +0100937 }
938 }
939}
940
Harald Welte2e32e432018-05-24 20:00:00 +0200941/***********************************************************************
942 * IPA Event waiter component. Wait for ASP_IPA_EVENT_ID_ACK
943 ***********************************************************************/
944
945type component IPA_EventWaiter_CT {
946 port IPA_SP_PT IPA_SP_PORT;
947}
948
Vadim Yanitskiy61564be2020-05-18 20:44:14 +0700949function waiter_main(template ASP_IPA_Event wait_for := tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK))
Harald Welte2e32e432018-05-24 20:00:00 +0200950runs on IPA_EventWaiter_CT {
951
952 alt {
953 [] IPA_SP_PORT.receive(wait_for) {
954 setverdict(pass);
955 }
956 [] IPA_SP_PORT.receive { repeat; }
957 }
958}
959
960
Harald Welted86cdc62017-11-22 00:45:07 +0100961}