blob: 6190fd0b96537b77eb82a9c406e2aed318b91e1d [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>
27#include <osmocom/sigtran/sua.h>
28
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
42static int hnbgw_rua_tx(struct hnb_context *ctx, struct msgb *msg)
43{
44 if (!msg)
45 return -EINVAL;
46
Harald Welteffa7c0a2015-12-23 00:03:41 +010047 msgb_sctp_ppid(msg) = IUH_PPI_RUA;
Daniel Willmann6480cad2016-01-06 18:06:26 +010048 osmo_stream_srv_send(ctx->conn, msg);
49
50 return 0;
Harald Welte318e4d52015-09-10 18:47:08 +020051}
52
Harald Weltecd5e9812015-12-23 22:14:16 +010053int rua_tx_udt(struct hnb_context *hnb, const uint8_t *data, unsigned int len)
Harald Welte64b4ebe2015-09-10 19:29:59 +020054{
Harald Weltee2e5d4d2015-09-10 23:49:45 +020055 RUA_ConnectionlessTransfer_t out;
56 RUA_ConnectionlessTransferIEs_t ies;
57 struct msgb *msg;
58 int rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +020059
Harald Weltee2e5d4d2015-09-10 23:49:45 +020060 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +010061 ies.ranaP_Message.buf = (uint8_t *) data;
62 ies.ranaP_Message.size = len;
Harald Weltee2e5d4d2015-09-10 23:49:45 +020063
64 /* FIXME: msgb_free(msg)? ownership not yet clear */
65
66 memset(&out, 0, sizeof(out));
67 rc = rua_encode_connectionlesstransferies(&out, &ies);
68 if (rc < 0)
69 return rc;
70
71 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_ConnectionlessTransfer,
72 RUA_Criticality_reject,
73 &asn_DEF_RUA_ConnectionlessTransfer,
74 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +010075 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_ConnectionlessTransfer, &out);
Harald Weltee2e5d4d2015-09-10 23:49:45 +020076
Harald Weltec4338de2015-12-24 00:40:52 +010077 DEBUGP(DRUA, "transmitting RUA payload of %u bytes\n", msgb_length(msg));
Harald Weltee2e5d4d2015-09-10 23:49:45 +020078
Harald Weltec4338de2015-12-24 00:40:52 +010079 return hnbgw_rua_tx(hnb, msg);
Harald Welte64b4ebe2015-09-10 19:29:59 +020080}
81
Harald Weltecd5e9812015-12-23 22:14:16 +010082int rua_tx_dt(struct hnb_context *hnb, int is_ps, uint32_t context_id,
83 const uint8_t *data, unsigned int len)
Harald Welte0f0ea812015-09-11 18:58:28 +020084{
85 RUA_DirectTransfer_t out;
86 RUA_DirectTransferIEs_t ies;
Harald Weltecd5e9812015-12-23 22:14:16 +010087 uint32_t ctxidbuf;
Harald Welte0f0ea812015-09-11 18:58:28 +020088 struct msgb *msg;
89 int rc;
90
91 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +010092 if (is_ps)
93 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
94 else
95 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
96 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
97 ies.ranaP_Message.buf = (uint8_t *) data;
98 ies.ranaP_Message.size = len;
Harald Welte0f0ea812015-09-11 18:58:28 +020099
100 /* FIXME: msgb_free(msg)? ownership not yet clear */
101
102 memset(&out, 0, sizeof(out));
103 rc = rua_encode_directtransferies(&out, &ies);
104 if (rc < 0)
105 return rc;
106
107 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_DirectTransfer,
108 RUA_Criticality_reject,
109 &asn_DEF_RUA_DirectTransfer,
110 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +0100111 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_DirectTransfer, &out);
Harald Welte0f0ea812015-09-11 18:58:28 +0200112
Harald Welte5bea8002015-12-26 23:40:31 +0100113 DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
114 is_ps ? "ps" : "cs", msgb_length(msg));
Harald Welte0f0ea812015-09-11 18:58:28 +0200115
Harald Weltecd5e9812015-12-23 22:14:16 +0100116 return hnbgw_rua_tx(hnb, msg);
Harald Welte0f0ea812015-09-11 18:58:28 +0200117}
118
Harald Weltecd5e9812015-12-23 22:14:16 +0100119int rua_tx_disc(struct hnb_context *hnb, int is_ps, uint32_t context_id,
120 const RUA_Cause_t *cause, const uint8_t *data, unsigned int len)
121{
122 RUA_Disconnect_t out;
123 RUA_DisconnectIEs_t ies;
124 struct msgb *msg;
125 uint32_t ctxidbuf;
126 int rc;
127
128 memset(&ies, 0, sizeof(ies));
129 if (is_ps)
130 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
131 else
132 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
133 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
134 memcpy(&ies.cause, cause, sizeof(ies.cause));
135 if (data && len) {
136 ies.presenceMask |= DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT;
137 ies.ranaP_Message.buf = (uint8_t *) data;
138 ies.ranaP_Message.size = len;
139 }
140
141 /* FIXME: msgb_free(msg)? ownership not yet clear */
142
143 memset(&out, 0, sizeof(out));
144 rc = rua_encode_disconnecties(&out, &ies);
145 if (rc < 0)
146 return rc;
147
148 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_Disconnect,
149 RUA_Criticality_reject,
150 &asn_DEF_RUA_Disconnect,
151 &out);
152 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_Disconnect, &out);
153
Harald Welte5bea8002015-12-26 23:40:31 +0100154 DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
155 is_ps ? "ps" : "cs", msgb_length(msg));
156
Harald Weltecd5e9812015-12-23 22:14:16 +0100157
158 return hnbgw_rua_tx(hnb, msg);
159}
160
161
Harald Welte0f0ea812015-09-11 18:58:28 +0200162
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200163/* forward a RUA message to the SCCP User API to SCCP */
164static int rua_to_scu(struct hnb_context *hnb,
165 CN_DomainIndicator_t cN_DomainIndicator,
Harald Weltec4338de2015-12-24 00:40:52 +0100166 enum osmo_scu_prim_type type,
167 uint32_t context_id, uint32_t cause,
168 const uint8_t *data, unsigned int len)
169{
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200170 struct msgb *msg;
Harald Weltec4338de2015-12-24 00:40:52 +0100171 struct osmo_scu_prim *prim;
172 struct hnbgw_context_map *map;
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200173 struct hnbgw_cnlink *cn;
Harald Weltec4338de2015-12-24 00:40:52 +0100174 int rc;
175
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200176 switch (cN_DomainIndicator) {
177 case RUA_CN_DomainIndicator_cs_domain:
178 cn = hnb->gw->cnlink_cs;
179 break;
180 case RUA_CN_DomainIndicator_ps_domain:
181 cn = hnb->gw->cnlink_ps;
182 break;
183 default:
184 LOGP(DRUA, LOGL_ERROR, "Unsupported Domain %u\n",
185 cN_DomainIndicator);
186 return -1;
187 }
188
Harald Welte49287972015-12-29 19:00:35 +0100189 if (!cn) {
190 DEBUGP(DRUA, "CN=NULL, discarding message\n");
191 return 0;
192 }
193
Harald Weltec4338de2015-12-24 00:40:52 +0100194 prim = (struct osmo_scu_prim *) msgb_put(msg, sizeof(*prim));
195 osmo_prim_init(&prim->oph, SCCP_SAP_USER, type, PRIM_OP_REQUEST, msg);
196
197 map = context_map_alloc_by_hnb(hnb, context_id, cn);
198
199 /* add primitive header */
200 switch (type) {
201 case OSMO_SCU_PRIM_N_CONNECT:
202 prim->u.connect.called_addr;
203 prim->u.connect.calling_addr;
204 prim->u.connect.sccp_class = 2;
205 prim->u.connect.conn_id = map->scu_conn_id;
206 break;
207 case OSMO_SCU_PRIM_N_DATA:
208 prim->u.data.conn_id = map->scu_conn_id;
209 break;
210 case OSMO_SCU_PRIM_N_DISCONNECT:
211 prim->u.disconnect.conn_id = map->scu_conn_id;
212 prim->u.disconnect.cause = cause;
213 break;
214 case OSMO_SCU_PRIM_N_UNITDATA:
215 prim->u.unitdata.called_addr;
216 prim->u.unitdata.calling_addr;
217 break;
218 default:
219 return -EINVAL;
220 }
221
222 /* add optional data section, if needed */
223 if (data && len) {
224 msg->l2h = msgb_put(msg, len);
225 memcpy(msg->l2h, data, len);
226 }
227
228 rc = osmo_sua_user_link_down(cn->sua_link, &prim->oph);
229
230 return rc;
231}
232
233static uint32_t rua_to_scu_cause(RUA_Cause_t *in)
234{
235 /* FIXME: Implement this! */
236#if 0
237 switch (in->present) {
238 case RUA_Cause_PR_NOTHING:
239 break;
240 case RUA_Cause_PR_radioNetwork:
241 switch (in->choice.radioNetwork) {
242 case RUA_CauseRadioNetwork_normal:
243 case RUA_CauseRadioNetwork_connect_failed:
244 case RUA_CauseRadioNetwork_network_release:
245 case RUA_CauseRadioNetwork_unspecified:
246 }
247 break;
248 case RUA_Cause_PR_transport:
249 switch (in->choice.transport) {
250 case RUA_CauseTransport_transport_resource_unavailable:
251 break;
252 case RUA_CauseTransport_unspecified:
253 break;
254 }
255 break;
256 case RUA_Cause_PR_protocol:
257 switch (in->choice.protocol) {
258 case RUA_CauseProtocol_transfer_syntax_error:
259 break;
260 case RUA_CauseProtocol_abstract_syntax_error_reject:
261 break;
262 case RUA_CauseProtocol_abstract_syntax_error_ignore_and_notify:
263 break;
264 case RUA_CauseProtocol_message_not_compatible_with_receiver_state:
265 break;
266 case RUA_CauseProtocol_semantic_error:
267 break;
268 case RUA_CauseProtocol_unspecified:
269 break;
270 case RUA_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
271 break;
272 }
273 break;
274 case RUA_Cause_PR_misc:
275 switch (in->choice.misc) {
276 case RUA_CauseMisc_processing_overload:
277 break;
278 case RUA_CauseMisc_hardware_failure:
279 break;
280 case RUA_CauseMisc_o_and_m_intervention:
281 break;
282 case RUA_CauseMisc_unspecified:
283 break;
284 }
285 break;
286 default:
287 break;
288 }
289#else
290 return 0;
291#endif
292
293}
294
Harald Welte350814a2015-09-10 22:32:15 +0200295static int rua_rx_init_connect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200296{
297 RUA_ConnectIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100298 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200299 uint32_t context_id;
300 int rc;
301
302 rc = rua_decode_connecties(&ies, in);
303 if (rc < 0)
304 return rc;
305
Harald Welteb0de9062015-12-24 14:10:17 +0100306 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200307
Harald Welte37166a22015-12-24 10:12:09 +0100308 DEBUGP(DRUA, "RUA Connect.req(ctx=0x%x, %s)\n", context_id,
Harald Welte64b4ebe2015-09-10 19:29:59 +0200309 ies.establishment_Cause == RUA_Establishment_Cause_emergency_call
310 ? "emergency" : "normal");
Harald Weltec4338de2015-12-24 00:40:52 +0100311
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200312 rc = rua_to_scu(hnb, ies.cN_DomainIndicator, OSMO_SCU_PRIM_N_CONNECT,
Harald Weltec4338de2015-12-24 00:40:52 +0100313 context_id, 0, ies.ranaP_Message.buf,
314 ies.ranaP_Message.size);
315 /* FIXME: what to do with the asn1c-allocated memory */
Daniel Willmann11e912a2016-01-07 13:19:30 +0100316 rua_free_connecties(&ies);
Harald Welte0f0ea812015-09-11 18:58:28 +0200317
318 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200319}
320
Harald Welte350814a2015-09-10 22:32:15 +0200321static int rua_rx_init_disconnect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200322{
323 RUA_DisconnectIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100324 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200325 uint32_t context_id;
Harald Weltec4338de2015-12-24 00:40:52 +0100326 uint32_t scu_cause;
327 uint8_t *ranap_data = NULL;
328 unsigned int ranap_len = 0;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200329 int rc;
330
331 rc = rua_decode_disconnecties(&ies, in);
332 if (rc < 0)
333 return rc;
334
Harald Welteb0de9062015-12-24 14:10:17 +0100335 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Weltec4338de2015-12-24 00:40:52 +0100336 scu_cause = rua_to_scu_cause(&ies.cause);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200337
Harald Welte37166a22015-12-24 10:12:09 +0100338 DEBUGP(DRUA, "RUA Disconnect.req(ctx=0x%x,cause=%s)\n", context_id,
Harald Welte64b4ebe2015-09-10 19:29:59 +0200339 rua_cause_str(&ies.cause));
Harald Welte0f0ea812015-09-11 18:58:28 +0200340
Harald Weltec4338de2015-12-24 00:40:52 +0100341 if (ies.presenceMask & DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT) {
342 ranap_data = ies.ranaP_Message.buf;
343 ranap_len = ies.ranaP_Message.size;
344 }
345
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200346 rc = rua_to_scu(hnb, ies.cN_DomainIndicator,
347 OSMO_SCU_PRIM_N_DISCONNECT,
Harald Weltec4338de2015-12-24 00:40:52 +0100348 context_id, scu_cause, ranap_data, ranap_len);
Neels Hofmeyrfe878092016-11-25 13:13:31 +0100349
Harald Weltec4338de2015-12-24 00:40:52 +0100350 /* FIXME: what to do with the asn1c-allocated memory */
Daniel Willmann11e912a2016-01-07 13:19:30 +0100351 rua_free_disconnecties(&ies);
Harald Weltec4338de2015-12-24 00:40:52 +0100352
Harald Welte0f0ea812015-09-11 18:58:28 +0200353 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200354}
355
Harald Welte350814a2015-09-10 22:32:15 +0200356static int rua_rx_init_dt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200357{
358 RUA_DirectTransferIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100359 struct hnb_context *hnb = msg->dst;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200360 uint32_t context_id;
361 int rc;
362
363 rc = rua_decode_directtransferies(&ies, in);
364 if (rc < 0)
365 return rc;
366
Harald Welteb0de9062015-12-24 14:10:17 +0100367 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200368
Harald Welte37166a22015-12-24 10:12:09 +0100369 DEBUGP(DRUA, "RUA Data.req(ctx=0x%x)\n", context_id);
Harald Weltec4338de2015-12-24 00:40:52 +0100370
Neels Hofmeyr12ed9752017-07-03 16:33:14 +0200371 rc = rua_to_scu(hnb,
372 ies.cN_DomainIndicator,
373 OSMO_SCU_PRIM_N_DATA,
Harald Weltec4338de2015-12-24 00:40:52 +0100374 context_id, 0, ies.ranaP_Message.buf,
375 ies.ranaP_Message.size);
Neels Hofmeyrfe878092016-11-25 13:13:31 +0100376
Harald Weltec4338de2015-12-24 00:40:52 +0100377 /* FIXME: what to do with the asn1c-allocated memory */
Daniel Willmann11e912a2016-01-07 13:19:30 +0100378 rua_free_directtransferies(&ies);
Harald Welte0f0ea812015-09-11 18:58:28 +0200379
380 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200381}
382
Harald Welte350814a2015-09-10 22:32:15 +0200383static int rua_rx_init_udt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200384{
385 RUA_ConnectionlessTransferIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100386 RUA_CN_DomainIndicator_t domain;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200387 int rc;
388
389 rc = rua_decode_connectionlesstransferies(&ies, in);
390 if (rc < 0)
391 return rc;
392
Harald Welte37166a22015-12-24 10:12:09 +0100393 DEBUGP(DRUA, "RUA UData.req()\n");
Harald Welte64b4ebe2015-09-10 19:29:59 +0200394
Harald Weltec4338de2015-12-24 00:40:52 +0100395 /* according tot the spec, we can primarily receive Overload,
396 * Reset, Reset ACK, Error Indication, reset Resource, Reset
397 * Resurce Acknowledge as connecitonless RANAP. There are some
398 * more messages regarding Information Transfer, Direct
399 * Information Transfer and Uplink Information Trnansfer that we
400 * can ignore. In either case, it is RANAP that we need to
401 * decode... */
Harald Welte350814a2015-09-10 22:32:15 +0200402 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
Daniel Willmann11e912a2016-01-07 13:19:30 +0100403 rua_free_connectionlesstransferies(&ies);
Harald Welte350814a2015-09-10 22:32:15 +0200404
405 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200406}
407
Harald Welte350814a2015-09-10 22:32:15 +0200408
409static int rua_rx_init_err_ind(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200410{
411 RUA_ErrorIndicationIEs_t ies;
412 int rc;
413
414 rc = rua_decode_errorindicationies(&ies, in);
415 if (rc < 0)
416 return rc;
417
Harald Welte831e1ee2015-12-25 10:28:55 +0100418 LOGP(DRUA, LOGL_ERROR, "RUA UData.ErrorInd(%s)\n",
419 rua_cause_str(&ies.cause));
Harald Weltec4338de2015-12-24 00:40:52 +0100420
Daniel Willmann11e912a2016-01-07 13:19:30 +0100421 rua_free_errorindicationies(&ies);
Harald Weltec4338de2015-12-24 00:40:52 +0100422 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200423}
Harald Welte318e4d52015-09-10 18:47:08 +0200424
Harald Welte350814a2015-09-10 22:32:15 +0200425static int rua_rx_initiating_msg(struct msgb *msg, RUA_InitiatingMessage_t *imsg)
Harald Welte318e4d52015-09-10 18:47:08 +0200426{
427 int rc;
428
429 switch (imsg->procedureCode) {
430 case RUA_ProcedureCode_id_Connect:
Harald Welte350814a2015-09-10 22:32:15 +0200431 rc = rua_rx_init_connect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200432 break;
433 case RUA_ProcedureCode_id_DirectTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200434 rc = rua_rx_init_dt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200435 break;
436 case RUA_ProcedureCode_id_Disconnect:
Harald Welte350814a2015-09-10 22:32:15 +0200437 rc = rua_rx_init_disconnect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200438 break;
439 case RUA_ProcedureCode_id_ConnectionlessTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200440 rc = rua_rx_init_udt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200441 break;
442 case RUA_ProcedureCode_id_ErrorIndication:
Harald Welte350814a2015-09-10 22:32:15 +0200443 rc = rua_rx_init_err_ind(msg, &imsg->value);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200444 break;
Harald Welte318e4d52015-09-10 18:47:08 +0200445 case RUA_ProcedureCode_id_privateMessage:
Neels Hofmeyr2b5021f2016-11-25 13:25:38 +0100446 LOGP(DRUA, LOGL_NOTICE,
447 "Unhandled: RUA Initiating Msg: Private Msg\n");
448 rc = 0;
Harald Welte318e4d52015-09-10 18:47:08 +0200449 break;
450 default:
Harald Welte37166a22015-12-24 10:12:09 +0100451 LOGP(DRUA, LOGL_NOTICE, "Unknown RUA Procedure %u\n",
452 imsg->procedureCode);
453 rc = -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200454 }
Harald Welte37166a22015-12-24 10:12:09 +0100455
456 return rc;
Harald Welte318e4d52015-09-10 18:47:08 +0200457}
458
Harald Welte350814a2015-09-10 22:32:15 +0200459static int rua_rx_successful_outcome_msg(struct msgb *msg, RUA_SuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200460{
Harald Weltec4338de2015-12-24 00:40:52 +0100461 /* FIXME */
Harald Welte37166a22015-12-24 10:12:09 +0100462 LOGP(DRUA, LOGL_NOTICE, "Unexpected RUA Sucessful Outcome\n");
463 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200464}
465
Harald Welte350814a2015-09-10 22:32:15 +0200466static int rua_rx_unsuccessful_outcome_msg(struct msgb *msg, RUA_UnsuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200467{
Harald Weltec4338de2015-12-24 00:40:52 +0100468 /* FIXME */
Harald Welte37166a22015-12-24 10:12:09 +0100469 LOGP(DRUA, LOGL_NOTICE, "Unexpected RUA Unsucessful Outcome\n");
470 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200471}
472
473
Harald Welte350814a2015-09-10 22:32:15 +0200474static int _hnbgw_rua_rx(struct msgb *msg, RUA_RUA_PDU_t *pdu)
Harald Welte318e4d52015-09-10 18:47:08 +0200475{
476 int rc;
477
478 /* it's a bit odd that we can't dispatch on procedure code, but
479 * that's not possible */
480 switch (pdu->present) {
481 case RUA_RUA_PDU_PR_initiatingMessage:
Harald Welte350814a2015-09-10 22:32:15 +0200482 rc = rua_rx_initiating_msg(msg, &pdu->choice.initiatingMessage);
Harald Welte318e4d52015-09-10 18:47:08 +0200483 break;
484 case RUA_RUA_PDU_PR_successfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200485 rc = rua_rx_successful_outcome_msg(msg, &pdu->choice.successfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200486 break;
487 case RUA_RUA_PDU_PR_unsuccessfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200488 rc = rua_rx_unsuccessful_outcome_msg(msg, &pdu->choice.unsuccessfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200489 break;
490 default:
Harald Welte37166a22015-12-24 10:12:09 +0100491 LOGP(DRUA, LOGL_NOTICE, "Unknown RUA presence %u\n", pdu->present);
492 rc = -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200493 }
Harald Welte37166a22015-12-24 10:12:09 +0100494
495 return rc;
Harald Welte318e4d52015-09-10 18:47:08 +0200496}
497
498int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg)
499{
500 RUA_RUA_PDU_t _pdu, *pdu = &_pdu;
501 asn_dec_rval_t dec_ret;
502 int rc;
503
504 /* decode and handle to _hnbgw_hnbap_rx() */
505
506 memset(pdu, 0, sizeof(*pdu));
507 dec_ret = aper_decode(NULL, &asn_DEF_RUA_RUA_PDU, (void **) &pdu,
508 msg->data, msgb_length(msg), 0, 0);
509 if (dec_ret.code != RC_OK) {
Harald Weltef42317b2015-12-23 15:36:31 +0100510 LOGP(DRUA, LOGL_ERROR, "Error in ASN.1 decode\n");
Neels Hofmeyra6a68e62016-11-25 13:21:02 +0100511 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200512 }
513
Harald Welte350814a2015-09-10 22:32:15 +0200514 rc = _hnbgw_rua_rx(msg, pdu);
Harald Welte318e4d52015-09-10 18:47:08 +0200515
516 return rc;
517}
518
519
520int hnbgw_rua_init(void)
521{
Harald Weltec4338de2015-12-24 00:40:52 +0100522 return 0;
Harald Welte318e4d52015-09-10 18:47:08 +0200523}