blob: 54c455b71fa14667b3451317ec9e5c086aa08f3f [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 Weltec4338de2015-12-24 00:40:52 +010027
Harald Welte318e4d52015-09-10 18:47:08 +020028#include <unistd.h>
29#include <errno.h>
30#include <string.h>
31
32#include "asn1helpers.h"
33
Neels Hofmeyrdf63de22016-08-18 13:13:55 +020034#include <osmocom/iuh/hnbgw.h>
35#include <osmocom/iuh/hnbgw_ranap.h>
Neels Hofmeyr83457922016-08-26 23:56:44 +020036#include <osmocom/rua/rua_common.h>
37#include <osmocom/rua/rua_ies_defs.h>
Neels Hofmeyrdf63de22016-08-18 13:13:55 +020038#include <osmocom/iuh/context_map.h>
Neels Hofmeyr12ed9752017-07-03 16:33:14 +020039#include <osmocom/hnbap/CN-DomainIndicator.h>
Harald Welte318e4d52015-09-10 18:47:08 +020040
Neels Hofmeyrc3614312017-07-03 14:34:38 +020041static const char *cn_domain_indicator_to_str(CN_DomainIndicator_t cN_DomainIndicator)
42{
43 switch (cN_DomainIndicator) {
44 case RUA_CN_DomainIndicator_cs_domain:
45 return "IuCS";
46 case RUA_CN_DomainIndicator_ps_domain:
47 return "IuPS";
48 default:
49 return "(unknown-domain)";
50 }
51}
52
Harald Welte318e4d52015-09-10 18:47:08 +020053static int hnbgw_rua_tx(struct hnb_context *ctx, struct msgb *msg)
54{
55 if (!msg)
56 return -EINVAL;
57
Harald Welteffa7c0a2015-12-23 00:03:41 +010058 msgb_sctp_ppid(msg) = IUH_PPI_RUA;
Daniel Willmann6480cad2016-01-06 18:06:26 +010059 osmo_stream_srv_send(ctx->conn, msg);
60
61 return 0;
Harald Welte318e4d52015-09-10 18:47:08 +020062}
63
Harald Weltecd5e9812015-12-23 22:14:16 +010064int rua_tx_udt(struct hnb_context *hnb, const uint8_t *data, unsigned int len)
Harald Welte64b4ebe2015-09-10 19:29:59 +020065{
Harald Weltee2e5d4d2015-09-10 23:49:45 +020066 RUA_ConnectionlessTransfer_t out;
67 RUA_ConnectionlessTransferIEs_t ies;
68 struct msgb *msg;
69 int rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +020070
Harald Weltee2e5d4d2015-09-10 23:49:45 +020071 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +010072 ies.ranaP_Message.buf = (uint8_t *) data;
73 ies.ranaP_Message.size = len;
Harald Weltee2e5d4d2015-09-10 23:49:45 +020074
75 /* FIXME: msgb_free(msg)? ownership not yet clear */
76
77 memset(&out, 0, sizeof(out));
78 rc = rua_encode_connectionlesstransferies(&out, &ies);
79 if (rc < 0)
80 return rc;
81
82 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_ConnectionlessTransfer,
83 RUA_Criticality_reject,
84 &asn_DEF_RUA_ConnectionlessTransfer,
85 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +010086 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_ConnectionlessTransfer, &out);
Harald Weltee2e5d4d2015-09-10 23:49:45 +020087
Harald Weltec4338de2015-12-24 00:40:52 +010088 DEBUGP(DRUA, "transmitting RUA payload of %u bytes\n", msgb_length(msg));
Harald Weltee2e5d4d2015-09-10 23:49:45 +020089
Harald Weltec4338de2015-12-24 00:40:52 +010090 return hnbgw_rua_tx(hnb, msg);
Harald Welte64b4ebe2015-09-10 19:29:59 +020091}
92
Harald Weltecd5e9812015-12-23 22:14:16 +010093int rua_tx_dt(struct hnb_context *hnb, int is_ps, uint32_t context_id,
94 const uint8_t *data, unsigned int len)
Harald Welte0f0ea812015-09-11 18:58:28 +020095{
96 RUA_DirectTransfer_t out;
97 RUA_DirectTransferIEs_t ies;
Harald Weltecd5e9812015-12-23 22:14:16 +010098 uint32_t ctxidbuf;
Harald Welte0f0ea812015-09-11 18:58:28 +020099 struct msgb *msg;
100 int rc;
101
102 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +0100103 if (is_ps)
104 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
105 else
106 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
107 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
108 ies.ranaP_Message.buf = (uint8_t *) data;
109 ies.ranaP_Message.size = len;
Harald Welte0f0ea812015-09-11 18:58:28 +0200110
111 /* FIXME: msgb_free(msg)? ownership not yet clear */
112
113 memset(&out, 0, sizeof(out));
114 rc = rua_encode_directtransferies(&out, &ies);
115 if (rc < 0)
116 return rc;
117
118 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_DirectTransfer,
119 RUA_Criticality_reject,
120 &asn_DEF_RUA_DirectTransfer,
121 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +0100122 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_DirectTransfer, &out);
Harald Welte0f0ea812015-09-11 18:58:28 +0200123
Harald Welte5bea8002015-12-26 23:40:31 +0100124 DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
125 is_ps ? "ps" : "cs", msgb_length(msg));
Harald Welte0f0ea812015-09-11 18:58:28 +0200126
Harald Weltecd5e9812015-12-23 22:14:16 +0100127 return hnbgw_rua_tx(hnb, msg);
Harald Welte0f0ea812015-09-11 18:58:28 +0200128}
129
Harald Weltecd5e9812015-12-23 22:14:16 +0100130int rua_tx_disc(struct hnb_context *hnb, int is_ps, uint32_t context_id,
131 const RUA_Cause_t *cause, const uint8_t *data, unsigned int len)
132{
133 RUA_Disconnect_t out;
134 RUA_DisconnectIEs_t ies;
135 struct msgb *msg;
136 uint32_t ctxidbuf;
137 int rc;
138
139 memset(&ies, 0, sizeof(ies));
140 if (is_ps)
141 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
142 else
143 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
144 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
145 memcpy(&ies.cause, cause, sizeof(ies.cause));
146 if (data && len) {
147 ies.presenceMask |= DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT;
148 ies.ranaP_Message.buf = (uint8_t *) data;
149 ies.ranaP_Message.size = len;
150 }
151
152 /* FIXME: msgb_free(msg)? ownership not yet clear */
153
154 memset(&out, 0, sizeof(out));
155 rc = rua_encode_disconnecties(&out, &ies);
156 if (rc < 0)
157 return rc;
158
159 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_Disconnect,
160 RUA_Criticality_reject,
161 &asn_DEF_RUA_Disconnect,
162 &out);
163 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_Disconnect, &out);
164
Harald Welte5bea8002015-12-26 23:40:31 +0100165 DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
166 is_ps ? "ps" : "cs", msgb_length(msg));
167
Harald Weltecd5e9812015-12-23 22:14:16 +0100168
169 return hnbgw_rua_tx(hnb, msg);
170}
171
172
Harald Welte0f0ea812015-09-11 18:58:28 +0200173
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200174/* forward a RUA message to the SCCP User API to SCCP */
175static int rua_to_scu(struct hnb_context *hnb,
176 CN_DomainIndicator_t cN_DomainIndicator,
Harald Weltec4338de2015-12-24 00:40:52 +0100177 enum osmo_scu_prim_type type,
178 uint32_t context_id, uint32_t cause,
179 const uint8_t *data, unsigned int len)
180{
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200181 struct msgb *msg;
Harald Weltec4338de2015-12-24 00:40:52 +0100182 struct osmo_scu_prim *prim;
183 struct hnbgw_context_map *map;
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200184 struct hnbgw_cnlink *cn = hnb->gw->sccp.cnlink;
185 struct osmo_sccp_addr *remote_addr;
186 bool is_ps;
Harald Weltec4338de2015-12-24 00:40:52 +0100187 int rc;
188
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200189 switch (cN_DomainIndicator) {
190 case RUA_CN_DomainIndicator_cs_domain:
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200191 remote_addr = &hnb->gw->sccp.remote_addr_cs;
192 is_ps = false;
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200193 break;
194 case RUA_CN_DomainIndicator_ps_domain:
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200195 remote_addr = &hnb->gw->sccp.remote_addr_ps;
196 is_ps = true;
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200197 break;
198 default:
199 LOGP(DRUA, LOGL_ERROR, "Unsupported Domain %u\n",
200 cN_DomainIndicator);
201 return -1;
202 }
203
Harald Welte49287972015-12-29 19:00:35 +0100204 if (!cn) {
205 DEBUGP(DRUA, "CN=NULL, discarding message\n");
206 return 0;
207 }
208
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200209 msg = msgb_alloc(1500, "rua_to_sccp");
210
Harald Weltec4338de2015-12-24 00:40:52 +0100211 prim = (struct osmo_scu_prim *) msgb_put(msg, sizeof(*prim));
212 osmo_prim_init(&prim->oph, SCCP_SAP_USER, type, PRIM_OP_REQUEST, msg);
213
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200214 map = context_map_alloc_by_hnb(hnb, context_id, is_ps, cn);
215 OSMO_ASSERT(map);
Harald Weltec4338de2015-12-24 00:40:52 +0100216
Neels Hofmeyrc3614312017-07-03 14:34:38 +0200217 DEBUGP(DRUA, "rua_to_scu() %s to %s, rua_ctx_id %u scu_conn_id %u\n",
218 cn_domain_indicator_to_str(cN_DomainIndicator),
219 osmo_sccp_addr_dump(remote_addr),
220 map->rua_ctx_id, map->scu_conn_id);
221
Harald Weltec4338de2015-12-24 00:40:52 +0100222 /* add primitive header */
223 switch (type) {
224 case OSMO_SCU_PRIM_N_CONNECT:
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200225 prim->u.connect.called_addr = *remote_addr;
226 prim->u.connect.calling_addr = cn->gw->sccp.local_addr;
Harald Weltec4338de2015-12-24 00:40:52 +0100227 prim->u.connect.sccp_class = 2;
228 prim->u.connect.conn_id = map->scu_conn_id;
229 break;
230 case OSMO_SCU_PRIM_N_DATA:
231 prim->u.data.conn_id = map->scu_conn_id;
232 break;
233 case OSMO_SCU_PRIM_N_DISCONNECT:
234 prim->u.disconnect.conn_id = map->scu_conn_id;
235 prim->u.disconnect.cause = cause;
236 break;
237 case OSMO_SCU_PRIM_N_UNITDATA:
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200238 prim->u.unitdata.called_addr = *remote_addr;
239 prim->u.unitdata.calling_addr = cn->gw->sccp.local_addr;
Harald Weltec4338de2015-12-24 00:40:52 +0100240 break;
241 default:
242 return -EINVAL;
243 }
244
245 /* add optional data section, if needed */
246 if (data && len) {
247 msg->l2h = msgb_put(msg, len);
248 memcpy(msg->l2h, data, len);
249 }
250
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200251 rc = osmo_sccp_user_sap_down(cn->sccp_user, &prim->oph);
Harald Weltec4338de2015-12-24 00:40:52 +0100252
253 return rc;
254}
255
256static uint32_t rua_to_scu_cause(RUA_Cause_t *in)
257{
258 /* FIXME: Implement this! */
259#if 0
260 switch (in->present) {
261 case RUA_Cause_PR_NOTHING:
262 break;
263 case RUA_Cause_PR_radioNetwork:
264 switch (in->choice.radioNetwork) {
265 case RUA_CauseRadioNetwork_normal:
266 case RUA_CauseRadioNetwork_connect_failed:
267 case RUA_CauseRadioNetwork_network_release:
268 case RUA_CauseRadioNetwork_unspecified:
269 }
270 break;
271 case RUA_Cause_PR_transport:
272 switch (in->choice.transport) {
273 case RUA_CauseTransport_transport_resource_unavailable:
274 break;
275 case RUA_CauseTransport_unspecified:
276 break;
277 }
278 break;
279 case RUA_Cause_PR_protocol:
280 switch (in->choice.protocol) {
281 case RUA_CauseProtocol_transfer_syntax_error:
282 break;
283 case RUA_CauseProtocol_abstract_syntax_error_reject:
284 break;
285 case RUA_CauseProtocol_abstract_syntax_error_ignore_and_notify:
286 break;
287 case RUA_CauseProtocol_message_not_compatible_with_receiver_state:
288 break;
289 case RUA_CauseProtocol_semantic_error:
290 break;
291 case RUA_CauseProtocol_unspecified:
292 break;
293 case RUA_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
294 break;
295 }
296 break;
297 case RUA_Cause_PR_misc:
298 switch (in->choice.misc) {
299 case RUA_CauseMisc_processing_overload:
300 break;
301 case RUA_CauseMisc_hardware_failure:
302 break;
303 case RUA_CauseMisc_o_and_m_intervention:
304 break;
305 case RUA_CauseMisc_unspecified:
306 break;
307 }
308 break;
309 default:
310 break;
311 }
312#else
313 return 0;
314#endif
315
316}
317
Harald Welte350814a2015-09-10 22:32:15 +0200318static int rua_rx_init_connect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200319{
320 RUA_ConnectIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100321 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200322 uint32_t context_id;
323 int rc;
324
325 rc = rua_decode_connecties(&ies, in);
326 if (rc < 0)
327 return rc;
328
Harald Welteb0de9062015-12-24 14:10:17 +0100329 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200330
Neels Hofmeyrc3614312017-07-03 14:34:38 +0200331 DEBUGP(DRUA, "RUA %s Connect.req(ctx=0x%x, %s)\n",
332 cn_domain_indicator_to_str(ies.cN_DomainIndicator),
333 context_id,
334 ies.establishment_Cause == RUA_Establishment_Cause_emergency_call
Harald Welte64b4ebe2015-09-10 19:29:59 +0200335 ? "emergency" : "normal");
Harald Weltec4338de2015-12-24 00:40:52 +0100336
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200337 rc = rua_to_scu(hnb, ies.cN_DomainIndicator, OSMO_SCU_PRIM_N_CONNECT,
Harald Weltec4338de2015-12-24 00:40:52 +0100338 context_id, 0, ies.ranaP_Message.buf,
339 ies.ranaP_Message.size);
340 /* FIXME: what to do with the asn1c-allocated memory */
Daniel Willmann11e912a2016-01-07 13:19:30 +0100341 rua_free_connecties(&ies);
Harald Welte0f0ea812015-09-11 18:58:28 +0200342
343 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200344}
345
Harald Welte350814a2015-09-10 22:32:15 +0200346static int rua_rx_init_disconnect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200347{
348 RUA_DisconnectIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100349 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200350 uint32_t context_id;
Harald Weltec4338de2015-12-24 00:40:52 +0100351 uint32_t scu_cause;
352 uint8_t *ranap_data = NULL;
353 unsigned int ranap_len = 0;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200354 int rc;
355
356 rc = rua_decode_disconnecties(&ies, in);
357 if (rc < 0)
358 return rc;
359
Harald Welteb0de9062015-12-24 14:10:17 +0100360 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Weltec4338de2015-12-24 00:40:52 +0100361 scu_cause = rua_to_scu_cause(&ies.cause);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200362
Harald Welte37166a22015-12-24 10:12:09 +0100363 DEBUGP(DRUA, "RUA Disconnect.req(ctx=0x%x,cause=%s)\n", context_id,
Harald Welte64b4ebe2015-09-10 19:29:59 +0200364 rua_cause_str(&ies.cause));
Harald Welte0f0ea812015-09-11 18:58:28 +0200365
Harald Weltec4338de2015-12-24 00:40:52 +0100366 if (ies.presenceMask & DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT) {
367 ranap_data = ies.ranaP_Message.buf;
368 ranap_len = ies.ranaP_Message.size;
369 }
370
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200371 rc = rua_to_scu(hnb, ies.cN_DomainIndicator,
372 OSMO_SCU_PRIM_N_DISCONNECT,
Harald Weltec4338de2015-12-24 00:40:52 +0100373 context_id, scu_cause, ranap_data, ranap_len);
Neels Hofmeyrfe878092016-11-25 13:13:31 +0100374
Harald Weltec4338de2015-12-24 00:40:52 +0100375 /* FIXME: what to do with the asn1c-allocated memory */
Daniel Willmann11e912a2016-01-07 13:19:30 +0100376 rua_free_disconnecties(&ies);
Harald Weltec4338de2015-12-24 00:40:52 +0100377
Harald Welte0f0ea812015-09-11 18:58:28 +0200378 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200379}
380
Harald Welte350814a2015-09-10 22:32:15 +0200381static int rua_rx_init_dt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200382{
383 RUA_DirectTransferIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100384 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200385 uint32_t context_id;
386 int rc;
387
388 rc = rua_decode_directtransferies(&ies, in);
389 if (rc < 0)
390 return rc;
391
Harald Welteb0de9062015-12-24 14:10:17 +0100392 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200393
Harald Welte37166a22015-12-24 10:12:09 +0100394 DEBUGP(DRUA, "RUA Data.req(ctx=0x%x)\n", context_id);
Harald Weltec4338de2015-12-24 00:40:52 +0100395
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200396 rc = rua_to_scu(hnb,
397 ies.cN_DomainIndicator,
398 OSMO_SCU_PRIM_N_DATA,
Harald Weltec4338de2015-12-24 00:40:52 +0100399 context_id, 0, ies.ranaP_Message.buf,
400 ies.ranaP_Message.size);
Neels Hofmeyrfe878092016-11-25 13:13:31 +0100401
Harald Weltec4338de2015-12-24 00:40:52 +0100402 /* FIXME: what to do with the asn1c-allocated memory */
Daniel Willmann11e912a2016-01-07 13:19:30 +0100403 rua_free_directtransferies(&ies);
Harald Welte0f0ea812015-09-11 18:58:28 +0200404
405 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200406}
407
Harald Welte350814a2015-09-10 22:32:15 +0200408static int rua_rx_init_udt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200409{
410 RUA_ConnectionlessTransferIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100411 RUA_CN_DomainIndicator_t domain;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200412 int rc;
413
414 rc = rua_decode_connectionlesstransferies(&ies, in);
415 if (rc < 0)
416 return rc;
417
Harald Welte37166a22015-12-24 10:12:09 +0100418 DEBUGP(DRUA, "RUA UData.req()\n");
Harald Welte64b4ebe2015-09-10 19:29:59 +0200419
Harald Weltec4338de2015-12-24 00:40:52 +0100420 /* according tot the spec, we can primarily receive Overload,
421 * Reset, Reset ACK, Error Indication, reset Resource, Reset
422 * Resurce Acknowledge as connecitonless RANAP. There are some
423 * more messages regarding Information Transfer, Direct
424 * Information Transfer and Uplink Information Trnansfer that we
425 * can ignore. In either case, it is RANAP that we need to
426 * decode... */
Harald Welte350814a2015-09-10 22:32:15 +0200427 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
Daniel Willmann11e912a2016-01-07 13:19:30 +0100428 rua_free_connectionlesstransferies(&ies);
Harald Welte350814a2015-09-10 22:32:15 +0200429
430 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200431}
432
Harald Welte350814a2015-09-10 22:32:15 +0200433
434static int rua_rx_init_err_ind(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200435{
436 RUA_ErrorIndicationIEs_t ies;
437 int rc;
438
439 rc = rua_decode_errorindicationies(&ies, in);
440 if (rc < 0)
441 return rc;
442
Harald Welte831e1ee2015-12-25 10:28:55 +0100443 LOGP(DRUA, LOGL_ERROR, "RUA UData.ErrorInd(%s)\n",
444 rua_cause_str(&ies.cause));
Harald Weltec4338de2015-12-24 00:40:52 +0100445
Daniel Willmann11e912a2016-01-07 13:19:30 +0100446 rua_free_errorindicationies(&ies);
Harald Weltec4338de2015-12-24 00:40:52 +0100447 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200448}
Harald Welte318e4d52015-09-10 18:47:08 +0200449
Harald Welte350814a2015-09-10 22:32:15 +0200450static int rua_rx_initiating_msg(struct msgb *msg, RUA_InitiatingMessage_t *imsg)
Harald Welte318e4d52015-09-10 18:47:08 +0200451{
452 int rc;
453
454 switch (imsg->procedureCode) {
455 case RUA_ProcedureCode_id_Connect:
Harald Welte350814a2015-09-10 22:32:15 +0200456 rc = rua_rx_init_connect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200457 break;
458 case RUA_ProcedureCode_id_DirectTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200459 rc = rua_rx_init_dt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200460 break;
461 case RUA_ProcedureCode_id_Disconnect:
Harald Welte350814a2015-09-10 22:32:15 +0200462 rc = rua_rx_init_disconnect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200463 break;
464 case RUA_ProcedureCode_id_ConnectionlessTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200465 rc = rua_rx_init_udt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200466 break;
467 case RUA_ProcedureCode_id_ErrorIndication:
Harald Welte350814a2015-09-10 22:32:15 +0200468 rc = rua_rx_init_err_ind(msg, &imsg->value);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200469 break;
Harald Welte318e4d52015-09-10 18:47:08 +0200470 case RUA_ProcedureCode_id_privateMessage:
Neels Hofmeyr2b5021f2016-11-25 13:25:38 +0100471 LOGP(DRUA, LOGL_NOTICE,
472 "Unhandled: RUA Initiating Msg: Private Msg\n");
473 rc = 0;
Harald Welte318e4d52015-09-10 18:47:08 +0200474 break;
475 default:
Harald Welte37166a22015-12-24 10:12:09 +0100476 LOGP(DRUA, LOGL_NOTICE, "Unknown RUA Procedure %u\n",
477 imsg->procedureCode);
478 rc = -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200479 }
Harald Welte37166a22015-12-24 10:12:09 +0100480
481 return rc;
Harald Welte318e4d52015-09-10 18:47:08 +0200482}
483
Harald Welte350814a2015-09-10 22:32:15 +0200484static int rua_rx_successful_outcome_msg(struct msgb *msg, RUA_SuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200485{
Harald Weltec4338de2015-12-24 00:40:52 +0100486 /* FIXME */
Harald Welte37166a22015-12-24 10:12:09 +0100487 LOGP(DRUA, LOGL_NOTICE, "Unexpected RUA Sucessful Outcome\n");
488 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200489}
490
Harald Welte350814a2015-09-10 22:32:15 +0200491static int rua_rx_unsuccessful_outcome_msg(struct msgb *msg, RUA_UnsuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200492{
Harald Weltec4338de2015-12-24 00:40:52 +0100493 /* FIXME */
Harald Welte37166a22015-12-24 10:12:09 +0100494 LOGP(DRUA, LOGL_NOTICE, "Unexpected RUA Unsucessful Outcome\n");
495 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200496}
497
498
Harald Welte350814a2015-09-10 22:32:15 +0200499static int _hnbgw_rua_rx(struct msgb *msg, RUA_RUA_PDU_t *pdu)
Harald Welte318e4d52015-09-10 18:47:08 +0200500{
501 int rc;
502
503 /* it's a bit odd that we can't dispatch on procedure code, but
504 * that's not possible */
505 switch (pdu->present) {
506 case RUA_RUA_PDU_PR_initiatingMessage:
Harald Welte350814a2015-09-10 22:32:15 +0200507 rc = rua_rx_initiating_msg(msg, &pdu->choice.initiatingMessage);
Harald Welte318e4d52015-09-10 18:47:08 +0200508 break;
509 case RUA_RUA_PDU_PR_successfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200510 rc = rua_rx_successful_outcome_msg(msg, &pdu->choice.successfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200511 break;
512 case RUA_RUA_PDU_PR_unsuccessfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200513 rc = rua_rx_unsuccessful_outcome_msg(msg, &pdu->choice.unsuccessfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200514 break;
515 default:
Harald Welte37166a22015-12-24 10:12:09 +0100516 LOGP(DRUA, LOGL_NOTICE, "Unknown RUA presence %u\n", pdu->present);
517 rc = -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200518 }
Harald Welte37166a22015-12-24 10:12:09 +0100519
520 return rc;
Harald Welte318e4d52015-09-10 18:47:08 +0200521}
522
523int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg)
524{
525 RUA_RUA_PDU_t _pdu, *pdu = &_pdu;
526 asn_dec_rval_t dec_ret;
527 int rc;
528
529 /* decode and handle to _hnbgw_hnbap_rx() */
530
531 memset(pdu, 0, sizeof(*pdu));
532 dec_ret = aper_decode(NULL, &asn_DEF_RUA_RUA_PDU, (void **) &pdu,
533 msg->data, msgb_length(msg), 0, 0);
534 if (dec_ret.code != RC_OK) {
Harald Weltef42317b2015-12-23 15:36:31 +0100535 LOGP(DRUA, LOGL_ERROR, "Error in ASN.1 decode\n");
Neels Hofmeyra6a68e62016-11-25 13:21:02 +0100536 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200537 }
538
Harald Welte350814a2015-09-10 22:32:15 +0200539 rc = _hnbgw_rua_rx(msg, pdu);
Harald Welte318e4d52015-09-10 18:47:08 +0200540
541 return rc;
542}
543
544
545int hnbgw_rua_init(void)
546{
Harald Weltec4338de2015-12-24 00:40:52 +0100547 return 0;
Harald Welte318e4d52015-09-10 18:47:08 +0200548}