blob: 7a8e8d66c1bf1539310519fb59b6f3611011e657 [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;
Harald Weltedf277252018-02-20 15:49:30 +010047#endif
Harald Weltec82eef42017-11-24 20:40:12 +010048
Harald Welte7460a722018-10-10 12:28:27 +020049#ifdef IPA_EMULATION_RSPRO
50import from RSPRO all;
51import from RSPRO_Types all;
52#endif
53
Harald Welte3286eb32019-08-18 19:36:10 +020054#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +010055import from Osmocom_CTRL_Types all;
Harald Welte3286eb32019-08-18 19:36:10 +020056#endif
Harald Weltea76c4bb2017-12-09 02:06:07 +010057
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +020058#ifdef IPA_EMULATION_OSMO_PCU
59import from PCUIF_Types all;
60#endif
61
Harald Welted86cdc62017-11-22 00:45:07 +010062modulepar {
Harald Welte92632e12017-11-25 02:31:20 +010063 /* Use Osmocom extended IPA mux header */
64 boolean mp_ipa_mgcp_uses_osmo_ext := true;
Harald Welted86cdc62017-11-22 00:45:07 +010065}
Harald Welted86cdc62017-11-22 00:45:07 +010066
Harald Welteb3414b22017-11-23 18:22:10 +010067type enumerated IpaMode {
68 IPA_MODE_CLIENT,
69 IPA_MODE_SERVER
70}
71
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +020072type enumerated IpaInitBehavior {
73 IPA_INIT_SEND_IPA_ID_GET,
74 IPA_INIT_SEND_IPA_ID_ACK
75}
76
Harald Weltec76f29f2017-11-22 12:46:46 +010077type record ASP_IPA_Unitdata {
78 IpaStreamId streamId,
Harald Weltec82eef42017-11-24 20:40:12 +010079 IpaExtStreamId streamIdExt optional,
Harald Weltec76f29f2017-11-22 12:46:46 +010080 octetstring payload
81}
82
Vadim Yanitskiy8701b272020-05-18 20:17:25 +070083type enumerated ASP_IPA_EventType {
Harald Welte0d846a72017-12-07 17:58:28 +010084 ASP_IPA_EVENT_DOWN,
85 ASP_IPA_EVENT_UP,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +070086 ASP_IPA_EVENT_ID_RESP,
Harald Welte0d846a72017-12-07 17:58:28 +010087 ASP_IPA_EVENT_ID_ACK
88}
89
Harald Weltebdb63702017-12-09 01:15:44 +010090/* an event indicating us whether or not a connection is physically up or down,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +070091 * and whether we have received an ID_RESP or ID_ACK */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +070092type record ASP_IPA_Event {
93 ASP_IPA_EventType ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +070094 integer conn_id,
95
96 /* Presence of these fields depends on event type */
97 IpaCcmIdResp id_resp optional // ASP_IPA_EVENT_ID_RESP
Harald Welte0d846a72017-12-07 17:58:28 +010098}
99
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700100template (value) ASP_IPA_Event ts_ASP_IPA_EV(ASP_IPA_EventType ev_type, integer conn_id,
101 template (omit) IpaCcmIdResp id_resp := omit) := {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700102 ev_type := ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700103 conn_id := conn_id,
104 id_resp := id_resp
Vadim Yanitskiy61564be2020-05-18 20:44:14 +0700105}
106
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700107template ASP_IPA_Event tr_ASP_IPA_EV(template ASP_IPA_EventType ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700108 template integer conn_id := ?,
109 template IpaCcmIdResp id_resp := *) := {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700110 ev_type := ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700111 conn_id := conn_id,
112 id_resp := id_resp
Harald Welte0d846a72017-12-07 17:58:28 +0100113}
114
Harald Welte1dd8f372017-11-25 02:25:27 +0100115template ASP_IPA_Unitdata t_ASP_IPA_UD(IpaStreamId sid, octetstring pl,
116 template IpaExtStreamId esid := omit) := {
117 streamId := sid,
118 streamIdExt := esid,
119 payload := pl
120}
121
Harald Weltedf277252018-02-20 15:49:30 +0100122#ifdef IPA_EMULATION_RSL
Harald Weltebdb63702017-12-09 01:15:44 +0100123/* like ASP_IPA_Unitdata, but with RSL_Message abstract type instead of octetstring */
Harald Welte0d846a72017-12-07 17:58:28 +0100124type record ASP_RSL_Unitdata {
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700125 integer conn_id optional,
Harald Welte0d846a72017-12-07 17:58:28 +0100126 IpaStreamId streamId,
127 RSL_Message rsl
128};
129
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700130template (value) ASP_RSL_Unitdata ts_ASP_RSL_UD(template (value) RSL_Message rsl,
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700131 IpaStreamId sid := IPAC_PROTO_RSL_TRX0,
132 template (omit) integer conn_id := omit) := {
133 conn_id := conn_id,
Harald Welte0d846a72017-12-07 17:58:28 +0100134 streamId := sid,
Vadim Yanitskiy6b4856d2020-05-25 21:23:46 +0700135 rsl := rsl
Harald Welte0d846a72017-12-07 17:58:28 +0100136}
137
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700138template ASP_RSL_Unitdata tr_ASP_RSL_UD(template (present) RSL_Message rsl,
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700139 template IpaStreamId sid := IPAC_PROTO_RSL_TRX0,
140 template integer conn_id := *) := {
141 conn_id := conn_id,
Harald Welte7ae019e2017-12-09 00:54:15 +0100142 streamId := sid,
143 rsl := rsl
144}
145
Harald Welte0d846a72017-12-07 17:58:28 +0100146template IpaStreamId t_IpaSidRSL := ( IPAC_PROTO_RSL_TRX0, IPAC_PROTO_RSL_TRX1,
147 IPAC_PROTO_RSL_TRX2, IPAC_PROTO_RSL_TRX3 );
Harald Weltedf277252018-02-20 15:49:30 +0100148#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100149
Harald Weltec6826662019-02-06 22:26:46 +0100150
Harald Weltebdb63702017-12-09 01:15:44 +0100151/* Client port for general IPA messages, not further decoded */
Harald Weltec76f29f2017-11-22 12:46:46 +0100152type port IPA_SP_PT message {
Harald Welte0d846a72017-12-07 17:58:28 +0100153 inout ASP_IPA_Unitdata, ASP_IPA_Event;
Harald Weltec76f29f2017-11-22 12:46:46 +0100154} with { extension "internal" }
155
Harald Weltedf277252018-02-20 15:49:30 +0100156#ifdef IPA_EMULATION_MGCP
Harald Weltebdb63702017-12-09 01:15:44 +0100157/* Client port for MGCP inside IPA */
Harald Weltec82eef42017-11-24 20:40:12 +0100158type port IPA_MGCP_PT message {
159 inout MgcpCommand, MgcpResponse;
160} with { extension "internal" }
Harald Weltedf277252018-02-20 15:49:30 +0100161#endif
Harald Weltec82eef42017-11-24 20:40:12 +0100162
Harald Weltedf277252018-02-20 15:49:30 +0100163#ifdef IPA_EMULATION_RSL
Harald Weltebdb63702017-12-09 01:15:44 +0100164/* Client port for A-bis RSL inside IPA */
Harald Welte0d846a72017-12-07 17:58:28 +0100165type port IPA_RSL_PT message {
166 inout ASP_RSL_Unitdata, ASP_IPA_Event;
167} with { extension "internal" }
Harald Weltedf277252018-02-20 15:49:30 +0100168#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100169
Harald Weltec6826662019-02-06 22:26:46 +0100170#ifdef IPA_EMULATION_OML
171/* Client port for A-bis OML inside IPA */
172type port IPA_OML_PT message {
173 inout OML_PDU, octetstring, ASP_IPA_Event;
174} with { extension "internal" }
175#endif
176
Harald Welte3286eb32019-08-18 19:36:10 +0200177#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +0100178/* Client port for CTRL inside IPA */
179type port IPA_CTRL_PT message {
180 inout CtrlMessage, ASP_IPA_Event;
181} with { extension "internal" }
Harald Welte3286eb32019-08-18 19:36:10 +0200182#endif
Harald Weltea76c4bb2017-12-09 02:06:07 +0100183
Harald Weltedf277252018-02-20 15:49:30 +0100184#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100185/* Client port for CTRL inside IPA */
186type port IPA_GSUP_PT message {
187 inout GSUP_PDU, ASP_IPA_Event;
188} with { extension "internal" }
Harald Weltedf277252018-02-20 15:49:30 +0100189#endif
Harald Weltedf327232017-12-28 22:51:51 +0100190
Harald Welte7460a722018-10-10 12:28:27 +0200191#ifdef IPA_EMULATION_RSPRO
192type port IPA_RSPRO_PT message {
193 inout RsproPDU, ASP_IPA_Event;
194} with { extension "internal" }
195#endif
196
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200197#ifdef IPA_EMULATION_OSMO_PCU
198/* Client port for Osmocom PCU extension inside IPA */
199type port IPA_OSMO_PCU_PT message {
200 inout PCUIF_Message, ASP_IPA_Event;
201} with { extension "internal" }
202#endif
Harald Welte7460a722018-10-10 12:28:27 +0200203
204
Harald Weltedf327232017-12-28 22:51:51 +0100205
Harald Welted86cdc62017-11-22 00:45:07 +0100206type component IPA_Emulation_CT {
207 /* down-facing port to IPA codec port */
208 port IPA_CODEC_PT IPA_PORT;
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100209 /* Down facing port to configure the component */
210 port IPA_CFG_PT CFG_PORT;
211
Harald Weltedf277252018-02-20 15:49:30 +0100212#ifdef IPA_EMULATION_SCCP
Harald Welted86cdc62017-11-22 00:45:07 +0100213 /* up-facing port to SCCP */
214 port MTP3asp_SP_PT MTP3_SP_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100215#endif
216#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100217 /* up-facing port for MGCP */
218 port IPA_MGCP_PT IPA_MGCP_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100219#endif
220#ifdef IPA_EMULATION_RSL
Harald Welte0d846a72017-12-07 17:58:28 +0100221 /* up-facing port for RSL */
222 port IPA_RSL_PT IPA_RSL_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100223#endif
Harald Weltec6826662019-02-06 22:26:46 +0100224#ifdef IPA_EMULATION_OML
225 /* up-facing port for OML */
226 port IPA_OML_PT IPA_OML_PORT;
227#endif
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200228#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +0100229 /* up-facing port for CTRL */
230 port IPA_CTRL_PT IPA_CTRL_PORT;
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200231#endif
Harald Weltedf277252018-02-20 15:49:30 +0100232#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100233 /* up-facing port for GSUP */
234 port IPA_GSUP_PT IPA_GSUP_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100235#endif
Harald Welte7460a722018-10-10 12:28:27 +0200236#ifdef IPA_EMULATION_RSPRO
237 /* up-facing port for RSPRO */
238 port IPA_RSPRO_PT IPA_RSPRO_PORT;
239#endif
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200240#ifdef IPA_EMULATION_OSMO_PCU
241 /* up-facing port for RSPRO */
242 port IPA_OSMO_PCU_PT IPA_OSMO_PCU_PORT;
243#endif
Harald Weltedf327232017-12-28 22:51:51 +0100244
Harald Weltec76f29f2017-11-22 12:46:46 +0100245 /* up-facing port for other streams */
246 port IPA_SP_PT IPA_SP_PORT;
Harald Welted86cdc62017-11-22 00:45:07 +0100247
248 var boolean g_initialized := false;
Harald Weltec82eef42017-11-24 20:40:12 +0100249 /* Are we a BSC/MGW (truel) or MSC (false) */
250 var boolean g_is_bsc_mgw;
Harald Welteb3414b22017-11-23 18:22:10 +0100251
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700252 /* Connection identifier of the client / server itself */
253 var IPL4asp_Types.ConnectionId g_self_conn_id := -1;
254 /* Connection identifier of the last connected client (server only) */
255 var IPL4asp_Types.ConnectionId g_last_conn_id := -1;
256
Harald Welteb3414b22017-11-23 18:22:10 +0100257 var IpaMode g_mode;
Harald Welte2d86aff2018-04-17 11:23:04 +0200258 var boolean g_ccm_enabled;
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200259 var IpaInitBehavior g_init_behavior;
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100260 /* Shall we stop the component once the client disconnects, or keep
261 * running to let next user in ? */
262 var boolean g_server_stop_on_ipa_ev_down := true;
Harald Weltee09921f2017-12-07 17:49:00 +0100263 var IPA_CCM_Parameters g_ccm_pars := c_IPA_default_ccm_pars;
Harald Welted86cdc62017-11-22 00:45:07 +0100264}
265
Harald Weltee21096d2017-12-04 20:45:12 +0100266type record IPA_CCM_Parameters {
267 charstring ser_nr optional,
268 charstring name optional,
269 charstring location1 optional,
270 charstring location2 optional,
271 charstring equip_version optional,
272 charstring sw_version optional,
273 charstring ip_addr optional,
274 charstring mac_addr optional,
275 charstring unit_id optional,
276 charstring osmo_rand optional
277}
278
Harald Weltee09921f2017-12-07 17:49:00 +0100279const IPA_CCM_Parameters c_IPA_default_ccm_pars := {
280 ser_nr := "",
Harald Weltee21096d2017-12-04 20:45:12 +0100281 name := "mahlzeit",
Harald Weltee09921f2017-12-07 17:49:00 +0100282 location1 := "",
283 location2 := "",
284 equip_version := "",
285 sw_version := "",
286 ip_addr := "",
287 mac_addr := "",
Harald Weltee21096d2017-12-04 20:45:12 +0100288 unit_id := "0/1/2",
Harald Weltee09921f2017-12-07 17:49:00 +0100289 osmo_rand := ""
Harald Weltee21096d2017-12-04 20:45:12 +0100290};
291
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100292signature IPA_CFG_disconnect(inout IPL4asp_Types.Result res);
293type port IPA_CFG_PT procedure {
294 inout IPA_CFG_disconnect;
295} with { extension "internal" };
296
297function f_ipa_cfg_disconnect(IPA_CFG_PT pt, inout IPL4asp_Types.Result res) {
298 pt.call(IPA_CFG_disconnect:{res}) {
299 [] pt.getreply(IPA_CFG_disconnect:{?}) -> param (res) {};
300 }
301}
302
Harald Weltebdb63702017-12-09 01:15:44 +0100303/* Function to use to connect as client to a remote IPA Server */
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100304function f_connect(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
305 charstring local_host, IPL4asp_Types.PortNumber local_port,
Harald Weltee09921f2017-12-07 17:49:00 +0100306 IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars) runs on IPA_Emulation_CT {
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100307 var IPL4asp_Types.Result res;
Harald Welted86cdc62017-11-22 00:45:07 +0100308 res := IPA_CodecPort_CtrlFunct.f_IPL4_connect(IPA_PORT, remote_host, remote_port,
309 local_host, local_port, 0, { tcp:={} });
Harald Welte9220f632018-05-23 20:27:02 +0200310 if (not ispresent(res.connId)) {
Stefan Sperling6a90be42018-08-31 15:05:39 +0200311 setverdict(fail, "Could not connect IPA socket from ", local_host, " port ", local_port,
312 " to ", remote_host, " port ", remote_port, "; check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200313 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200314 }
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700315 g_self_conn_id := res.connId;
Harald Weltee21096d2017-12-04 20:45:12 +0100316 g_ccm_pars := ccm_pars;
Harald Weltec82eef42017-11-24 20:40:12 +0100317 g_is_bsc_mgw := true;
Harald Welted86cdc62017-11-22 00:45:07 +0100318}
319
Harald Weltebdb63702017-12-09 01:15:44 +0100320/* Function to use to bind to a local port as IPA server, accepting remote clients */
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100321function f_bind(charstring local_host, IPL4asp_Types.PortNumber local_port,
Harald Weltee09921f2017-12-07 17:49:00 +0100322 IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars) runs on IPA_Emulation_CT {
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100323 var IPL4asp_Types.Result res;
Pau Espin Pedrol76ba5412019-06-10 11:00:33 +0200324 res := IPA_CodecPort_CtrlFunct.f_IPL4_listen(IPA_PORT,
Harald Welteb3414b22017-11-23 18:22:10 +0100325 local_host, local_port, { tcp:={} });
Harald Welte9220f632018-05-23 20:27:02 +0200326 if (not ispresent(res.connId)) {
Maxb7aae8b2019-03-11 15:22:02 +0100327 setverdict(fail, "Could not listen IPA socket ", local_host, ":", local_port, ", check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200328 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200329 }
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700330 g_self_conn_id := res.connId;
Harald Weltee21096d2017-12-04 20:45:12 +0100331 g_ccm_pars := ccm_pars;
Harald Weltec82eef42017-11-24 20:40:12 +0100332 g_is_bsc_mgw := false;
Harald Welteb3414b22017-11-23 18:22:10 +0100333}
334
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100335private function f_close() runs on IPA_Emulation_CT return IPL4asp_Types.Result {
336 var IPL4asp_Types.Result res;
337 select (g_mode) {
338 case (IPA_MODE_CLIENT) {
339 res := IPA_CodecPort_CtrlFunct.f_IPL4_close(IPA_PORT, g_self_conn_id, {tcp := {}});
340 g_self_conn_id := -1;
341 }
342 case (IPA_MODE_SERVER) {
343 res := IPA_CodecPort_CtrlFunct.f_IPL4_close(IPA_PORT, g_last_conn_id, {tcp := {}});
344 g_last_conn_id := -1;
345 }
346 case else {
347 setverdict(fail, "Unknown mode");
348 mtc.stop;
349 }
350 }
351 return res;
352}
353
Harald Weltedf277252018-02-20 15:49:30 +0100354#ifdef IPA_EMULATION_SCCP
Harald Welted86cdc62017-11-22 00:45:07 +0100355template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := {
356 sio := { '10'B, '00'B, '0011'B },
357 opc := opc,
358 dpc := 0,
359 sls := 0,
360 data := data
361}
Harald Weltedf277252018-02-20 15:49:30 +0100362#endif
Harald Welted86cdc62017-11-22 00:45:07 +0100363
364
365private template IpaCcmRespPart t_IdRespPart(IpaCcmIdTag tag, charstring payload) := {
366 len := 0, /* overwritten by codec */
367 tag := tag,
Harald Welte95686e02018-08-02 15:05:43 +0200368 data := char2oct(payload) & '00'O
Harald Welted86cdc62017-11-22 00:45:07 +0100369}
370
Vadim Yanitskiy61564be2020-05-18 20:44:14 +0700371private function f_send_IPA_EVT(template (value) ASP_IPA_Event evt) runs on IPA_Emulation_CT {
Harald Welte2e32e432018-05-24 20:00:00 +0200372 if (IPA_SP_PORT.checkstate("Connected")) {
373 IPA_SP_PORT.send(evt);
374 }
Harald Weltedf277252018-02-20 15:49:30 +0100375#ifdef IPA_EMULATION_RSL
Harald Welte5819b552017-12-09 02:55:46 +0100376 if (IPA_RSL_PORT.checkstate("Connected")) {
377 IPA_RSL_PORT.send(evt);
378 }
Harald Weltedf277252018-02-20 15:49:30 +0100379#endif
Harald Weltec6826662019-02-06 22:26:46 +0100380#ifdef IPA_EMULATION_OML
381 if (IPA_OML_PORT.checkstate("Connected")) {
382 IPA_OML_PORT.send(evt);
383 }
384#endif
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200385#ifdef IPA_EMULATION_CTRL
Harald Welte5819b552017-12-09 02:55:46 +0100386 if (IPA_CTRL_PORT.checkstate("Connected")) {
387 IPA_CTRL_PORT.send(evt);
388 }
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200389#endif
Harald Weltedf277252018-02-20 15:49:30 +0100390#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100391 if (IPA_GSUP_PORT.checkstate("Connected")) {
392 IPA_GSUP_PORT.send(evt);
393 }
Harald Weltedf277252018-02-20 15:49:30 +0100394#endif
Harald Welte7460a722018-10-10 12:28:27 +0200395#ifdef IPA_EMULATION_RSPRO
396 if (IPA_RSPRO_PORT.checkstate("Connected")) {
397 IPA_RSPRO_PORT.send(evt);
398 }
399#endif
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200400#ifdef IPA_EMULATION_OSMO_PCU
401 if (IPA_OSMO_PCU_PORT.checkstate("Connected")) {
402 IPA_OSMO_PCU_PORT.send(evt);
403 }
404#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100405 /* FIXME: to other ports */
406}
407
Harald Welted86cdc62017-11-22 00:45:07 +0100408/* build IPA CCM ID RESP response from IPA CCM GET */
Harald Weltee21096d2017-12-04 20:45:12 +0100409private 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 +0100410 var integer i;
411 var PDU_IPA_CCM resp := {
412 msg_type := IPAC_MSGT_ID_RESP,
413 u := {
414 resp := {}
415 }
416 }
417
Pau Espin Pedrol8768f662023-10-12 17:55:56 +0200418 /* If no Tags were present in the received IPA message, .u = omit */
419 if (not ispresent(get.u)) {
420 return resp;
421 }
422
Harald Welted86cdc62017-11-22 00:45:07 +0100423 for (i := 0; i < sizeof(get.u.get); i := i + 1) {
424 var IpaCcmIdTag tag := get.u.get[i].tag;
425 var charstring foo;
426 select (tag) {
Harald Weltee21096d2017-12-04 20:45:12 +0100427 case (IPAC_IDTAG_SERNR) {
428 foo := g_ccm_pars.ser_nr;
Harald Welted86cdc62017-11-22 00:45:07 +0100429 }
430 case (IPAC_IDTAG_UNITNAME) {
Harald Weltee21096d2017-12-04 20:45:12 +0100431 foo := g_ccm_pars.name;
432 }
433 case (IPAC_IDTAG_LOCATION1) {
434 foo := g_ccm_pars.location1;
435 }
436 case (IPAC_IDTAG_LOCATION2) {
437 foo := g_ccm_pars.location2;
438 }
439 case (IPAC_IDTAG_EQUIPVERS) {
440 foo := g_ccm_pars.equip_version;
441 }
442 case (IPAC_IDTAG_SWVERSION) {
443 foo := g_ccm_pars.sw_version;
444 }
445 case (IPAC_IDTAG_IPADDR) {
446 foo := g_ccm_pars.ip_addr;
447 }
448 case (IPAC_IDTAG_MACADDR) {
449 foo := g_ccm_pars.mac_addr;
450 }
Vadim Yanitskiy44f0c482020-05-24 20:49:29 +0700451 case (IPAC_IDTAG_UNITID) {
Harald Weltee21096d2017-12-04 20:45:12 +0100452 foo := g_ccm_pars.unit_id;
453 }
454 case (IPAC_IDTAG_OSMO_RAND) {
455 foo := g_ccm_pars.osmo_rand;
Harald Welted86cdc62017-11-22 00:45:07 +0100456 }
457 case else {
Harald Weltee21096d2017-12-04 20:45:12 +0100458 foo := "unknown";
Harald Welted86cdc62017-11-22 00:45:07 +0100459 }
460 }
461 resp.u.resp[sizeof(resp.u.resp)] := valueof(t_IdRespPart(tag, foo));
462 }
463
464 return resp;
465}
466
467/* transmit IPA CCM message */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700468private function f_ccm_tx(PDU_IPA_CCM ccm, IPL4asp_Types.ConnectionId conn_id)
469runs on IPA_Emulation_CT {
470 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 +0100471 log("CCM Tx:", ccm);
472 IPA_PORT.send(ipa_tx);
473}
474
475template PDU_IPA_CCM ts_IPA_PONG := {
476 msg_type := IPAC_MSGT_PONG,
477 u := omit
478}
479
480template PDU_IPA_CCM ts_IPA_ACK := {
481 msg_type := IPAC_MSGT_ID_ACK,
482 u := omit
483}
484
Harald Welteb3414b22017-11-23 18:22:10 +0100485template PDU_IPA_CCM ts_IPA_ID_GET := {
486 msg_type := IPAC_MSGT_ID_GET,
487 u := {
488 get := {
Vadim Yanitskiy40ee56c2020-05-24 20:51:24 +0700489 { 1, IPAC_IDTAG_UNITNAME },
490 { 1, IPAC_IDTAG_UNITID }
Harald Welteb3414b22017-11-23 18:22:10 +0100491 }
492 }
493}
494
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700495template PDU_IPA_CCM tr_IPA_ID_RESP := {
496 msg_type := IPAC_MSGT_ID_RESP,
497 u := {
498 resp := {
499 { ?, IPAC_IDTAG_UNITNAME, ? },
500 { ?, IPAC_IDTAG_UNITID, ? }
501 }
502 }
503}
504
Harald Welted86cdc62017-11-22 00:45:07 +0100505/* receive IPA CCM message */
Harald Welte2d86aff2018-04-17 11:23:04 +0200506private function f_ccm_rx_client(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
Harald Welted86cdc62017-11-22 00:45:07 +0100507 select (ccm.msg_type) {
508 case (IPAC_MSGT_PING) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700509 f_ccm_tx(valueof(ts_IPA_PONG), g_self_conn_id);
Harald Welted86cdc62017-11-22 00:45:07 +0100510 }
511 case (IPAC_MSGT_ID_ACK) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700512 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK, g_self_conn_id));
Harald Welted86cdc62017-11-22 00:45:07 +0100513 }
514 case (IPAC_MSGT_ID_GET) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700515 f_ccm_tx(f_ccm_make_id_resp(ccm), g_self_conn_id);
Harald Welted86cdc62017-11-22 00:45:07 +0100516 }
Harald Welte2d86aff2018-04-17 11:23:04 +0200517 case else {
518 log("Unknown/unsupported IPA CCM message type", ccm);
519 }
520 }
521}
522
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700523private function f_ccm_rx_server(PDU_IPA_CCM ccm, IPL4asp_Types.ConnectionId conn_id)
524runs on IPA_Emulation_CT {
Harald Welte2d86aff2018-04-17 11:23:04 +0200525 select (ccm.msg_type) {
526 case (IPAC_MSGT_PING) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700527 f_ccm_tx(valueof(ts_IPA_PONG), conn_id);
Harald Welte2d86aff2018-04-17 11:23:04 +0200528 }
529 case (IPAC_MSGT_ID_ACK) {
530 /* the IPA server should at some point receive an ID_ACK from the client,
531 * in case of RSL/OML from nanoBTS, this is actually the first message after
532 * the TCP connection is established. Other implementations may differ.
533 * We currently ignore it completely - but actually we should make sure that
534 * one ID_ACK is received by the server at some point */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700535 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK, conn_id));
Harald Welte2d86aff2018-04-17 11:23:04 +0200536 }
Harald Welte3bc387f2018-02-21 12:18:46 +0100537 case (IPAC_MSGT_ID_RESP) {
538 log("IPA ID RESP: ", ccm.u.resp);
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700539
540 /* make sure that the response contains all fields we requested */
541 if (not match(ccm, tr_IPA_ID_RESP)) {
542 log("IPA identity response ", ccm.u.resp, " mismatch");
543 return;
544 }
545
546 /* forward to the upper layers, so they can map conn_id with unit_id */
547 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 +0200548 /* acknowledge any identity that the client may have sent */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700549 f_ccm_tx(valueof(ts_IPA_ACK), conn_id);
Harald Welte3bc387f2018-02-21 12:18:46 +0100550 }
Harald Welted86cdc62017-11-22 00:45:07 +0100551 case else {
552 log("Unknown/unsupported IPA CCM message type", ccm);
553 }
554 }
555}
556
Harald Weltec76f29f2017-11-22 12:46:46 +0100557private function f_to_asp(IPA_RecvFrom ipa_rx) return ASP_IPA_Unitdata {
558 var ASP_IPA_Unitdata ret := {
559 streamId := ipa_rx.streamId,
Harald Welte2a8f8472017-11-23 21:11:34 +0100560 streamIdExt := ipa_rx.streamIdExt,
Harald Weltec76f29f2017-11-22 12:46:46 +0100561 payload := ipa_rx.msg
562 }
563 return ret;
564}
565
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100566private function f_from_asp(IPL4asp_Types.ConnectionId connId, ASP_IPA_Unitdata ipa_tx) return IPA_Send {
Harald Weltec82eef42017-11-24 20:40:12 +0100567 var IPA_Send ret := valueof(t_IPA_Send(connId, ipa_tx.streamId, ipa_tx.payload,
568 ipa_tx.streamIdExt));
Harald Weltec76f29f2017-11-22 12:46:46 +0100569 return ret;
570}
Harald Welted86cdc62017-11-22 00:45:07 +0100571
Harald Weltedf277252018-02-20 15:49:30 +0100572#ifdef IPA_EMULATION_RSL
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100573private function f_from_rsl(IPL4asp_Types.ConnectionId connId, ASP_RSL_Unitdata rsl_tx) return IPA_Send {
Harald Welte0d846a72017-12-07 17:58:28 +0100574 var octetstring payload := enc_RSL_Message(rsl_tx.rsl);
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700575
576 /* ASP_RSL_Unitdata may (optionally) contain TCP/IP connection ID */
577 if (rsl_tx.conn_id != omit) {
578 connId := rsl_tx.conn_id;
579 }
580
581 return valueof(t_IPA_Send(connId, rsl_tx.streamId, payload));
Harald Welte0d846a72017-12-07 17:58:28 +0100582}
Harald Weltedf277252018-02-20 15:49:30 +0100583#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100584
Harald Weltec6826662019-02-06 22:26:46 +0100585#ifdef IPA_EMULATION_OML
586private function f_from_oml(IPL4asp_Types.ConnectionId connId, OML_PDU oml_tx) return IPA_Send {
587 var octetstring payload := enc_OML_PDU(oml_tx);
588 var IPA_Send ret := valueof(t_IPA_Send(connId, IPAC_PROTO_OML, payload));
589 return ret;
590}
591#endif
592
Harald Weltebdb63702017-12-09 01:15:44 +0100593/* main function to use for a client-side IPA implementation */
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100594function main_client(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
595 charstring local_host, IPL4asp_Types.PortNumber local_port,
Harald Welte2d86aff2018-04-17 11:23:04 +0200596 IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars,
597 boolean ccm_enabled := true) runs on IPA_Emulation_CT {
Harald Welteb3414b22017-11-23 18:22:10 +0100598 g_mode := IPA_MODE_CLIENT;
Harald Welte2d86aff2018-04-17 11:23:04 +0200599 g_ccm_enabled := ccm_enabled;
Harald Weltee09921f2017-12-07 17:49:00 +0100600 f_connect(remote_host, remote_port, local_host, local_port, ccm_pars);
Harald Welte2d86aff2018-04-17 11:23:04 +0200601 if (g_ccm_enabled) {
602 /* we're a client: Send ID_ACK immediately after connect */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700603 f_ccm_tx(valueof(ts_IPA_ACK), g_self_conn_id);
Harald Welte2d86aff2018-04-17 11:23:04 +0200604 }
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700605 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_UP, g_self_conn_id));
Harald Welteb3414b22017-11-23 18:22:10 +0100606 ScanEvents();
607}
608
Harald Weltebdb63702017-12-09 01:15:44 +0100609/* main function to use for a server-side IPA implementation */
Harald Welte2d86aff2018-04-17 11:23:04 +0200610function main_server(charstring local_host, IPL4asp_Types.PortNumber local_port,
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200611 boolean ccm_enabled := true,
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100612 IpaInitBehavior init_behavior := IPA_INIT_SEND_IPA_ID_GET,
613 boolean server_stop_on_ipa_ev_down := true)
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200614runs on IPA_Emulation_CT {
Harald Welteb3414b22017-11-23 18:22:10 +0100615 g_mode := IPA_MODE_SERVER;
Harald Welte2d86aff2018-04-17 11:23:04 +0200616 g_ccm_enabled := ccm_enabled;
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200617 g_init_behavior := init_behavior;
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100618 g_server_stop_on_ipa_ev_down := server_stop_on_ipa_ev_down;
Harald Welteb3414b22017-11-23 18:22:10 +0100619 f_bind(local_host, local_port);
620 ScanEvents();
621}
622
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200623#ifdef IPA_EMULATION_CTRL
Harald Weltedf277252018-02-20 15:49:30 +0100624private function f_ctrl_to_user(octetstring msg) runs on IPA_Emulation_CT {
625 var charstring msg_ch := oct2char(msg);
626 IPA_CTRL_PORT.send(dec_CtrlMessage(msg_ch));
627}
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200628#endif
Harald Weltedf277252018-02-20 15:49:30 +0100629
630#ifdef IPA_EMULATION_GSUP
631private function f_gsup_to_user(octetstring msg) runs on IPA_Emulation_CT {
632 var GSUP_PDU gsup := dec_GSUP_PDU(msg);
633 f_gsup_postprocess_decoded(gsup);
634 IPA_GSUP_PORT.send(gsup);
635}
636#endif
637
Harald Welte7460a722018-10-10 12:28:27 +0200638#ifdef IPA_EMULATION_RSPRO
639private function f_rspro_to_user(octetstring msg) runs on IPA_Emulation_CT {
640 var RsproPDU rspro := dec_RsproPDU(msg);
641 IPA_RSPRO_PORT.send(rspro);
642}
643#endif
644
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200645#ifdef IPA_EMULATION_OSMO_PCU
646private function f_osmo_pcu_to_user(octetstring msg) runs on IPA_Emulation_CT {
647 var PCUIF_Message pcuif_msg := dec_PCUIF_Message(msg);
648 IPA_OSMO_PCU_PORT.send(pcuif_msg);
649}
650#endif
651
Harald Weltedf277252018-02-20 15:49:30 +0100652#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100653private function f_mgcp_to_user(octetstring msg) runs on IPA_Emulation_CT {
654 var charstring msg_ch := oct2char(msg);
655 if (g_is_bsc_mgw) {
656 log("============");
657 log(msg_ch);
658 IPA_MGCP_PORT.send(dec_MgcpCommand(msg_ch));
659 } else {
660 IPA_MGCP_PORT.send(dec_MgcpResponse(msg_ch));
661 }
662}
663
Harald Welte92632e12017-11-25 02:31:20 +0100664private function f_mgcp_to_ud(octetstring payload) runs on IPA_Emulation_CT return ASP_IPA_Unitdata {
665 if (mp_ipa_mgcp_uses_osmo_ext) {
666 return valueof(t_ASP_IPA_UD(IPAC_PROTO_MGCP_OLD, payload));
667 } else {
668 return valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_MGCP));
669 }
670}
Harald Weltedf277252018-02-20 15:49:30 +0100671#endif
Harald Welte92632e12017-11-25 02:31:20 +0100672
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700673/* Resolve TCP/IP connection identifier depending on g_mode */
674private function f_ipa_conn_id() runs on IPA_Emulation_CT
675return IPL4asp_Types.ConnectionId {
676 var IPL4asp_Types.ConnectionId conn_id;
677
678 select (g_mode) {
679 case (IPA_MODE_CLIENT) { conn_id := g_self_conn_id; }
680 case (IPA_MODE_SERVER) { conn_id := g_last_conn_id; }
681 case else {
682 setverdict(fail, "Unknown mode");
683 mtc.stop;
684 }
685 }
686
687 if (conn_id == -1) { /* Just to be sure */
688 setverdict(fail, "Connection is not established");
689 mtc.stop;
690 }
691
692 return conn_id;
693}
694
Harald Weltebdb63702017-12-09 01:15:44 +0100695/* main loop function for both client and server. 'thread' of the component */
Harald Welteb3414b22017-11-23 18:22:10 +0100696private function ScanEvents() runs on IPA_Emulation_CT {
Harald Welted86cdc62017-11-22 00:45:07 +0100697 var IPA_RecvFrom ipa_rx;
Harald Welteb3414b22017-11-23 18:22:10 +0100698 var ASP_Event asp_evt;
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100699 var Socket_API_Definitions.PortEvent port_evt;
Harald Weltedf277252018-02-20 15:49:30 +0100700 var octetstring payload;
Harald Weltedf277252018-02-20 15:49:30 +0100701 var ASP_IPA_Unitdata ipa_ud;
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100702 var IPL4asp_Types.Result res;
Harald Welte3286eb32019-08-18 19:36:10 +0200703#ifdef IPA_EMULATION_CTRL
704 var CtrlMessage ctrl_msg;
705#endif
Harald Weltedf277252018-02-20 15:49:30 +0100706#ifdef IPA_EMULATION_SCCP
707 var ASP_MTP3_TRANSFERreq mtp_req;
708#endif
709#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100710 var MgcpCommand mgcp_cmd;
711 var MgcpResponse mgcp_rsp;
Harald Weltedf277252018-02-20 15:49:30 +0100712#endif
713#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100714 var GSUP_PDU gsup_msg;
Harald Weltedf277252018-02-20 15:49:30 +0100715#endif
716#ifdef IPA_EMULATION_RSL
Harald Welte0d846a72017-12-07 17:58:28 +0100717 var ASP_RSL_Unitdata rsl;
Harald Weltedf277252018-02-20 15:49:30 +0100718#endif
Harald Weltec6826662019-02-06 22:26:46 +0100719#ifdef IPA_EMULATION_OML
720 var OML_PDU oml;
721#endif
Harald Welte7460a722018-10-10 12:28:27 +0200722#ifdef IPA_EMULATION_RSPRO
723 var RsproPDU rspro;
724#endif
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200725#ifdef IPA_EMULATION_OSMO_PCU
726 var PCUIF_Message pcu;
727#endif
Harald Welted86cdc62017-11-22 00:45:07 +0100728
Harald Welte3e6ad892017-12-12 14:39:46 +0100729 /* Set function for dissecting the binary */
730 var f_IPL4_getMsgLen vl_f := refers(f_IPL4_fixedMsgLen);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700731 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 +0100732
Harald Welted86cdc62017-11-22 00:45:07 +0100733 while (true) {
734 alt {
735 /* Received IPA -> up into SCCP stack */
Harald Welte2d86aff2018-04-17 11:23:04 +0200736 [g_ccm_enabled] IPA_PORT.receive(IPA_RecvFrom:{?,IPAC_PROTO_CCM,omit,?}) -> value ipa_rx {
737 var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg);
738 log("CCM Rx:", ccm);
739 select (g_mode) {
740 case (IPA_MODE_CLIENT) {
741 f_ccm_rx_client(ccm);
742 }
743 case (IPA_MODE_SERVER) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700744 f_ccm_rx_server(ccm, ipa_rx.connId);
Harald Welte2d86aff2018-04-17 11:23:04 +0200745 }
746 case else {
747 setverdict(fail, "Unknown mode");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200748 mtc.stop;
Harald Welte2d86aff2018-04-17 11:23:04 +0200749 }
Harald Weltedf277252018-02-20 15:49:30 +0100750 }
Harald Welte2d86aff2018-04-17 11:23:04 +0200751 }
752 [] IPA_PORT.receive(IPA_RecvFrom:?) -> value ipa_rx {
753 select (ipa_rx.streamId) {
Harald Weltedf277252018-02-20 15:49:30 +0100754#ifdef IPA_EMULATION_SCCP
755 case (IPAC_PROTO_SCCP) {
Harald Welted86cdc62017-11-22 00:45:07 +0100756 var ASP_MTP3_TRANSFERind mtp;
757 mtp := valueof(ts_MTP3_XFER_ind(0, ipa_rx.msg));
758 MTP3_SP_PORT.send(mtp);
Harald Weltedf277252018-02-20 15:49:30 +0100759 }
760#endif
761#ifdef IPA_EMULATION_MGCP
762 case (IPAC_PROTO_MGCP_OLD) {
Harald Weltec82eef42017-11-24 20:40:12 +0100763 f_mgcp_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100764 }
765#endif
766#ifdef IPA_EMULATION_RSL
767 case (t_IpaSidRSL) {
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700768 rsl := valueof(ts_ASP_RSL_UD(
769 rsl := dec_RSL_Message(ipa_rx.msg),
770 sid := ipa_rx.streamId,
771 conn_id := ipa_rx.connId
772 ));
Harald Welte0d846a72017-12-07 17:58:28 +0100773 IPA_RSL_PORT.send(rsl);
Harald Weltedf277252018-02-20 15:49:30 +0100774 }
775#endif
Harald Weltec6826662019-02-06 22:26:46 +0100776#ifdef IPA_EMULATION_OML
777 case (IPAC_PROTO_OML) {
778 oml := dec_OML_PDU(ipa_rx.msg)
779 IPA_OML_PORT.send(oml);
780 }
781#endif
Harald Weltedf277252018-02-20 15:49:30 +0100782 case (IPAC_PROTO_OSMO) {
Harald Weltec82eef42017-11-24 20:40:12 +0100783 select (ipa_rx.streamIdExt) {
Harald Weltedf277252018-02-20 15:49:30 +0100784#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100785 case (IPAC_PROTO_EXT_MGCP) {
786 f_mgcp_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100787 }
788#endif
Harald Welte3286eb32019-08-18 19:36:10 +0200789#ifdef IPA_EMULATION_CTRL
Harald Weltedf277252018-02-20 15:49:30 +0100790 case (IPAC_PROTO_EXT_CTRL) {
Harald Weltea76c4bb2017-12-09 02:06:07 +0100791 f_ctrl_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100792 }
Harald Welte3286eb32019-08-18 19:36:10 +0200793#endif
Harald Weltedf277252018-02-20 15:49:30 +0100794#ifdef IPA_EMULATION_GSUP
795 case (IPAC_PROTO_EXT_GSUP) {
Harald Weltedf327232017-12-28 22:51:51 +0100796 f_gsup_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100797 }
798#endif
Harald Welte7460a722018-10-10 12:28:27 +0200799#ifdef IPA_EMULATION_RSPRO
800 case (IPAC_PROTO_EXT_RSPRO) {
801 f_rspro_to_user(ipa_rx.msg);
802 }
803#endif
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200804#ifdef IPA_EMULATION_OSMO_PCU
805 case (IPAC_PROTO_EXT_OSMO_PCU) {
806 f_osmo_pcu_to_user(ipa_rx.msg);
807 }
808#endif
Harald Weltedf277252018-02-20 15:49:30 +0100809 case else {
Harald Weltec82eef42017-11-24 20:40:12 +0100810 IPA_SP_PORT.send(f_to_asp(ipa_rx));
811 }
Harald Welted86cdc62017-11-22 00:45:07 +0100812 }
Harald Weltedf277252018-02-20 15:49:30 +0100813 }
814 case else {
Harald Weltec76f29f2017-11-22 12:46:46 +0100815 IPA_SP_PORT.send(f_to_asp(ipa_rx));
Harald Welted86cdc62017-11-22 00:45:07 +0100816 }
817 }
818 }
819
Harald Welteb3414b22017-11-23 18:22:10 +0100820 /* server only */
821 [] IPA_PORT.receive(ASP_Event:{connOpened:=?}) -> value asp_evt {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700822 g_last_conn_id := asp_evt.connOpened.connId;
823 log("Established a new IPA connection (conn_id=", g_last_conn_id, ")");
824
825 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_UP, g_last_conn_id));
Harald Welte2d86aff2018-04-17 11:23:04 +0200826 if (g_mode == IPA_MODE_SERVER and g_ccm_enabled) {
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200827 select (g_init_behavior) {
828 case (IPA_INIT_SEND_IPA_ID_GET) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700829 f_ccm_tx(valueof(ts_IPA_ID_GET), g_last_conn_id);
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200830 }
831 case (IPA_INIT_SEND_IPA_ID_ACK) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700832 f_ccm_tx(valueof(ts_IPA_ACK), g_last_conn_id);
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200833 }
834 }
Harald Welteb3414b22017-11-23 18:22:10 +0100835 }
836 }
837
838 [] IPA_PORT.receive(ASP_Event:{connClosed:=?}) -> value asp_evt {
839 log("IPA: Closed");
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700840 g_self_conn_id := -1;
841 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_DOWN, asp_evt.connClosed.connId));
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100842 if (g_mode != IPA_MODE_SERVER or g_server_stop_on_ipa_ev_down) {
843 self.stop;
844 }
Harald Welteb3414b22017-11-23 18:22:10 +0100845 }
846
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100847 [] IPA_PORT.receive(Socket_API_Definitions.PortEvent:{result:={errorCode:=ERROR_SOCKET, connId:=?, os_error_code:=?, os_error_text:=?}}) -> value port_evt {
848 log("PortEvent: ERROR_SOCKET: ", port_evt);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700849 g_self_conn_id := -1;
850 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_DOWN, port_evt.result.connId));
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100851 self.stop;
852 }
853
Harald Weltedf277252018-02-20 15:49:30 +0100854#ifdef IPA_EMULATION_SCCP
Harald Welted86cdc62017-11-22 00:45:07 +0100855 /* Received SCCP -> down into IPA */
856 [] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700857 var IPA_Send ipa_tx := valueof(t_IPA_Send(f_ipa_conn_id(), IPAC_PROTO_SCCP,
Harald Weltec82eef42017-11-24 20:40:12 +0100858 mtp_req.data));
Harald Welted86cdc62017-11-22 00:45:07 +0100859 IPA_PORT.send(ipa_tx);
860 }
Harald Weltedf277252018-02-20 15:49:30 +0100861#endif
Harald Weltec76f29f2017-11-22 12:46:46 +0100862
Harald Weltedf277252018-02-20 15:49:30 +0100863#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100864 /* Received MGCP -> down into IPA */
865 [] IPA_MGCP_PORT.receive(MgcpCommand:?) -> value mgcp_cmd {
Harald Welte92632e12017-11-25 02:31:20 +0100866 payload := char2oct(enc_MgcpCommand(mgcp_cmd));
867 ipa_ud := f_mgcp_to_ud(payload);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700868 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltec82eef42017-11-24 20:40:12 +0100869 }
870 [] IPA_MGCP_PORT.receive(MgcpResponse:?) -> value mgcp_rsp {
Harald Welte1dd8f372017-11-25 02:25:27 +0100871 payload := char2oct(enc_MgcpResponse(mgcp_rsp));
Harald Welte92632e12017-11-25 02:31:20 +0100872 ipa_ud := f_mgcp_to_ud(payload);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700873 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltec82eef42017-11-24 20:40:12 +0100874 }
Harald Weltedf277252018-02-20 15:49:30 +0100875#endif
Harald Weltec82eef42017-11-24 20:40:12 +0100876
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200877#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +0100878 [] IPA_CTRL_PORT.receive(CtrlMessage:?) -> value ctrl_msg {
879 payload := char2oct(enc_CtrlMessage(ctrl_msg));
880 ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_CTRL));
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700881 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltea76c4bb2017-12-09 02:06:07 +0100882 }
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200883#endif
Harald Weltea76c4bb2017-12-09 02:06:07 +0100884
Harald Weltedf277252018-02-20 15:49:30 +0100885#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100886 [] IPA_GSUP_PORT.receive(GSUP_PDU:?) -> value gsup_msg {
Harald Welte2f562b12018-01-24 20:52:38 +0100887 f_gsup_preprocess_encoded(gsup_msg);
Harald Weltedf327232017-12-28 22:51:51 +0100888 payload := enc_GSUP_PDU(gsup_msg);
889 ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_GSUP));
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700890 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltedf327232017-12-28 22:51:51 +0100891 }
Harald Weltedf277252018-02-20 15:49:30 +0100892#endif
Harald Weltedf327232017-12-28 22:51:51 +0100893
Harald Welte7460a722018-10-10 12:28:27 +0200894#ifdef IPA_EMULATION_RSPRO
895 [] IPA_RSPRO_PORT.receive(RsproPDU:?) -> value rspro {
896 payload := enc_RsproPDU(rspro);
897 ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_RSPRO));
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700898 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Welte7460a722018-10-10 12:28:27 +0200899 }
900#endif
901
Pau Espin Pedrol6924ef72021-06-09 16:19:26 +0200902#ifdef IPA_EMULATION_OSMO_PCU
903 [] IPA_OSMO_PCU_PORT.receive(PCUIF_Message:?) -> value pcu {
904 payload := enc_PCUIF_Message(pcu);
905 ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_OSMO_PCU));
906 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
907 }
908#endif
909
Harald Weltedf277252018-02-20 15:49:30 +0100910#ifdef IPA_EMULATION_RSL
Harald Welte0d846a72017-12-07 17:58:28 +0100911 /* Received RSL -> down into IPA */
912 [] IPA_RSL_PORT.receive(ASP_RSL_Unitdata:?) -> value rsl {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700913 IPA_PORT.send(f_from_rsl(f_ipa_conn_id(), rsl));
Harald Welte0d846a72017-12-07 17:58:28 +0100914 }
Harald Weltedf277252018-02-20 15:49:30 +0100915#endif
Harald Weltec6826662019-02-06 22:26:46 +0100916#ifdef IPA_EMULATION_OML
917 /* Received OML -> down into IPA */
918 [] IPA_OML_PORT.receive(OML_PDU:?) -> value oml {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700919 IPA_PORT.send(f_from_oml(f_ipa_conn_id(), oml));
Harald Weltec6826662019-02-06 22:26:46 +0100920 }
921 [] IPA_OML_PORT.receive(octetstring:?) -> value payload {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700922 IPA_PORT.send(t_IPA_Send(f_ipa_conn_id(), IPAC_PROTO_OML, payload));
Harald Weltec6826662019-02-06 22:26:46 +0100923 }
924#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100925 /* Received MISC (OML/CTRL) -> down into IPA */
Harald Weltec76f29f2017-11-22 12:46:46 +0100926 [] IPA_SP_PORT.receive(ASP_IPA_Unitdata: ?) -> value ipa_ud {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700927 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltec76f29f2017-11-22 12:46:46 +0100928 }
929
Pau Espin Pedrolaf0c61e2022-01-11 12:48:34 +0100930 /* Received call to configure/operate the component */
931 [] CFG_PORT.getcall(IPA_CFG_disconnect:{?}) {
932 res := f_close();
933 CFG_PORT.reply(IPA_CFG_disconnect:{res});
934 }
Harald Weltec76f29f2017-11-22 12:46:46 +0100935
Harald Welted86cdc62017-11-22 00:45:07 +0100936 }
937 }
938}
939
Harald Welte2e32e432018-05-24 20:00:00 +0200940/***********************************************************************
941 * IPA Event waiter component. Wait for ASP_IPA_EVENT_ID_ACK
942 ***********************************************************************/
943
944type component IPA_EventWaiter_CT {
945 port IPA_SP_PT IPA_SP_PORT;
946}
947
Vadim Yanitskiy61564be2020-05-18 20:44:14 +0700948function waiter_main(template ASP_IPA_Event wait_for := tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK))
Harald Welte2e32e432018-05-24 20:00:00 +0200949runs on IPA_EventWaiter_CT {
950
951 alt {
952 [] IPA_SP_PORT.receive(wait_for) {
953 setverdict(pass);
954 }
955 [] IPA_SP_PORT.receive { repeat; }
956 }
957}
958
959
Harald Welted86cdc62017-11-22 00:45:07 +0100960}