blob: eb4a56a5ae1c792423c37dd6bfd30e9dff02d0d2 [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
26#include <unistd.h>
27#include <errno.h>
28#include <string.h>
29
30#include "asn1helpers.h"
31
32#include "hnbgw.h"
Harald Welte350814a2015-09-10 22:32:15 +020033#include "hnbgw_ranap.h"
Harald Welte318e4d52015-09-10 18:47:08 +020034#include "rua_common.h"
35#include "rua_ies_defs.h"
36
37static int hnbgw_rua_tx(struct hnb_context *ctx, struct msgb *msg)
38{
39 if (!msg)
40 return -EINVAL;
41
Harald Welteffa7c0a2015-12-23 00:03:41 +010042 msgb_sctp_ppid(msg) = IUH_PPI_RUA;
Harald Welte318e4d52015-09-10 18:47:08 +020043 return osmo_wqueue_enqueue(&ctx->wqueue, msg);
44}
45
Harald Weltecd5e9812015-12-23 22:14:16 +010046int rua_tx_udt(struct hnb_context *hnb, const uint8_t *data, unsigned int len)
Harald Welte64b4ebe2015-09-10 19:29:59 +020047{
Harald Weltee2e5d4d2015-09-10 23:49:45 +020048 RUA_ConnectionlessTransfer_t out;
49 RUA_ConnectionlessTransferIEs_t ies;
50 struct msgb *msg;
51 int rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +020052
Harald Weltee2e5d4d2015-09-10 23:49:45 +020053 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +010054 ies.ranaP_Message.buf = (uint8_t *) data;
55 ies.ranaP_Message.size = len;
Harald Weltee2e5d4d2015-09-10 23:49:45 +020056
57 /* FIXME: msgb_free(msg)? ownership not yet clear */
58
59 memset(&out, 0, sizeof(out));
60 rc = rua_encode_connectionlesstransferies(&out, &ies);
61 if (rc < 0)
62 return rc;
63
64 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_ConnectionlessTransfer,
65 RUA_Criticality_reject,
66 &asn_DEF_RUA_ConnectionlessTransfer,
67 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +010068 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_ConnectionlessTransfer, &out);
Harald Weltee2e5d4d2015-09-10 23:49:45 +020069
70 DEBUGP(DMAIN, "transmitting RUA payload of %u bytes\n", msgb_length(msg));
71
72 return hnbgw_rua_tx(msg->dst, msg);
Harald Welte64b4ebe2015-09-10 19:29:59 +020073}
74
Harald Weltecd5e9812015-12-23 22:14:16 +010075int rua_tx_dt(struct hnb_context *hnb, int is_ps, uint32_t context_id,
76 const uint8_t *data, unsigned int len)
Harald Welte0f0ea812015-09-11 18:58:28 +020077{
78 RUA_DirectTransfer_t out;
79 RUA_DirectTransferIEs_t ies;
Harald Weltecd5e9812015-12-23 22:14:16 +010080 uint32_t ctxidbuf;
Harald Welte0f0ea812015-09-11 18:58:28 +020081 struct msgb *msg;
82 int rc;
83
84 memset(&ies, 0, sizeof(ies));
Harald Weltecd5e9812015-12-23 22:14:16 +010085 if (is_ps)
86 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
87 else
88 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
89 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
90 ies.ranaP_Message.buf = (uint8_t *) data;
91 ies.ranaP_Message.size = len;
Harald Welte0f0ea812015-09-11 18:58:28 +020092
93 /* FIXME: msgb_free(msg)? ownership not yet clear */
94
95 memset(&out, 0, sizeof(out));
96 rc = rua_encode_directtransferies(&out, &ies);
97 if (rc < 0)
98 return rc;
99
100 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_DirectTransfer,
101 RUA_Criticality_reject,
102 &asn_DEF_RUA_DirectTransfer,
103 &out);
Harald Weltecd5e9812015-12-23 22:14:16 +0100104 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_DirectTransfer, &out);
Harald Welte0f0ea812015-09-11 18:58:28 +0200105
106 DEBUGP(DMAIN, "transmitting RUA payload of %u bytes\n", msgb_length(msg));
107
Harald Weltecd5e9812015-12-23 22:14:16 +0100108 return hnbgw_rua_tx(hnb, msg);
Harald Welte0f0ea812015-09-11 18:58:28 +0200109}
110
Harald Weltecd5e9812015-12-23 22:14:16 +0100111int rua_tx_disc(struct hnb_context *hnb, int is_ps, uint32_t context_id,
112 const RUA_Cause_t *cause, const uint8_t *data, unsigned int len)
113{
114 RUA_Disconnect_t out;
115 RUA_DisconnectIEs_t ies;
116 struct msgb *msg;
117 uint32_t ctxidbuf;
118 int rc;
119
120 memset(&ies, 0, sizeof(ies));
121 if (is_ps)
122 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain;
123 else
124 ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain;
125 asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id);
126 memcpy(&ies.cause, cause, sizeof(ies.cause));
127 if (data && len) {
128 ies.presenceMask |= DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT;
129 ies.ranaP_Message.buf = (uint8_t *) data;
130 ies.ranaP_Message.size = len;
131 }
132
133 /* FIXME: msgb_free(msg)? ownership not yet clear */
134
135 memset(&out, 0, sizeof(out));
136 rc = rua_encode_disconnecties(&out, &ies);
137 if (rc < 0)
138 return rc;
139
140 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_Disconnect,
141 RUA_Criticality_reject,
142 &asn_DEF_RUA_Disconnect,
143 &out);
144 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_Disconnect, &out);
145
146 DEBUGP(DMAIN, "transmitting RUA payload of %u bytes\n", msgb_length(msg));
147
148 return hnbgw_rua_tx(hnb, msg);
149}
150
151
Harald Welte0f0ea812015-09-11 18:58:28 +0200152
Harald Welte350814a2015-09-10 22:32:15 +0200153static int rua_rx_init_connect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200154{
155 RUA_ConnectIEs_t ies;
156 uint32_t context_id;
157 int rc;
158
159 rc = rua_decode_connecties(&ies, in);
160 if (rc < 0)
161 return rc;
162
163 context_id = asn1bitstr_to_u32(&ies.context_ID);
164
165 DEBUGP(DMAIN, "Connect.req(ctx=0x%x, %s)\n", context_id,
166 ies.establishment_Cause == RUA_Establishment_Cause_emergency_call
167 ? "emergency" : "normal");
Harald Welte0f0ea812015-09-11 18:58:28 +0200168 /* FIXME: route to CS (MSC) or PS (SGSN) domain */
169 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
170
171 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200172}
173
Harald Welte350814a2015-09-10 22:32:15 +0200174static int rua_rx_init_disconnect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200175{
176 RUA_DisconnectIEs_t ies;
177 uint32_t context_id;
178 int rc;
179
180 rc = rua_decode_disconnecties(&ies, in);
181 if (rc < 0)
182 return rc;
183
184 context_id = asn1bitstr_to_u32(&ies.context_ID);
185
186 DEBUGP(DMAIN, "Disconnect.req(ctx=0x%x,cause=%s)\n", context_id,
187 rua_cause_str(&ies.cause));
Harald Welte0f0ea812015-09-11 18:58:28 +0200188 if (ies.presenceMask & DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT)
189 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf,
190 ies.ranaP_Message.size);
191
Harald Welte350814a2015-09-10 22:32:15 +0200192 /* FIXME */
Harald Welte0f0ea812015-09-11 18:58:28 +0200193 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200194}
195
Harald Welte350814a2015-09-10 22:32:15 +0200196static int rua_rx_init_dt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200197{
198 RUA_DirectTransferIEs_t ies;
199 uint32_t context_id;
200 int rc;
201
202 rc = rua_decode_directtransferies(&ies, in);
203 if (rc < 0)
204 return rc;
205
206 context_id = asn1bitstr_to_u32(&ies.context_ID);
207
208 DEBUGP(DMAIN, "Data.req(ctx=0x%x)\n", context_id);
Harald Welte350814a2015-09-10 22:32:15 +0200209 /* FIXME */
Harald Welte0f0ea812015-09-11 18:58:28 +0200210 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
211
212 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200213
214}
215
Harald Welte350814a2015-09-10 22:32:15 +0200216static int rua_rx_init_udt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200217{
218 RUA_ConnectionlessTransferIEs_t ies;
219 int rc;
220
221 rc = rua_decode_connectionlesstransferies(&ies, in);
222 if (rc < 0)
223 return rc;
224
225 DEBUGP(DMAIN, "UData.req()\n");
226
Harald Welte350814a2015-09-10 22:32:15 +0200227 /* FIXME: pass on to RANAP */
228 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
229 /* FIXME: what to do with the asn1c-allocated memory */
230
231 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200232}
233
Harald Welte350814a2015-09-10 22:32:15 +0200234
235static int rua_rx_init_err_ind(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200236{
237 RUA_ErrorIndicationIEs_t ies;
238 int rc;
239
240 rc = rua_decode_errorindicationies(&ies, in);
241 if (rc < 0)
242 return rc;
243
244}
Harald Welte318e4d52015-09-10 18:47:08 +0200245
Harald Welte350814a2015-09-10 22:32:15 +0200246static int rua_rx_initiating_msg(struct msgb *msg, RUA_InitiatingMessage_t *imsg)
Harald Welte318e4d52015-09-10 18:47:08 +0200247{
248 int rc;
249
250 switch (imsg->procedureCode) {
251 case RUA_ProcedureCode_id_Connect:
Harald Welte350814a2015-09-10 22:32:15 +0200252 rc = rua_rx_init_connect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200253 break;
254 case RUA_ProcedureCode_id_DirectTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200255 rc = rua_rx_init_dt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200256 break;
257 case RUA_ProcedureCode_id_Disconnect:
Harald Welte350814a2015-09-10 22:32:15 +0200258 rc = rua_rx_init_disconnect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200259 break;
260 case RUA_ProcedureCode_id_ConnectionlessTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200261 rc = rua_rx_init_udt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200262 break;
263 case RUA_ProcedureCode_id_ErrorIndication:
Harald Welte350814a2015-09-10 22:32:15 +0200264 rc = rua_rx_init_err_ind(msg, &imsg->value);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200265 break;
Harald Welte318e4d52015-09-10 18:47:08 +0200266 case RUA_ProcedureCode_id_privateMessage:
267 break;
268 default:
Harald Welte64b4ebe2015-09-10 19:29:59 +0200269 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200270 }
271}
272
Harald Welte350814a2015-09-10 22:32:15 +0200273static int rua_rx_successful_outcome_msg(struct msgb *msg, RUA_SuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200274{
275
276}
277
Harald Welte350814a2015-09-10 22:32:15 +0200278static int rua_rx_unsuccessful_outcome_msg(struct msgb *msg, RUA_UnsuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200279{
280
281}
282
283
Harald Welte350814a2015-09-10 22:32:15 +0200284static int _hnbgw_rua_rx(struct msgb *msg, RUA_RUA_PDU_t *pdu)
Harald Welte318e4d52015-09-10 18:47:08 +0200285{
286 int rc;
287
288 /* it's a bit odd that we can't dispatch on procedure code, but
289 * that's not possible */
290 switch (pdu->present) {
291 case RUA_RUA_PDU_PR_initiatingMessage:
Harald Welte350814a2015-09-10 22:32:15 +0200292 rc = rua_rx_initiating_msg(msg, &pdu->choice.initiatingMessage);
Harald Welte318e4d52015-09-10 18:47:08 +0200293 break;
294 case RUA_RUA_PDU_PR_successfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200295 rc = rua_rx_successful_outcome_msg(msg, &pdu->choice.successfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200296 break;
297 case RUA_RUA_PDU_PR_unsuccessfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200298 rc = rua_rx_unsuccessful_outcome_msg(msg, &pdu->choice.unsuccessfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200299 break;
300 default:
301 return -1;
302 }
303}
304
305int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg)
306{
307 RUA_RUA_PDU_t _pdu, *pdu = &_pdu;
308 asn_dec_rval_t dec_ret;
309 int rc;
310
311 /* decode and handle to _hnbgw_hnbap_rx() */
312
313 memset(pdu, 0, sizeof(*pdu));
314 dec_ret = aper_decode(NULL, &asn_DEF_RUA_RUA_PDU, (void **) &pdu,
315 msg->data, msgb_length(msg), 0, 0);
316 if (dec_ret.code != RC_OK) {
Harald Weltef42317b2015-12-23 15:36:31 +0100317 LOGP(DRUA, LOGL_ERROR, "Error in ASN.1 decode\n");
Harald Welte318e4d52015-09-10 18:47:08 +0200318 return rc;
319 }
320
Harald Welte350814a2015-09-10 22:32:15 +0200321 rc = _hnbgw_rua_rx(msg, pdu);
Harald Welte318e4d52015-09-10 18:47:08 +0200322
323 return rc;
324}
325
326
327int hnbgw_rua_init(void)
328{
329
330}