blob: 71c3f8e363d20c7cacdeb0e0c583412f1875f9ac [file] [log] [blame]
Harald Welte77847ad2015-10-06 22:07:04 +02001/* hnb-gw specific code for RUA (Ranap User Adaption) */
2
3/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21
Harald Welte318e4d52015-09-10 18:47:08 +020022#include <osmocom/core/msgb.h>
23#include <osmocom/core/utils.h>
Harald Welteffa7c0a2015-12-23 00:03:41 +010024#include <osmocom/netif/stream.h>
Harald Welte318e4d52015-09-10 18:47:08 +020025
Harald Weltec4338de2015-12-24 00:40:52 +010026#include <osmocom/sigtran/sccp_sap.h>
Harald Welteda86fe52017-11-21 08:14:37 +010027#include <osmocom/sigtran/sccp_helpers.h>
Harald Weltec4338de2015-12-24 00:40:52 +010028
Harald Welte318e4d52015-09-10 18:47:08 +020029#include <unistd.h>
30#include <errno.h>
31#include <string.h>
32
33#include "asn1helpers.h"
34
Neels Hofmeyrdf63de22016-08-18 13:13:55 +020035#include <osmocom/iuh/hnbgw.h>
36#include <osmocom/iuh/hnbgw_ranap.h>
Neels Hofmeyr83457922016-08-26 23:56:44 +020037#include <osmocom/rua/rua_common.h>
38#include <osmocom/rua/rua_ies_defs.h>
Neels Hofmeyrdf63de22016-08-18 13:13:55 +020039#include <osmocom/iuh/context_map.h>
Neels Hofmeyr12ed9752017-07-03 16:33:14 +020040#include <osmocom/hnbap/CN-DomainIndicator.h>
Harald Welte318e4d52015-09-10 18:47:08 +020041
Neels Hofmeyrc3614312017-07-03 14:34:38 +020042static const char *cn_domain_indicator_to_str(CN_DomainIndicator_t cN_DomainIndicator)
43{
44 switch (cN_DomainIndicator) {
45 case RUA_CN_DomainIndicator_cs_domain:
46 return "IuCS";
47 case RUA_CN_DomainIndicator_ps_domain:
48 return "IuPS";
49 default:
50 return "(unknown-domain)";
51 }
52}
53
Harald Welte318e4d52015-09-10 18:47:08 +020054static int hnbgw_rua_tx(struct hnb_context *ctx, struct msgb *msg)
55{
56 if (!msg)
57 return -EINVAL;
58
Harald Welteffa7c0a2015-12-23 00:03:41 +010059 msgb_sctp_ppid(msg) = IUH_PPI_RUA;
Daniel Willmann6480cad2016-01-06 18:06:26 +010060 osmo_stream_srv_send(ctx->conn, msg);
61
62 return 0;
Harald Welte318e4d52015-09-10 18:47:08 +020063}
64
Harald Weltecd5e9812015-12-23 22:14:16 +010065int rua_tx_udt(struct hnb_context *hnb, const uint8_t *data, unsigned int len)
Harald Welte64b4ebe2015-09-10 19:29:59 +020066{
Harald Weltee2e5d4d2015-09-10 23:49:45 +020067 RUA_ConnectionlessTransfer_t out;
68 RUA_ConnectionlessTransferIEs_t ies;
69 struct msgb *msg;
70 int rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +020071
Harald Weltee2e5d4d2015-09-10 23:49:45 +020072 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +010073 ies.ranaP_Message.buf = (uint8_t *) data;
74 ies.ranaP_Message.size = len;
Harald Weltee2e5d4d2015-09-10 23:49:45 +020075
76 /* FIXME: msgb_free(msg)? ownership not yet clear */
77
78 memset(&out, 0, sizeof(out));
79 rc = rua_encode_connectionlesstransferies(&out, &ies);
80 if (rc < 0)
81 return rc;
82
83 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_ConnectionlessTransfer,
84 RUA_Criticality_reject,
85 &asn_DEF_RUA_ConnectionlessTransfer,
86 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +010087 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_ConnectionlessTransfer, &out);
Harald Weltee2e5d4d2015-09-10 23:49:45 +020088
Harald Weltec4338de2015-12-24 00:40:52 +010089 DEBUGP(DRUA, "transmitting RUA payload of %u bytes\n", msgb_length(msg));
Harald Weltee2e5d4d2015-09-10 23:49:45 +020090
Harald Weltec4338de2015-12-24 00:40:52 +010091 return hnbgw_rua_tx(hnb, msg);
Harald Welte64b4ebe2015-09-10 19:29:59 +020092}
93
Harald Weltecd5e9812015-12-23 22:14:16 +010094int rua_tx_dt(struct hnb_context *hnb, int is_ps, uint32_t context_id,
95 const uint8_t *data, unsigned int len)
Harald Welte0f0ea812015-09-11 18:58:28 +020096{
97 RUA_DirectTransfer_t out;
98 RUA_DirectTransferIEs_t ies;
Harald Weltecd5e9812015-12-23 22:14:16 +010099 uint32_t ctxidbuf;
Harald Welte0f0ea812015-09-11 18:58:28 +0200100 struct msgb *msg;
101 int rc;
102
103 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +0100104 if (is_ps)
105 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
106 else
107 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
108 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
109 ies.ranaP_Message.buf = (uint8_t *) data;
110 ies.ranaP_Message.size = len;
Harald Welte0f0ea812015-09-11 18:58:28 +0200111
112 /* FIXME: msgb_free(msg)? ownership not yet clear */
113
114 memset(&out, 0, sizeof(out));
115 rc = rua_encode_directtransferies(&out, &ies);
116 if (rc < 0)
117 return rc;
118
119 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_DirectTransfer,
120 RUA_Criticality_reject,
121 &asn_DEF_RUA_DirectTransfer,
122 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +0100123 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_DirectTransfer, &out);
Harald Welte0f0ea812015-09-11 18:58:28 +0200124
Harald Welte5bea8002015-12-26 23:40:31 +0100125 DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
126 is_ps ? "ps" : "cs", msgb_length(msg));
Harald Welte0f0ea812015-09-11 18:58:28 +0200127
Harald Weltecd5e9812015-12-23 22:14:16 +0100128 return hnbgw_rua_tx(hnb, msg);
Harald Welte0f0ea812015-09-11 18:58:28 +0200129}
130
Harald Weltecd5e9812015-12-23 22:14:16 +0100131int rua_tx_disc(struct hnb_context *hnb, int is_ps, uint32_t context_id,
132 const RUA_Cause_t *cause, const uint8_t *data, unsigned int len)
133{
134 RUA_Disconnect_t out;
135 RUA_DisconnectIEs_t ies;
136 struct msgb *msg;
137 uint32_t ctxidbuf;
138 int rc;
139
140 memset(&ies, 0, sizeof(ies));
141 if (is_ps)
142 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
143 else
144 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
145 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
146 memcpy(&ies.cause, cause, sizeof(ies.cause));
147 if (data && len) {
148 ies.presenceMask |= DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT;
149 ies.ranaP_Message.buf = (uint8_t *) data;
150 ies.ranaP_Message.size = len;
151 }
152
153 /* FIXME: msgb_free(msg)? ownership not yet clear */
154
155 memset(&out, 0, sizeof(out));
156 rc = rua_encode_disconnecties(&out, &ies);
157 if (rc < 0)
158 return rc;
159
160 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_Disconnect,
161 RUA_Criticality_reject,
162 &asn_DEF_RUA_Disconnect,
163 &out);
164 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_Disconnect, &out);
165
Harald Welte5bea8002015-12-26 23:40:31 +0100166 DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
167 is_ps ? "ps" : "cs", msgb_length(msg));
168
Harald Weltecd5e9812015-12-23 22:14:16 +0100169
170 return hnbgw_rua_tx(hnb, msg);
171}
172
173
Harald Welte0f0ea812015-09-11 18:58:28 +0200174
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200175/* forward a RUA message to the SCCP User API to SCCP */
176static int rua_to_scu(struct hnb_context *hnb,
177 CN_DomainIndicator_t cN_DomainIndicator,
Harald Weltec4338de2015-12-24 00:40:52 +0100178 enum osmo_scu_prim_type type,
179 uint32_t context_id, uint32_t cause,
180 const uint8_t *data, unsigned int len)
181{
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200182 struct msgb *msg;
Harald Weltec4338de2015-12-24 00:40:52 +0100183 struct osmo_scu_prim *prim;
Neels Hofmeyr6814d222018-01-15 23:19:43 +0100184 struct hnbgw_context_map *map = NULL;
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200185 struct hnbgw_cnlink *cn = hnb->gw->sccp.cnlink;
186 struct osmo_sccp_addr *remote_addr;
187 bool is_ps;
Neels Hofmeyrb10e2932017-12-24 21:49:44 +0100188 bool release_context_map = false;
Harald Weltec4338de2015-12-24 00:40:52 +0100189 int rc;
190
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200191 switch (cN_DomainIndicator) {
192 case RUA_CN_DomainIndicator_cs_domain:
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +0200193 remote_addr = &hnb->gw->sccp.iucs_remote_addr;
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200194 is_ps = false;
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200195 break;
196 case RUA_CN_DomainIndicator_ps_domain:
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +0200197 remote_addr = &hnb->gw->sccp.iups_remote_addr;
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200198 is_ps = true;
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200199 break;
200 default:
Neels Hofmeyr70d3ece2018-01-15 23:19:04 +0100201 LOGP(DRUA, LOGL_ERROR, "Unsupported Domain %ld\n",
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200202 cN_DomainIndicator);
203 return -1;
204 }
205
Harald Welte49287972015-12-29 19:00:35 +0100206 if (!cn) {
207 DEBUGP(DRUA, "CN=NULL, discarding message\n");
208 return 0;
209 }
210
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200211 msg = msgb_alloc(1500, "rua_to_sccp");
212
Harald Weltec4338de2015-12-24 00:40:52 +0100213 prim = (struct osmo_scu_prim *) msgb_put(msg, sizeof(*prim));
214 osmo_prim_init(&prim->oph, SCCP_SAP_USER, type, PRIM_OP_REQUEST, msg);
215
Neels Hofmeyr1e9f4f52017-12-24 23:57:58 +0100216 switch (type) {
217 case OSMO_SCU_PRIM_N_UNITDATA:
218 DEBUGP(DRUA, "rua_to_scu() %s to %s, rua_ctx_id %u (unitdata, no scu_conn_id)\n",
219 cn_domain_indicator_to_str(cN_DomainIndicator),
220 osmo_sccp_addr_dump(remote_addr),
Neels Hofmeyr6814d222018-01-15 23:19:43 +0100221 context_id);
Neels Hofmeyr1e9f4f52017-12-24 23:57:58 +0100222 break;
223 default:
224 map = context_map_alloc_by_hnb(hnb, context_id, is_ps, cn);
225 OSMO_ASSERT(map);
226 DEBUGP(DRUA, "rua_to_scu() %s to %s, rua_ctx_id %u scu_conn_id %u\n",
227 cn_domain_indicator_to_str(cN_DomainIndicator),
228 osmo_sccp_addr_dump(remote_addr),
229 map->rua_ctx_id, map->scu_conn_id);
230 }
Neels Hofmeyrc3614312017-07-03 14:34:38 +0200231
Harald Weltec4338de2015-12-24 00:40:52 +0100232 /* add primitive header */
233 switch (type) {
234 case OSMO_SCU_PRIM_N_CONNECT:
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200235 prim->u.connect.called_addr = *remote_addr;
236 prim->u.connect.calling_addr = cn->gw->sccp.local_addr;
Harald Weltec4338de2015-12-24 00:40:52 +0100237 prim->u.connect.sccp_class = 2;
238 prim->u.connect.conn_id = map->scu_conn_id;
Neels Hofmeyr54e6e1f2017-07-03 17:29:28 +0200239 /* Two separate logs because of osmo_sccp_addr_dump(). */
240 DEBUGP(DRUA, "RUA to SCCP N_CONNECT: called_addr:%s\n",
241 osmo_sccp_addr_dump(&prim->u.connect.called_addr));
242 DEBUGP(DRUA, "RUA to SCCP N_CONNECT: calling_addr:%s\n",
243 osmo_sccp_addr_dump(&prim->u.connect.calling_addr));
Harald Weltec4338de2015-12-24 00:40:52 +0100244 break;
245 case OSMO_SCU_PRIM_N_DATA:
246 prim->u.data.conn_id = map->scu_conn_id;
247 break;
248 case OSMO_SCU_PRIM_N_DISCONNECT:
249 prim->u.disconnect.conn_id = map->scu_conn_id;
250 prim->u.disconnect.cause = cause;
Neels Hofmeyrb10e2932017-12-24 21:49:44 +0100251 release_context_map = true;
Harald Weltec4338de2015-12-24 00:40:52 +0100252 break;
253 case OSMO_SCU_PRIM_N_UNITDATA:
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200254 prim->u.unitdata.called_addr = *remote_addr;
255 prim->u.unitdata.calling_addr = cn->gw->sccp.local_addr;
Neels Hofmeyr54e6e1f2017-07-03 17:29:28 +0200256 /* Two separate logs because of osmo_sccp_addr_dump(). */
257 DEBUGP(DRUA, "RUA to SCCP N_UNITDATA: called_addr:%s\n",
258 osmo_sccp_addr_dump(&prim->u.unitdata.called_addr));
259 DEBUGP(DRUA, "RUA to SCCP N_UNITDATA: calling_addr:%s\n",
260 osmo_sccp_addr_dump(&prim->u.unitdata.calling_addr));
Harald Weltec4338de2015-12-24 00:40:52 +0100261 break;
262 default:
263 return -EINVAL;
264 }
265
266 /* add optional data section, if needed */
267 if (data && len) {
268 msg->l2h = msgb_put(msg, len);
269 memcpy(msg->l2h, data, len);
270 }
271
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200272 rc = osmo_sccp_user_sap_down(cn->sccp_user, &prim->oph);
Harald Weltec4338de2015-12-24 00:40:52 +0100273
Neels Hofmeyr1e9f4f52017-12-24 23:57:58 +0100274 if (map && release_context_map)
Neels Hofmeyrb10e2932017-12-24 21:49:44 +0100275 context_map_deactivate(map);
276
Harald Weltec4338de2015-12-24 00:40:52 +0100277 return rc;
278}
279
280static uint32_t rua_to_scu_cause(RUA_Cause_t *in)
281{
282 /* FIXME: Implement this! */
283#if 0
284 switch (in->present) {
285 case RUA_Cause_PR_NOTHING:
286 break;
287 case RUA_Cause_PR_radioNetwork:
288 switch (in->choice.radioNetwork) {
289 case RUA_CauseRadioNetwork_normal:
290 case RUA_CauseRadioNetwork_connect_failed:
291 case RUA_CauseRadioNetwork_network_release:
292 case RUA_CauseRadioNetwork_unspecified:
293 }
294 break;
295 case RUA_Cause_PR_transport:
296 switch (in->choice.transport) {
297 case RUA_CauseTransport_transport_resource_unavailable:
298 break;
299 case RUA_CauseTransport_unspecified:
300 break;
301 }
302 break;
303 case RUA_Cause_PR_protocol:
304 switch (in->choice.protocol) {
305 case RUA_CauseProtocol_transfer_syntax_error:
306 break;
307 case RUA_CauseProtocol_abstract_syntax_error_reject:
308 break;
309 case RUA_CauseProtocol_abstract_syntax_error_ignore_and_notify:
310 break;
311 case RUA_CauseProtocol_message_not_compatible_with_receiver_state:
312 break;
313 case RUA_CauseProtocol_semantic_error:
314 break;
315 case RUA_CauseProtocol_unspecified:
316 break;
317 case RUA_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
318 break;
319 }
320 break;
321 case RUA_Cause_PR_misc:
322 switch (in->choice.misc) {
323 case RUA_CauseMisc_processing_overload:
324 break;
325 case RUA_CauseMisc_hardware_failure:
326 break;
327 case RUA_CauseMisc_o_and_m_intervention:
328 break;
329 case RUA_CauseMisc_unspecified:
330 break;
331 }
332 break;
333 default:
334 break;
335 }
336#else
337 return 0;
338#endif
339
340}
341
Harald Welte350814a2015-09-10 22:32:15 +0200342static int rua_rx_init_connect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200343{
344 RUA_ConnectIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100345 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200346 uint32_t context_id;
347 int rc;
348
349 rc = rua_decode_connecties(&ies, in);
350 if (rc < 0)
351 return rc;
352
Harald Welteb0de9062015-12-24 14:10:17 +0100353 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200354
Neels Hofmeyrc3614312017-07-03 14:34:38 +0200355 DEBUGP(DRUA, "RUA %s Connect.req(ctx=0x%x, %s)\n",
356 cn_domain_indicator_to_str(ies.cN_DomainIndicator),
357 context_id,
358 ies.establishment_Cause == RUA_Establishment_Cause_emergency_call
Harald Welte64b4ebe2015-09-10 19:29:59 +0200359 ? "emergency" : "normal");
Harald Weltec4338de2015-12-24 00:40:52 +0100360
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200361 rc = rua_to_scu(hnb, ies.cN_DomainIndicator, OSMO_SCU_PRIM_N_CONNECT,
Harald Weltec4338de2015-12-24 00:40:52 +0100362 context_id, 0, ies.ranaP_Message.buf,
363 ies.ranaP_Message.size);
Neels Hofmeyr23f3fdc2017-12-25 00:00:04 +0100364
Daniel Willmann11e912a2016-01-07 13:19:30 +0100365 rua_free_connecties(&ies);
Harald Welte0f0ea812015-09-11 18:58:28 +0200366
367 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200368}
369
Harald Welte350814a2015-09-10 22:32:15 +0200370static int rua_rx_init_disconnect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200371{
372 RUA_DisconnectIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100373 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200374 uint32_t context_id;
Harald Weltec4338de2015-12-24 00:40:52 +0100375 uint32_t scu_cause;
376 uint8_t *ranap_data = NULL;
377 unsigned int ranap_len = 0;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200378 int rc;
379
380 rc = rua_decode_disconnecties(&ies, in);
381 if (rc < 0)
382 return rc;
383
Harald Welteb0de9062015-12-24 14:10:17 +0100384 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Weltec4338de2015-12-24 00:40:52 +0100385 scu_cause = rua_to_scu_cause(&ies.cause);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200386
Harald Welte37166a22015-12-24 10:12:09 +0100387 DEBUGP(DRUA, "RUA Disconnect.req(ctx=0x%x,cause=%s)\n", context_id,
Harald Welte64b4ebe2015-09-10 19:29:59 +0200388 rua_cause_str(&ies.cause));
Harald Welte0f0ea812015-09-11 18:58:28 +0200389
Harald Weltec4338de2015-12-24 00:40:52 +0100390 if (ies.presenceMask & DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT) {
391 ranap_data = ies.ranaP_Message.buf;
392 ranap_len = ies.ranaP_Message.size;
393 }
394
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200395 rc = rua_to_scu(hnb, ies.cN_DomainIndicator,
396 OSMO_SCU_PRIM_N_DISCONNECT,
Harald Weltec4338de2015-12-24 00:40:52 +0100397 context_id, scu_cause, ranap_data, ranap_len);
Neels Hofmeyrfe878092016-11-25 13:13:31 +0100398
Daniel Willmann11e912a2016-01-07 13:19:30 +0100399 rua_free_disconnecties(&ies);
Harald Weltec4338de2015-12-24 00:40:52 +0100400
Harald Welte0f0ea812015-09-11 18:58:28 +0200401 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200402}
403
Harald Welte350814a2015-09-10 22:32:15 +0200404static int rua_rx_init_dt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200405{
406 RUA_DirectTransferIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100407 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200408 uint32_t context_id;
409 int rc;
410
411 rc = rua_decode_directtransferies(&ies, in);
412 if (rc < 0)
413 return rc;
414
Harald Welteb0de9062015-12-24 14:10:17 +0100415 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200416
Harald Welte37166a22015-12-24 10:12:09 +0100417 DEBUGP(DRUA, "RUA Data.req(ctx=0x%x)\n", context_id);
Harald Weltec4338de2015-12-24 00:40:52 +0100418
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200419 rc = rua_to_scu(hnb,
420 ies.cN_DomainIndicator,
421 OSMO_SCU_PRIM_N_DATA,
Harald Weltec4338de2015-12-24 00:40:52 +0100422 context_id, 0, ies.ranaP_Message.buf,
423 ies.ranaP_Message.size);
Neels Hofmeyrfe878092016-11-25 13:13:31 +0100424
Daniel Willmann11e912a2016-01-07 13:19:30 +0100425 rua_free_directtransferies(&ies);
Harald Welte0f0ea812015-09-11 18:58:28 +0200426
427 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200428}
429
Harald Welte350814a2015-09-10 22:32:15 +0200430static int rua_rx_init_udt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200431{
432 RUA_ConnectionlessTransferIEs_t ies;
433 int rc;
434
435 rc = rua_decode_connectionlesstransferies(&ies, in);
436 if (rc < 0)
437 return rc;
438
Harald Welte37166a22015-12-24 10:12:09 +0100439 DEBUGP(DRUA, "RUA UData.req()\n");
Harald Welte64b4ebe2015-09-10 19:29:59 +0200440
Harald Weltec4338de2015-12-24 00:40:52 +0100441 /* according tot the spec, we can primarily receive Overload,
442 * Reset, Reset ACK, Error Indication, reset Resource, Reset
443 * Resurce Acknowledge as connecitonless RANAP. There are some
444 * more messages regarding Information Transfer, Direct
445 * Information Transfer and Uplink Information Trnansfer that we
446 * can ignore. In either case, it is RANAP that we need to
447 * decode... */
Harald Welte350814a2015-09-10 22:32:15 +0200448 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
Daniel Willmann11e912a2016-01-07 13:19:30 +0100449 rua_free_connectionlesstransferies(&ies);
Harald Welte350814a2015-09-10 22:32:15 +0200450
451 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200452}
453
Harald Welte350814a2015-09-10 22:32:15 +0200454
455static int rua_rx_init_err_ind(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200456{
457 RUA_ErrorIndicationIEs_t ies;
458 int rc;
459
460 rc = rua_decode_errorindicationies(&ies, in);
461 if (rc < 0)
462 return rc;
463
Harald Welte831e1ee2015-12-25 10:28:55 +0100464 LOGP(DRUA, LOGL_ERROR, "RUA UData.ErrorInd(%s)\n",
465 rua_cause_str(&ies.cause));
Harald Weltec4338de2015-12-24 00:40:52 +0100466
Daniel Willmann11e912a2016-01-07 13:19:30 +0100467 rua_free_errorindicationies(&ies);
Harald Weltec4338de2015-12-24 00:40:52 +0100468 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200469}
Harald Welte318e4d52015-09-10 18:47:08 +0200470
Harald Welte350814a2015-09-10 22:32:15 +0200471static int rua_rx_initiating_msg(struct msgb *msg, RUA_InitiatingMessage_t *imsg)
Harald Welte318e4d52015-09-10 18:47:08 +0200472{
473 int rc;
474
475 switch (imsg->procedureCode) {
476 case RUA_ProcedureCode_id_Connect:
Harald Welte350814a2015-09-10 22:32:15 +0200477 rc = rua_rx_init_connect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200478 break;
479 case RUA_ProcedureCode_id_DirectTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200480 rc = rua_rx_init_dt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200481 break;
482 case RUA_ProcedureCode_id_Disconnect:
Harald Welte350814a2015-09-10 22:32:15 +0200483 rc = rua_rx_init_disconnect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200484 break;
485 case RUA_ProcedureCode_id_ConnectionlessTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200486 rc = rua_rx_init_udt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200487 break;
488 case RUA_ProcedureCode_id_ErrorIndication:
Harald Welte350814a2015-09-10 22:32:15 +0200489 rc = rua_rx_init_err_ind(msg, &imsg->value);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200490 break;
Harald Welte318e4d52015-09-10 18:47:08 +0200491 case RUA_ProcedureCode_id_privateMessage:
Neels Hofmeyr2b5021f2016-11-25 13:25:38 +0100492 LOGP(DRUA, LOGL_NOTICE,
493 "Unhandled: RUA Initiating Msg: Private Msg\n");
494 rc = 0;
Harald Welte318e4d52015-09-10 18:47:08 +0200495 break;
496 default:
Harald Welteda86fe52017-11-21 08:14:37 +0100497 LOGP(DRUA, LOGL_NOTICE, "Unknown RUA Procedure %lu\n",
Harald Welte37166a22015-12-24 10:12:09 +0100498 imsg->procedureCode);
499 rc = -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200500 }
Harald Welte37166a22015-12-24 10:12:09 +0100501
502 return rc;
Harald Welte318e4d52015-09-10 18:47:08 +0200503}
504
Harald Welte350814a2015-09-10 22:32:15 +0200505static int rua_rx_successful_outcome_msg(struct msgb *msg, RUA_SuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200506{
Harald Weltec4338de2015-12-24 00:40:52 +0100507 /* FIXME */
Thorsten Alteholz445bdcc2019-07-16 21:15:36 +0200508 LOGP(DRUA, LOGL_NOTICE, "Unexpected RUA Successful Outcome\n");
Harald Welte37166a22015-12-24 10:12:09 +0100509 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200510}
511
Harald Welte350814a2015-09-10 22:32:15 +0200512static int rua_rx_unsuccessful_outcome_msg(struct msgb *msg, RUA_UnsuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200513{
Harald Weltec4338de2015-12-24 00:40:52 +0100514 /* FIXME */
Harald Welte37166a22015-12-24 10:12:09 +0100515 LOGP(DRUA, LOGL_NOTICE, "Unexpected RUA Unsucessful Outcome\n");
516 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200517}
518
519
Harald Welte350814a2015-09-10 22:32:15 +0200520static int _hnbgw_rua_rx(struct msgb *msg, RUA_RUA_PDU_t *pdu)
Harald Welte318e4d52015-09-10 18:47:08 +0200521{
522 int rc;
523
524 /* it's a bit odd that we can't dispatch on procedure code, but
525 * that's not possible */
526 switch (pdu->present) {
527 case RUA_RUA_PDU_PR_initiatingMessage:
Harald Welte350814a2015-09-10 22:32:15 +0200528 rc = rua_rx_initiating_msg(msg, &pdu->choice.initiatingMessage);
Harald Welte318e4d52015-09-10 18:47:08 +0200529 break;
530 case RUA_RUA_PDU_PR_successfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200531 rc = rua_rx_successful_outcome_msg(msg, &pdu->choice.successfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200532 break;
533 case RUA_RUA_PDU_PR_unsuccessfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200534 rc = rua_rx_unsuccessful_outcome_msg(msg, &pdu->choice.unsuccessfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200535 break;
536 default:
Harald Welte37166a22015-12-24 10:12:09 +0100537 LOGP(DRUA, LOGL_NOTICE, "Unknown RUA presence %u\n", pdu->present);
538 rc = -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200539 }
Harald Welte37166a22015-12-24 10:12:09 +0100540
541 return rc;
Harald Welte318e4d52015-09-10 18:47:08 +0200542}
543
544int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg)
545{
546 RUA_RUA_PDU_t _pdu, *pdu = &_pdu;
547 asn_dec_rval_t dec_ret;
548 int rc;
549
550 /* decode and handle to _hnbgw_hnbap_rx() */
551
552 memset(pdu, 0, sizeof(*pdu));
553 dec_ret = aper_decode(NULL, &asn_DEF_RUA_RUA_PDU, (void **) &pdu,
554 msg->data, msgb_length(msg), 0, 0);
555 if (dec_ret.code != RC_OK) {
Harald Weltef42317b2015-12-23 15:36:31 +0100556 LOGP(DRUA, LOGL_ERROR, "Error in ASN.1 decode\n");
Neels Hofmeyra6a68e62016-11-25 13:21:02 +0100557 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200558 }
559
Harald Welte350814a2015-09-10 22:32:15 +0200560 rc = _hnbgw_rua_rx(msg, pdu);
Harald Welte318e4d52015-09-10 18:47:08 +0200561
562 return rc;
563}
564
565
566int hnbgw_rua_init(void)
567{
Harald Weltec4338de2015-12-24 00:40:52 +0100568 return 0;
Harald Welte318e4d52015-09-10 18:47:08 +0200569}