blob: 329f990ae8446ff956fd3229edaefd612a0b7d81 [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
41static int hnbgw_rua_tx(struct hnb_context *ctx, struct msgb *msg)
42{
43 if (!msg)
44 return -EINVAL;
45
Harald Welteffa7c0a2015-12-23 00:03:41 +010046 msgb_sctp_ppid(msg) = IUH_PPI_RUA;
Daniel Willmann6480cad2016-01-06 18:06:26 +010047 osmo_stream_srv_send(ctx->conn, msg);
48
49 return 0;
Harald Welte318e4d52015-09-10 18:47:08 +020050}
51
Harald Weltecd5e9812015-12-23 22:14:16 +010052int rua_tx_udt(struct hnb_context *hnb, const uint8_t *data, unsigned int len)
Harald Welte64b4ebe2015-09-10 19:29:59 +020053{
Harald Weltee2e5d4d2015-09-10 23:49:45 +020054 RUA_ConnectionlessTransfer_t out;
55 RUA_ConnectionlessTransferIEs_t ies;
56 struct msgb *msg;
57 int rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +020058
Harald Weltee2e5d4d2015-09-10 23:49:45 +020059 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +010060 ies.ranaP_Message.buf = (uint8_t *) data;
61 ies.ranaP_Message.size = len;
Harald Weltee2e5d4d2015-09-10 23:49:45 +020062
63 /* FIXME: msgb_free(msg)? ownership not yet clear */
64
65 memset(&out, 0, sizeof(out));
66 rc = rua_encode_connectionlesstransferies(&out, &ies);
67 if (rc < 0)
68 return rc;
69
70 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_ConnectionlessTransfer,
71 RUA_Criticality_reject,
72 &asn_DEF_RUA_ConnectionlessTransfer,
73 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +010074 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_ConnectionlessTransfer, &out);
Harald Weltee2e5d4d2015-09-10 23:49:45 +020075
Harald Weltec4338de2015-12-24 00:40:52 +010076 DEBUGP(DRUA, "transmitting RUA payload of %u bytes\n", msgb_length(msg));
Harald Weltee2e5d4d2015-09-10 23:49:45 +020077
Harald Weltec4338de2015-12-24 00:40:52 +010078 return hnbgw_rua_tx(hnb, msg);
Harald Welte64b4ebe2015-09-10 19:29:59 +020079}
80
Harald Weltecd5e9812015-12-23 22:14:16 +010081int rua_tx_dt(struct hnb_context *hnb, int is_ps, uint32_t context_id,
82 const uint8_t *data, unsigned int len)
Harald Welte0f0ea812015-09-11 18:58:28 +020083{
84 RUA_DirectTransfer_t out;
85 RUA_DirectTransferIEs_t ies;
Harald Weltecd5e9812015-12-23 22:14:16 +010086 uint32_t ctxidbuf;
Harald Welte0f0ea812015-09-11 18:58:28 +020087 struct msgb *msg;
88 int rc;
89
90 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +010091 if (is_ps)
92 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
93 else
94 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
95 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
96 ies.ranaP_Message.buf = (uint8_t *) data;
97 ies.ranaP_Message.size = len;
Harald Welte0f0ea812015-09-11 18:58:28 +020098
99 /* FIXME: msgb_free(msg)? ownership not yet clear */
100
101 memset(&out, 0, sizeof(out));
102 rc = rua_encode_directtransferies(&out, &ies);
103 if (rc < 0)
104 return rc;
105
106 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_DirectTransfer,
107 RUA_Criticality_reject,
108 &asn_DEF_RUA_DirectTransfer,
109 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +0100110 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_DirectTransfer, &out);
Harald Welte0f0ea812015-09-11 18:58:28 +0200111
Harald Welte5bea8002015-12-26 23:40:31 +0100112 DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
113 is_ps ? "ps" : "cs", msgb_length(msg));
Harald Welte0f0ea812015-09-11 18:58:28 +0200114
Harald Weltecd5e9812015-12-23 22:14:16 +0100115 return hnbgw_rua_tx(hnb, msg);
Harald Welte0f0ea812015-09-11 18:58:28 +0200116}
117
Harald Weltecd5e9812015-12-23 22:14:16 +0100118int rua_tx_disc(struct hnb_context *hnb, int is_ps, uint32_t context_id,
119 const RUA_Cause_t *cause, const uint8_t *data, unsigned int len)
120{
121 RUA_Disconnect_t out;
122 RUA_DisconnectIEs_t ies;
123 struct msgb *msg;
124 uint32_t ctxidbuf;
125 int rc;
126
127 memset(&ies, 0, sizeof(ies));
128 if (is_ps)
129 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
130 else
131 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
132 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
133 memcpy(&ies.cause, cause, sizeof(ies.cause));
134 if (data && len) {
135 ies.presenceMask |= DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT;
136 ies.ranaP_Message.buf = (uint8_t *) data;
137 ies.ranaP_Message.size = len;
138 }
139
140 /* FIXME: msgb_free(msg)? ownership not yet clear */
141
142 memset(&out, 0, sizeof(out));
143 rc = rua_encode_disconnecties(&out, &ies);
144 if (rc < 0)
145 return rc;
146
147 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_Disconnect,
148 RUA_Criticality_reject,
149 &asn_DEF_RUA_Disconnect,
150 &out);
151 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_Disconnect, &out);
152
Harald Welte5bea8002015-12-26 23:40:31 +0100153 DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
154 is_ps ? "ps" : "cs", msgb_length(msg));
155
Harald Weltecd5e9812015-12-23 22:14:16 +0100156
157 return hnbgw_rua_tx(hnb, msg);
158}
159
160
Harald Welte0f0ea812015-09-11 18:58:28 +0200161
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200162/* forward a RUA message to the SCCP User API to SCCP */
163static int rua_to_scu(struct hnb_context *hnb,
164 CN_DomainIndicator_t cN_DomainIndicator,
Harald Weltec4338de2015-12-24 00:40:52 +0100165 enum osmo_scu_prim_type type,
166 uint32_t context_id, uint32_t cause,
167 const uint8_t *data, unsigned int len)
168{
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200169 struct msgb *msg;
Harald Weltec4338de2015-12-24 00:40:52 +0100170 struct osmo_scu_prim *prim;
171 struct hnbgw_context_map *map;
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200172 struct hnbgw_cnlink *cn = hnb->gw->sccp.cnlink;
173 struct osmo_sccp_addr *remote_addr;
174 bool is_ps;
Harald Weltec4338de2015-12-24 00:40:52 +0100175 int rc;
176
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200177 switch (cN_DomainIndicator) {
178 case RUA_CN_DomainIndicator_cs_domain:
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200179 remote_addr = &hnb->gw->sccp.remote_addr_cs;
180 is_ps = false;
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200181 break;
182 case RUA_CN_DomainIndicator_ps_domain:
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200183 remote_addr = &hnb->gw->sccp.remote_addr_ps;
184 is_ps = true;
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200185 break;
186 default:
187 LOGP(DRUA, LOGL_ERROR, "Unsupported Domain %u\n",
188 cN_DomainIndicator);
189 return -1;
190 }
191
Harald Welte49287972015-12-29 19:00:35 +0100192 if (!cn) {
193 DEBUGP(DRUA, "CN=NULL, discarding message\n");
194 return 0;
195 }
196
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200197 msg = msgb_alloc(1500, "rua_to_sccp");
198
Harald Weltec4338de2015-12-24 00:40:52 +0100199 prim = (struct osmo_scu_prim *) msgb_put(msg, sizeof(*prim));
200 osmo_prim_init(&prim->oph, SCCP_SAP_USER, type, PRIM_OP_REQUEST, msg);
201
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200202 map = context_map_alloc_by_hnb(hnb, context_id, is_ps, cn);
203 OSMO_ASSERT(map);
Harald Weltec4338de2015-12-24 00:40:52 +0100204
205 /* add primitive header */
206 switch (type) {
207 case OSMO_SCU_PRIM_N_CONNECT:
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200208 prim->u.connect.called_addr = *remote_addr;
209 prim->u.connect.calling_addr = cn->gw->sccp.local_addr;
Harald Weltec4338de2015-12-24 00:40:52 +0100210 prim->u.connect.sccp_class = 2;
211 prim->u.connect.conn_id = map->scu_conn_id;
212 break;
213 case OSMO_SCU_PRIM_N_DATA:
214 prim->u.data.conn_id = map->scu_conn_id;
215 break;
216 case OSMO_SCU_PRIM_N_DISCONNECT:
217 prim->u.disconnect.conn_id = map->scu_conn_id;
218 prim->u.disconnect.cause = cause;
219 break;
220 case OSMO_SCU_PRIM_N_UNITDATA:
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200221 prim->u.unitdata.called_addr = *remote_addr;
222 prim->u.unitdata.calling_addr = cn->gw->sccp.local_addr;
Harald Weltec4338de2015-12-24 00:40:52 +0100223 break;
224 default:
225 return -EINVAL;
226 }
227
228 /* add optional data section, if needed */
229 if (data && len) {
230 msg->l2h = msgb_put(msg, len);
231 memcpy(msg->l2h, data, len);
232 }
233
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200234 rc = osmo_sccp_user_sap_down(cn->sccp_user, &prim->oph);
Harald Weltec4338de2015-12-24 00:40:52 +0100235
236 return rc;
237}
238
239static uint32_t rua_to_scu_cause(RUA_Cause_t *in)
240{
241 /* FIXME: Implement this! */
242#if 0
243 switch (in->present) {
244 case RUA_Cause_PR_NOTHING:
245 break;
246 case RUA_Cause_PR_radioNetwork:
247 switch (in->choice.radioNetwork) {
248 case RUA_CauseRadioNetwork_normal:
249 case RUA_CauseRadioNetwork_connect_failed:
250 case RUA_CauseRadioNetwork_network_release:
251 case RUA_CauseRadioNetwork_unspecified:
252 }
253 break;
254 case RUA_Cause_PR_transport:
255 switch (in->choice.transport) {
256 case RUA_CauseTransport_transport_resource_unavailable:
257 break;
258 case RUA_CauseTransport_unspecified:
259 break;
260 }
261 break;
262 case RUA_Cause_PR_protocol:
263 switch (in->choice.protocol) {
264 case RUA_CauseProtocol_transfer_syntax_error:
265 break;
266 case RUA_CauseProtocol_abstract_syntax_error_reject:
267 break;
268 case RUA_CauseProtocol_abstract_syntax_error_ignore_and_notify:
269 break;
270 case RUA_CauseProtocol_message_not_compatible_with_receiver_state:
271 break;
272 case RUA_CauseProtocol_semantic_error:
273 break;
274 case RUA_CauseProtocol_unspecified:
275 break;
276 case RUA_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
277 break;
278 }
279 break;
280 case RUA_Cause_PR_misc:
281 switch (in->choice.misc) {
282 case RUA_CauseMisc_processing_overload:
283 break;
284 case RUA_CauseMisc_hardware_failure:
285 break;
286 case RUA_CauseMisc_o_and_m_intervention:
287 break;
288 case RUA_CauseMisc_unspecified:
289 break;
290 }
291 break;
292 default:
293 break;
294 }
295#else
296 return 0;
297#endif
298
299}
300
Harald Welte350814a2015-09-10 22:32:15 +0200301static int rua_rx_init_connect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200302{
303 RUA_ConnectIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100304 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200305 uint32_t context_id;
306 int rc;
307
308 rc = rua_decode_connecties(&ies, in);
309 if (rc < 0)
310 return rc;
311
Harald Welteb0de9062015-12-24 14:10:17 +0100312 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200313
Harald Welte37166a22015-12-24 10:12:09 +0100314 DEBUGP(DRUA, "RUA Connect.req(ctx=0x%x, %s)\n", context_id,
Harald Welte64b4ebe2015-09-10 19:29:59 +0200315 ies.establishment_Cause == RUA_Establishment_Cause_emergency_call
316 ? "emergency" : "normal");
Harald Weltec4338de2015-12-24 00:40:52 +0100317
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200318 rc = rua_to_scu(hnb, ies.cN_DomainIndicator, OSMO_SCU_PRIM_N_CONNECT,
Harald Weltec4338de2015-12-24 00:40:52 +0100319 context_id, 0, ies.ranaP_Message.buf,
320 ies.ranaP_Message.size);
321 /* FIXME: what to do with the asn1c-allocated memory */
Daniel Willmann11e912a2016-01-07 13:19:30 +0100322 rua_free_connecties(&ies);
Harald Welte0f0ea812015-09-11 18:58:28 +0200323
324 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200325}
326
Harald Welte350814a2015-09-10 22:32:15 +0200327static int rua_rx_init_disconnect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200328{
329 RUA_DisconnectIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100330 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200331 uint32_t context_id;
Harald Weltec4338de2015-12-24 00:40:52 +0100332 uint32_t scu_cause;
333 uint8_t *ranap_data = NULL;
334 unsigned int ranap_len = 0;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200335 int rc;
336
337 rc = rua_decode_disconnecties(&ies, in);
338 if (rc < 0)
339 return rc;
340
Harald Welteb0de9062015-12-24 14:10:17 +0100341 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Weltec4338de2015-12-24 00:40:52 +0100342 scu_cause = rua_to_scu_cause(&ies.cause);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200343
Harald Welte37166a22015-12-24 10:12:09 +0100344 DEBUGP(DRUA, "RUA Disconnect.req(ctx=0x%x,cause=%s)\n", context_id,
Harald Welte64b4ebe2015-09-10 19:29:59 +0200345 rua_cause_str(&ies.cause));
Harald Welte0f0ea812015-09-11 18:58:28 +0200346
Harald Weltec4338de2015-12-24 00:40:52 +0100347 if (ies.presenceMask & DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT) {
348 ranap_data = ies.ranaP_Message.buf;
349 ranap_len = ies.ranaP_Message.size;
350 }
351
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200352 rc = rua_to_scu(hnb, ies.cN_DomainIndicator,
353 OSMO_SCU_PRIM_N_DISCONNECT,
Harald Weltec4338de2015-12-24 00:40:52 +0100354 context_id, scu_cause, ranap_data, ranap_len);
Neels Hofmeyrfe878092016-11-25 13:13:31 +0100355
Harald Weltec4338de2015-12-24 00:40:52 +0100356 /* FIXME: what to do with the asn1c-allocated memory */
Daniel Willmann11e912a2016-01-07 13:19:30 +0100357 rua_free_disconnecties(&ies);
Harald Weltec4338de2015-12-24 00:40:52 +0100358
Harald Welte0f0ea812015-09-11 18:58:28 +0200359 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200360}
361
Harald Welte350814a2015-09-10 22:32:15 +0200362static int rua_rx_init_dt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200363{
364 RUA_DirectTransferIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100365 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200366 uint32_t context_id;
367 int rc;
368
369 rc = rua_decode_directtransferies(&ies, in);
370 if (rc < 0)
371 return rc;
372
Harald Welteb0de9062015-12-24 14:10:17 +0100373 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200374
Harald Welte37166a22015-12-24 10:12:09 +0100375 DEBUGP(DRUA, "RUA Data.req(ctx=0x%x)\n", context_id);
Harald Weltec4338de2015-12-24 00:40:52 +0100376
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200377 rc = rua_to_scu(hnb,
378 ies.cN_DomainIndicator,
379 OSMO_SCU_PRIM_N_DATA,
Harald Weltec4338de2015-12-24 00:40:52 +0100380 context_id, 0, ies.ranaP_Message.buf,
381 ies.ranaP_Message.size);
Neels Hofmeyrfe878092016-11-25 13:13:31 +0100382
Harald Weltec4338de2015-12-24 00:40:52 +0100383 /* FIXME: what to do with the asn1c-allocated memory */
Daniel Willmann11e912a2016-01-07 13:19:30 +0100384 rua_free_directtransferies(&ies);
Harald Welte0f0ea812015-09-11 18:58:28 +0200385
386 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200387}
388
Harald Welte350814a2015-09-10 22:32:15 +0200389static int rua_rx_init_udt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200390{
391 RUA_ConnectionlessTransferIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100392 RUA_CN_DomainIndicator_t domain;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200393 int rc;
394
395 rc = rua_decode_connectionlesstransferies(&ies, in);
396 if (rc < 0)
397 return rc;
398
Harald Welte37166a22015-12-24 10:12:09 +0100399 DEBUGP(DRUA, "RUA UData.req()\n");
Harald Welte64b4ebe2015-09-10 19:29:59 +0200400
Harald Weltec4338de2015-12-24 00:40:52 +0100401 /* according tot the spec, we can primarily receive Overload,
402 * Reset, Reset ACK, Error Indication, reset Resource, Reset
403 * Resurce Acknowledge as connecitonless RANAP. There are some
404 * more messages regarding Information Transfer, Direct
405 * Information Transfer and Uplink Information Trnansfer that we
406 * can ignore. In either case, it is RANAP that we need to
407 * decode... */
Harald Welte350814a2015-09-10 22:32:15 +0200408 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
Daniel Willmann11e912a2016-01-07 13:19:30 +0100409 rua_free_connectionlesstransferies(&ies);
Harald Welte350814a2015-09-10 22:32:15 +0200410
411 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200412}
413
Harald Welte350814a2015-09-10 22:32:15 +0200414
415static int rua_rx_init_err_ind(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200416{
417 RUA_ErrorIndicationIEs_t ies;
418 int rc;
419
420 rc = rua_decode_errorindicationies(&ies, in);
421 if (rc < 0)
422 return rc;
423
Harald Welte831e1ee2015-12-25 10:28:55 +0100424 LOGP(DRUA, LOGL_ERROR, "RUA UData.ErrorInd(%s)\n",
425 rua_cause_str(&ies.cause));
Harald Weltec4338de2015-12-24 00:40:52 +0100426
Daniel Willmann11e912a2016-01-07 13:19:30 +0100427 rua_free_errorindicationies(&ies);
Harald Weltec4338de2015-12-24 00:40:52 +0100428 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200429}
Harald Welte318e4d52015-09-10 18:47:08 +0200430
Harald Welte350814a2015-09-10 22:32:15 +0200431static int rua_rx_initiating_msg(struct msgb *msg, RUA_InitiatingMessage_t *imsg)
Harald Welte318e4d52015-09-10 18:47:08 +0200432{
433 int rc;
434
435 switch (imsg->procedureCode) {
436 case RUA_ProcedureCode_id_Connect:
Harald Welte350814a2015-09-10 22:32:15 +0200437 rc = rua_rx_init_connect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200438 break;
439 case RUA_ProcedureCode_id_DirectTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200440 rc = rua_rx_init_dt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200441 break;
442 case RUA_ProcedureCode_id_Disconnect:
Harald Welte350814a2015-09-10 22:32:15 +0200443 rc = rua_rx_init_disconnect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200444 break;
445 case RUA_ProcedureCode_id_ConnectionlessTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200446 rc = rua_rx_init_udt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200447 break;
448 case RUA_ProcedureCode_id_ErrorIndication:
Harald Welte350814a2015-09-10 22:32:15 +0200449 rc = rua_rx_init_err_ind(msg, &imsg->value);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200450 break;
Harald Welte318e4d52015-09-10 18:47:08 +0200451 case RUA_ProcedureCode_id_privateMessage:
Neels Hofmeyr2b5021f2016-11-25 13:25:38 +0100452 LOGP(DRUA, LOGL_NOTICE,
453 "Unhandled: RUA Initiating Msg: Private Msg\n");
454 rc = 0;
Harald Welte318e4d52015-09-10 18:47:08 +0200455 break;
456 default:
Harald Welte37166a22015-12-24 10:12:09 +0100457 LOGP(DRUA, LOGL_NOTICE, "Unknown RUA Procedure %u\n",
458 imsg->procedureCode);
459 rc = -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200460 }
Harald Welte37166a22015-12-24 10:12:09 +0100461
462 return rc;
Harald Welte318e4d52015-09-10 18:47:08 +0200463}
464
Harald Welte350814a2015-09-10 22:32:15 +0200465static int rua_rx_successful_outcome_msg(struct msgb *msg, RUA_SuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200466{
Harald Weltec4338de2015-12-24 00:40:52 +0100467 /* FIXME */
Harald Welte37166a22015-12-24 10:12:09 +0100468 LOGP(DRUA, LOGL_NOTICE, "Unexpected RUA Sucessful Outcome\n");
469 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200470}
471
Harald Welte350814a2015-09-10 22:32:15 +0200472static int rua_rx_unsuccessful_outcome_msg(struct msgb *msg, RUA_UnsuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200473{
Harald Weltec4338de2015-12-24 00:40:52 +0100474 /* FIXME */
Harald Welte37166a22015-12-24 10:12:09 +0100475 LOGP(DRUA, LOGL_NOTICE, "Unexpected RUA Unsucessful Outcome\n");
476 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200477}
478
479
Harald Welte350814a2015-09-10 22:32:15 +0200480static int _hnbgw_rua_rx(struct msgb *msg, RUA_RUA_PDU_t *pdu)
Harald Welte318e4d52015-09-10 18:47:08 +0200481{
482 int rc;
483
484 /* it's a bit odd that we can't dispatch on procedure code, but
485 * that's not possible */
486 switch (pdu->present) {
487 case RUA_RUA_PDU_PR_initiatingMessage:
Harald Welte350814a2015-09-10 22:32:15 +0200488 rc = rua_rx_initiating_msg(msg, &pdu->choice.initiatingMessage);
Harald Welte318e4d52015-09-10 18:47:08 +0200489 break;
490 case RUA_RUA_PDU_PR_successfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200491 rc = rua_rx_successful_outcome_msg(msg, &pdu->choice.successfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200492 break;
493 case RUA_RUA_PDU_PR_unsuccessfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200494 rc = rua_rx_unsuccessful_outcome_msg(msg, &pdu->choice.unsuccessfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200495 break;
496 default:
Harald Welte37166a22015-12-24 10:12:09 +0100497 LOGP(DRUA, LOGL_NOTICE, "Unknown RUA presence %u\n", pdu->present);
498 rc = -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200499 }
Harald Welte37166a22015-12-24 10:12:09 +0100500
501 return rc;
Harald Welte318e4d52015-09-10 18:47:08 +0200502}
503
504int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg)
505{
506 RUA_RUA_PDU_t _pdu, *pdu = &_pdu;
507 asn_dec_rval_t dec_ret;
508 int rc;
509
510 /* decode and handle to _hnbgw_hnbap_rx() */
511
512 memset(pdu, 0, sizeof(*pdu));
513 dec_ret = aper_decode(NULL, &asn_DEF_RUA_RUA_PDU, (void **) &pdu,
514 msg->data, msgb_length(msg), 0, 0);
515 if (dec_ret.code != RC_OK) {
Harald Weltef42317b2015-12-23 15:36:31 +0100516 LOGP(DRUA, LOGL_ERROR, "Error in ASN.1 decode\n");
Neels Hofmeyra6a68e62016-11-25 13:21:02 +0100517 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200518 }
519
Harald Welte350814a2015-09-10 22:32:15 +0200520 rc = _hnbgw_rua_rx(msg, pdu);
Harald Welte318e4d52015-09-10 18:47:08 +0200521
522 return rc;
523}
524
525
526int hnbgw_rua_init(void)
527{
Harald Weltec4338de2015-12-24 00:40:52 +0100528 return 0;
Harald Welte318e4d52015-09-10 18:47:08 +0200529}