blob: 98855534c9043dc82222b0fa3a9f5e41a76cf703 [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
35#include "hnbgw.h"
Harald Welte350814a2015-09-10 22:32:15 +020036#include "hnbgw_ranap.h"
Harald Welte318e4d52015-09-10 18:47:08 +020037#include "rua_common.h"
38#include "rua_ies_defs.h"
Harald Weltec4338de2015-12-24 00:40:52 +010039#include "context_map.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;
Harald Welte318e4d52015-09-10 18:47:08 +020047 return osmo_wqueue_enqueue(&ctx->wqueue, msg);
48}
49
Harald Weltecd5e9812015-12-23 22:14:16 +010050int rua_tx_udt(struct hnb_context *hnb, const uint8_t *data, unsigned int len)
Harald Welte64b4ebe2015-09-10 19:29:59 +020051{
Harald Weltee2e5d4d2015-09-10 23:49:45 +020052 RUA_ConnectionlessTransfer_t out;
53 RUA_ConnectionlessTransferIEs_t ies;
54 struct msgb *msg;
55 int rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +020056
Harald Weltee2e5d4d2015-09-10 23:49:45 +020057 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +010058 ies.ranaP_Message.buf = (uint8_t *) data;
59 ies.ranaP_Message.size = len;
Harald Weltee2e5d4d2015-09-10 23:49:45 +020060
61 /* FIXME: msgb_free(msg)? ownership not yet clear */
62
63 memset(&out, 0, sizeof(out));
64 rc = rua_encode_connectionlesstransferies(&out, &ies);
65 if (rc < 0)
66 return rc;
67
68 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_ConnectionlessTransfer,
69 RUA_Criticality_reject,
70 &asn_DEF_RUA_ConnectionlessTransfer,
71 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +010072 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_ConnectionlessTransfer, &out);
Harald Weltee2e5d4d2015-09-10 23:49:45 +020073
Harald Weltec4338de2015-12-24 00:40:52 +010074 DEBUGP(DRUA, "transmitting RUA payload of %u bytes\n", msgb_length(msg));
Harald Weltee2e5d4d2015-09-10 23:49:45 +020075
Harald Weltec4338de2015-12-24 00:40:52 +010076 return hnbgw_rua_tx(hnb, msg);
Harald Welte64b4ebe2015-09-10 19:29:59 +020077}
78
Harald Weltecd5e9812015-12-23 22:14:16 +010079int rua_tx_dt(struct hnb_context *hnb, int is_ps, uint32_t context_id,
80 const uint8_t *data, unsigned int len)
Harald Welte0f0ea812015-09-11 18:58:28 +020081{
82 RUA_DirectTransfer_t out;
83 RUA_DirectTransferIEs_t ies;
Harald Weltecd5e9812015-12-23 22:14:16 +010084 uint32_t ctxidbuf;
Harald Welte0f0ea812015-09-11 18:58:28 +020085 struct msgb *msg;
86 int rc;
87
88 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +010089 if (is_ps)
90 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
91 else
92 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
93 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
94 ies.ranaP_Message.buf = (uint8_t *) data;
95 ies.ranaP_Message.size = len;
Harald Welte0f0ea812015-09-11 18:58:28 +020096
97 /* FIXME: msgb_free(msg)? ownership not yet clear */
98
99 memset(&out, 0, sizeof(out));
100 rc = rua_encode_directtransferies(&out, &ies);
101 if (rc < 0)
102 return rc;
103
104 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_DirectTransfer,
105 RUA_Criticality_reject,
106 &asn_DEF_RUA_DirectTransfer,
107 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +0100108 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_DirectTransfer, &out);
Harald Welte0f0ea812015-09-11 18:58:28 +0200109
Harald Welte5bea8002015-12-26 23:40:31 +0100110 DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
111 is_ps ? "ps" : "cs", msgb_length(msg));
Harald Welte0f0ea812015-09-11 18:58:28 +0200112
Harald Weltecd5e9812015-12-23 22:14:16 +0100113 return hnbgw_rua_tx(hnb, msg);
Harald Welte0f0ea812015-09-11 18:58:28 +0200114}
115
Harald Weltecd5e9812015-12-23 22:14:16 +0100116int rua_tx_disc(struct hnb_context *hnb, int is_ps, uint32_t context_id,
117 const RUA_Cause_t *cause, const uint8_t *data, unsigned int len)
118{
119 RUA_Disconnect_t out;
120 RUA_DisconnectIEs_t ies;
121 struct msgb *msg;
122 uint32_t ctxidbuf;
123 int rc;
124
125 memset(&ies, 0, sizeof(ies));
126 if (is_ps)
127 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
128 else
129 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
130 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
131 memcpy(&ies.cause, cause, sizeof(ies.cause));
132 if (data && len) {
133 ies.presenceMask |= DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT;
134 ies.ranaP_Message.buf = (uint8_t *) data;
135 ies.ranaP_Message.size = len;
136 }
137
138 /* FIXME: msgb_free(msg)? ownership not yet clear */
139
140 memset(&out, 0, sizeof(out));
141 rc = rua_encode_disconnecties(&out, &ies);
142 if (rc < 0)
143 return rc;
144
145 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_Disconnect,
146 RUA_Criticality_reject,
147 &asn_DEF_RUA_Disconnect,
148 &out);
149 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_Disconnect, &out);
150
Harald Welte5bea8002015-12-26 23:40:31 +0100151 DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n",
152 is_ps ? "ps" : "cs", msgb_length(msg));
153
Harald Weltecd5e9812015-12-23 22:14:16 +0100154
155 return hnbgw_rua_tx(hnb, msg);
156}
157
158
Harald Welte0f0ea812015-09-11 18:58:28 +0200159
Harald Weltec4338de2015-12-24 00:40:52 +0100160/* forward a RUA message to the SCCP User API to SCCP/SUA */
161static int rua_to_scu(struct hnb_context *hnb, struct hnbgw_cnlink *cn,
162 enum osmo_scu_prim_type type,
163 uint32_t context_id, uint32_t cause,
164 const uint8_t *data, unsigned int len)
165{
166 struct msgb *msg = msgb_alloc(1500, "rua_to_sua");
167 struct osmo_scu_prim *prim;
168 struct hnbgw_context_map *map;
169 int rc;
170
Harald Welte49287972015-12-29 19:00:35 +0100171 if (!cn) {
172 DEBUGP(DRUA, "CN=NULL, discarding message\n");
173 return 0;
174 }
175
Harald Weltec4338de2015-12-24 00:40:52 +0100176 prim = (struct osmo_scu_prim *) msgb_put(msg, sizeof(*prim));
177 osmo_prim_init(&prim->oph, SCCP_SAP_USER, type, PRIM_OP_REQUEST, msg);
178
179 map = context_map_alloc_by_hnb(hnb, context_id, cn);
180
181 /* add primitive header */
182 switch (type) {
183 case OSMO_SCU_PRIM_N_CONNECT:
184 prim->u.connect.called_addr;
185 prim->u.connect.calling_addr;
186 prim->u.connect.sccp_class = 2;
187 prim->u.connect.conn_id = map->scu_conn_id;
188 break;
189 case OSMO_SCU_PRIM_N_DATA:
190 prim->u.data.conn_id = map->scu_conn_id;
191 break;
192 case OSMO_SCU_PRIM_N_DISCONNECT:
193 prim->u.disconnect.conn_id = map->scu_conn_id;
194 prim->u.disconnect.cause = cause;
195 break;
196 case OSMO_SCU_PRIM_N_UNITDATA:
197 prim->u.unitdata.called_addr;
198 prim->u.unitdata.calling_addr;
199 break;
200 default:
201 return -EINVAL;
202 }
203
204 /* add optional data section, if needed */
205 if (data && len) {
206 msg->l2h = msgb_put(msg, len);
207 memcpy(msg->l2h, data, len);
208 }
209
210 rc = osmo_sua_user_link_down(cn->sua_link, &prim->oph);
211
212 return rc;
213}
214
215static uint32_t rua_to_scu_cause(RUA_Cause_t *in)
216{
217 /* FIXME: Implement this! */
218#if 0
219 switch (in->present) {
220 case RUA_Cause_PR_NOTHING:
221 break;
222 case RUA_Cause_PR_radioNetwork:
223 switch (in->choice.radioNetwork) {
224 case RUA_CauseRadioNetwork_normal:
225 case RUA_CauseRadioNetwork_connect_failed:
226 case RUA_CauseRadioNetwork_network_release:
227 case RUA_CauseRadioNetwork_unspecified:
228 }
229 break;
230 case RUA_Cause_PR_transport:
231 switch (in->choice.transport) {
232 case RUA_CauseTransport_transport_resource_unavailable:
233 break;
234 case RUA_CauseTransport_unspecified:
235 break;
236 }
237 break;
238 case RUA_Cause_PR_protocol:
239 switch (in->choice.protocol) {
240 case RUA_CauseProtocol_transfer_syntax_error:
241 break;
242 case RUA_CauseProtocol_abstract_syntax_error_reject:
243 break;
244 case RUA_CauseProtocol_abstract_syntax_error_ignore_and_notify:
245 break;
246 case RUA_CauseProtocol_message_not_compatible_with_receiver_state:
247 break;
248 case RUA_CauseProtocol_semantic_error:
249 break;
250 case RUA_CauseProtocol_unspecified:
251 break;
252 case RUA_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
253 break;
254 }
255 break;
256 case RUA_Cause_PR_misc:
257 switch (in->choice.misc) {
258 case RUA_CauseMisc_processing_overload:
259 break;
260 case RUA_CauseMisc_hardware_failure:
261 break;
262 case RUA_CauseMisc_o_and_m_intervention:
263 break;
264 case RUA_CauseMisc_unspecified:
265 break;
266 }
267 break;
268 default:
269 break;
270 }
271#else
272 return 0;
273#endif
274
275}
276
Harald Welte350814a2015-09-10 22:32:15 +0200277static int rua_rx_init_connect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200278{
279 RUA_ConnectIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100280 struct hnb_context *hnb = msg->dst;
281 struct hnbgw_cnlink *cn;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200282 uint32_t context_id;
283 int rc;
284
285 rc = rua_decode_connecties(&ies, in);
286 if (rc < 0)
287 return rc;
288
Harald Welteb0de9062015-12-24 14:10:17 +0100289 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200290
Harald Weltec4338de2015-12-24 00:40:52 +0100291 /* route to CS (MSC) or PS (SGSN) domain */
292 switch (ies.cN_DomainIndicator) {
293 case RUA_CN_DomainIndicator_cs_domain:
294 cn = hnb->gw->cnlink_cs;
295 break;
296 case RUA_CN_DomainIndicator_ps_domain:
297 cn = hnb->gw->cnlink_ps;
298 break;
Harald Welte5bea8002015-12-26 23:40:31 +0100299 default:
300 LOGP(DRUA, LOGL_ERROR, "Unsupported Domain %u\n",
301 ies.cN_DomainIndicator);
302 return -1;
Harald Weltec4338de2015-12-24 00:40:52 +0100303 }
304
Harald Welte37166a22015-12-24 10:12:09 +0100305 DEBUGP(DRUA, "RUA Connect.req(ctx=0x%x, %s)\n", context_id,
Harald Welte64b4ebe2015-09-10 19:29:59 +0200306 ies.establishment_Cause == RUA_Establishment_Cause_emergency_call
307 ? "emergency" : "normal");
Harald Weltec4338de2015-12-24 00:40:52 +0100308
309 rc = rua_to_scu(hnb, cn, OSMO_SCU_PRIM_N_CONNECT,
310 context_id, 0, ies.ranaP_Message.buf,
311 ies.ranaP_Message.size);
312 /* FIXME: what to do with the asn1c-allocated memory */
Harald Welte0f0ea812015-09-11 18:58:28 +0200313
314 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200315}
316
Harald Welte350814a2015-09-10 22:32:15 +0200317static int rua_rx_init_disconnect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200318{
319 RUA_DisconnectIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100320 struct hnb_context *hnb = msg->dst;
321 struct hnbgw_cnlink *cn;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200322 uint32_t context_id;
Harald Weltec4338de2015-12-24 00:40:52 +0100323 uint32_t scu_cause;
324 uint8_t *ranap_data = NULL;
325 unsigned int ranap_len = 0;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200326 int rc;
327
328 rc = rua_decode_disconnecties(&ies, in);
329 if (rc < 0)
330 return rc;
331
Harald Welteb0de9062015-12-24 14:10:17 +0100332 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Weltec4338de2015-12-24 00:40:52 +0100333 scu_cause = rua_to_scu_cause(&ies.cause);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200334
Harald Welte37166a22015-12-24 10:12:09 +0100335 DEBUGP(DRUA, "RUA Disconnect.req(ctx=0x%x,cause=%s)\n", context_id,
Harald Welte64b4ebe2015-09-10 19:29:59 +0200336 rua_cause_str(&ies.cause));
Harald Welte0f0ea812015-09-11 18:58:28 +0200337
Harald Weltec4338de2015-12-24 00:40:52 +0100338 /* route to CS (MSC) or PS (SGSN) domain */
339 switch (ies.cN_DomainIndicator) {
340 case RUA_CN_DomainIndicator_cs_domain:
341 cn = hnb->gw->cnlink_cs;
342 break;
343 case RUA_CN_DomainIndicator_ps_domain:
344 cn = hnb->gw->cnlink_ps;
345 break;
346 }
347
348 if (ies.presenceMask & DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT) {
349 ranap_data = ies.ranaP_Message.buf;
350 ranap_len = ies.ranaP_Message.size;
351 }
352
353 rc = rua_to_scu(hnb, cn, OSMO_SCU_PRIM_N_DISCONNECT,
354 context_id, scu_cause, ranap_data, ranap_len);
355 /* FIXME: what to do with the asn1c-allocated memory */
356
Harald Welte0f0ea812015-09-11 18:58:28 +0200357 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200358}
359
Harald Welte350814a2015-09-10 22:32:15 +0200360static int rua_rx_init_dt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200361{
362 RUA_DirectTransferIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100363 struct hnb_context *hnb = msg->dst;
364 struct hnbgw_cnlink *cn;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200365 uint32_t context_id;
366 int rc;
367
368 rc = rua_decode_directtransferies(&ies, in);
369 if (rc < 0)
370 return rc;
371
Harald Welteb0de9062015-12-24 14:10:17 +0100372 context_id = asn1bitstr_to_u24(&ies.context_ID);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200373
Harald Welte37166a22015-12-24 10:12:09 +0100374 DEBUGP(DRUA, "RUA Data.req(ctx=0x%x)\n", context_id);
Harald Weltec4338de2015-12-24 00:40:52 +0100375
376 /* route to CS (MSC) or PS (SGSN) domain */
377 switch (ies.cN_DomainIndicator) {
378 case RUA_CN_DomainIndicator_cs_domain:
379 cn = hnb->gw->cnlink_cs;
380 break;
381 case RUA_CN_DomainIndicator_ps_domain:
382 cn = hnb->gw->cnlink_ps;
383 break;
384 }
385
386 rc = rua_to_scu(hnb, cn, OSMO_SCU_PRIM_N_DATA,
387 context_id, 0, ies.ranaP_Message.buf,
388 ies.ranaP_Message.size);
389 /* FIXME: what to do with the asn1c-allocated memory */
Harald Welte0f0ea812015-09-11 18:58:28 +0200390
391 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200392
393}
394
Harald Welte350814a2015-09-10 22:32:15 +0200395static int rua_rx_init_udt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200396{
397 RUA_ConnectionlessTransferIEs_t ies;
Harald Weltec4338de2015-12-24 00:40:52 +0100398 RUA_CN_DomainIndicator_t domain;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200399 int rc;
400
401 rc = rua_decode_connectionlesstransferies(&ies, in);
402 if (rc < 0)
403 return rc;
404
Harald Welte37166a22015-12-24 10:12:09 +0100405 DEBUGP(DRUA, "RUA UData.req()\n");
Harald Welte64b4ebe2015-09-10 19:29:59 +0200406
Harald Weltec4338de2015-12-24 00:40:52 +0100407 /* according tot the spec, we can primarily receive Overload,
408 * Reset, Reset ACK, Error Indication, reset Resource, Reset
409 * Resurce Acknowledge as connecitonless RANAP. There are some
410 * more messages regarding Information Transfer, Direct
411 * Information Transfer and Uplink Information Trnansfer that we
412 * can ignore. In either case, it is RANAP that we need to
413 * decode... */
Harald Welte350814a2015-09-10 22:32:15 +0200414 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
Harald Welte350814a2015-09-10 22:32:15 +0200415
416 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200417}
418
Harald Welte350814a2015-09-10 22:32:15 +0200419
420static int rua_rx_init_err_ind(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200421{
422 RUA_ErrorIndicationIEs_t ies;
423 int rc;
424
425 rc = rua_decode_errorindicationies(&ies, in);
426 if (rc < 0)
427 return rc;
428
Harald Welte831e1ee2015-12-25 10:28:55 +0100429 LOGP(DRUA, LOGL_ERROR, "RUA UData.ErrorInd(%s)\n",
430 rua_cause_str(&ies.cause));
Harald Weltec4338de2015-12-24 00:40:52 +0100431
432 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200433}
Harald Welte318e4d52015-09-10 18:47:08 +0200434
Harald Welte350814a2015-09-10 22:32:15 +0200435static int rua_rx_initiating_msg(struct msgb *msg, RUA_InitiatingMessage_t *imsg)
Harald Welte318e4d52015-09-10 18:47:08 +0200436{
437 int rc;
438
439 switch (imsg->procedureCode) {
440 case RUA_ProcedureCode_id_Connect:
Harald Welte350814a2015-09-10 22:32:15 +0200441 rc = rua_rx_init_connect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200442 break;
443 case RUA_ProcedureCode_id_DirectTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200444 rc = rua_rx_init_dt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200445 break;
446 case RUA_ProcedureCode_id_Disconnect:
Harald Welte350814a2015-09-10 22:32:15 +0200447 rc = rua_rx_init_disconnect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200448 break;
449 case RUA_ProcedureCode_id_ConnectionlessTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200450 rc = rua_rx_init_udt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200451 break;
452 case RUA_ProcedureCode_id_ErrorIndication:
Harald Welte350814a2015-09-10 22:32:15 +0200453 rc = rua_rx_init_err_ind(msg, &imsg->value);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200454 break;
Harald Welte318e4d52015-09-10 18:47:08 +0200455 case RUA_ProcedureCode_id_privateMessage:
456 break;
457 default:
Harald Welte37166a22015-12-24 10:12:09 +0100458 LOGP(DRUA, LOGL_NOTICE, "Unknown RUA Procedure %u\n",
459 imsg->procedureCode);
460 rc = -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200461 }
Harald Welte37166a22015-12-24 10:12:09 +0100462
463 return rc;
Harald Welte318e4d52015-09-10 18:47:08 +0200464}
465
Harald Welte350814a2015-09-10 22:32:15 +0200466static int rua_rx_successful_outcome_msg(struct msgb *msg, RUA_SuccessfulOutcome_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 Sucessful Outcome\n");
470 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200471}
472
Harald Welte350814a2015-09-10 22:32:15 +0200473static int rua_rx_unsuccessful_outcome_msg(struct msgb *msg, RUA_UnsuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200474{
Harald Weltec4338de2015-12-24 00:40:52 +0100475 /* FIXME */
Harald Welte37166a22015-12-24 10:12:09 +0100476 LOGP(DRUA, LOGL_NOTICE, "Unexpected RUA Unsucessful Outcome\n");
477 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200478}
479
480
Harald Welte350814a2015-09-10 22:32:15 +0200481static int _hnbgw_rua_rx(struct msgb *msg, RUA_RUA_PDU_t *pdu)
Harald Welte318e4d52015-09-10 18:47:08 +0200482{
483 int rc;
484
485 /* it's a bit odd that we can't dispatch on procedure code, but
486 * that's not possible */
487 switch (pdu->present) {
488 case RUA_RUA_PDU_PR_initiatingMessage:
Harald Welte350814a2015-09-10 22:32:15 +0200489 rc = rua_rx_initiating_msg(msg, &pdu->choice.initiatingMessage);
Harald Welte318e4d52015-09-10 18:47:08 +0200490 break;
491 case RUA_RUA_PDU_PR_successfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200492 rc = rua_rx_successful_outcome_msg(msg, &pdu->choice.successfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200493 break;
494 case RUA_RUA_PDU_PR_unsuccessfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200495 rc = rua_rx_unsuccessful_outcome_msg(msg, &pdu->choice.unsuccessfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200496 break;
497 default:
Harald Welte37166a22015-12-24 10:12:09 +0100498 LOGP(DRUA, LOGL_NOTICE, "Unknown RUA presence %u\n", pdu->present);
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
505int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg)
506{
507 RUA_RUA_PDU_t _pdu, *pdu = &_pdu;
508 asn_dec_rval_t dec_ret;
509 int rc;
510
511 /* decode and handle to _hnbgw_hnbap_rx() */
512
513 memset(pdu, 0, sizeof(*pdu));
514 dec_ret = aper_decode(NULL, &asn_DEF_RUA_RUA_PDU, (void **) &pdu,
515 msg->data, msgb_length(msg), 0, 0);
516 if (dec_ret.code != RC_OK) {
Harald Weltef42317b2015-12-23 15:36:31 +0100517 LOGP(DRUA, LOGL_ERROR, "Error in ASN.1 decode\n");
Harald Welte318e4d52015-09-10 18:47:08 +0200518 return rc;
519 }
520
Harald Welte350814a2015-09-10 22:32:15 +0200521 rc = _hnbgw_rua_rx(msg, pdu);
Harald Welte318e4d52015-09-10 18:47:08 +0200522
523 return rc;
524}
525
526
527int hnbgw_rua_init(void)
528{
Harald Weltec4338de2015-12-24 00:40:52 +0100529 return 0;
Harald Welte318e4d52015-09-10 18:47:08 +0200530}