blob: cca09ade5b34d56981c52238850ed07b29b2b17c [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>
24
25#include <unistd.h>
26#include <errno.h>
27#include <string.h>
28
29#include "asn1helpers.h"
30
31#include "hnbgw.h"
Harald Welte350814a2015-09-10 22:32:15 +020032#include "hnbgw_ranap.h"
Harald Welte318e4d52015-09-10 18:47:08 +020033#include "rua_common.h"
34#include "rua_ies_defs.h"
35
36static int hnbgw_rua_tx(struct hnb_context *ctx, struct msgb *msg)
37{
38 if (!msg)
39 return -EINVAL;
40
41 msgb_ppid(msg) = IUH_PPI_RUA;
42 return osmo_wqueue_enqueue(&ctx->wqueue, msg);
43}
44
Harald Weltee2e5d4d2015-09-10 23:49:45 +020045int rua_tx_udt(struct msgb *inmsg)
Harald Welte64b4ebe2015-09-10 19:29:59 +020046{
Harald Weltee2e5d4d2015-09-10 23:49:45 +020047 RUA_ConnectionlessTransfer_t out;
48 RUA_ConnectionlessTransferIEs_t ies;
49 struct msgb *msg;
50 int rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +020051
Harald Weltee2e5d4d2015-09-10 23:49:45 +020052 memset(&ies, 0, sizeof(ies));
53 ies.ranaP_Message.buf = inmsg->data;
54 ies.ranaP_Message.size = msgb_length(inmsg);
55
56 /* FIXME: msgb_free(msg)? ownership not yet clear */
57
58 memset(&out, 0, sizeof(out));
59 rc = rua_encode_connectionlesstransferies(&out, &ies);
60 if (rc < 0)
61 return rc;
62
63 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_ConnectionlessTransfer,
64 RUA_Criticality_reject,
65 &asn_DEF_RUA_ConnectionlessTransfer,
66 &out);
67 msg->dst = inmsg->dst;
68
69 DEBUGP(DMAIN, "transmitting RUA payload of %u bytes\n", msgb_length(msg));
70
71 return hnbgw_rua_tx(msg->dst, msg);
Harald Welte64b4ebe2015-09-10 19:29:59 +020072}
73
Harald Welte0f0ea812015-09-11 18:58:28 +020074int rua_tx_dt(struct msgb *inmsg)
75{
76 RUA_DirectTransfer_t out;
77 RUA_DirectTransferIEs_t ies;
78 struct msgb *msg;
79 int rc;
80
81 memset(&ies, 0, sizeof(ies));
82 ies.ranaP_Message.buf = inmsg->data;
83 ies.ranaP_Message.size = msgb_length(inmsg);
84
85 /* FIXME: msgb_free(msg)? ownership not yet clear */
86
87 memset(&out, 0, sizeof(out));
88 rc = rua_encode_directtransferies(&out, &ies);
89 if (rc < 0)
90 return rc;
91
92 msg = rua_generate_initiating_message(RUA_ProcedureCode_id_DirectTransfer,
93 RUA_Criticality_reject,
94 &asn_DEF_RUA_DirectTransfer,
95 &out);
96 msg->dst = inmsg->dst;
97
98 DEBUGP(DMAIN, "transmitting RUA payload of %u bytes\n", msgb_length(msg));
99
100 return hnbgw_rua_tx(msg->dst, msg);
101}
102
103
Harald Welte350814a2015-09-10 22:32:15 +0200104static int rua_rx_init_connect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200105{
106 RUA_ConnectIEs_t ies;
107 uint32_t context_id;
108 int rc;
109
110 rc = rua_decode_connecties(&ies, in);
111 if (rc < 0)
112 return rc;
113
114 context_id = asn1bitstr_to_u32(&ies.context_ID);
115
116 DEBUGP(DMAIN, "Connect.req(ctx=0x%x, %s)\n", context_id,
117 ies.establishment_Cause == RUA_Establishment_Cause_emergency_call
118 ? "emergency" : "normal");
Harald Welte0f0ea812015-09-11 18:58:28 +0200119 /* FIXME: route to CS (MSC) or PS (SGSN) domain */
120 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
121
122 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200123}
124
Harald Welte350814a2015-09-10 22:32:15 +0200125static int rua_rx_init_disconnect(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200126{
127 RUA_DisconnectIEs_t ies;
128 uint32_t context_id;
129 int rc;
130
131 rc = rua_decode_disconnecties(&ies, in);
132 if (rc < 0)
133 return rc;
134
135 context_id = asn1bitstr_to_u32(&ies.context_ID);
136
137 DEBUGP(DMAIN, "Disconnect.req(ctx=0x%x,cause=%s)\n", context_id,
138 rua_cause_str(&ies.cause));
Harald Welte0f0ea812015-09-11 18:58:28 +0200139 if (ies.presenceMask & DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT)
140 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf,
141 ies.ranaP_Message.size);
142
Harald Welte350814a2015-09-10 22:32:15 +0200143 /* FIXME */
Harald Welte0f0ea812015-09-11 18:58:28 +0200144 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200145}
146
Harald Welte350814a2015-09-10 22:32:15 +0200147static int rua_rx_init_dt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200148{
149 RUA_DirectTransferIEs_t ies;
150 uint32_t context_id;
151 int rc;
152
153 rc = rua_decode_directtransferies(&ies, in);
154 if (rc < 0)
155 return rc;
156
157 context_id = asn1bitstr_to_u32(&ies.context_ID);
158
159 DEBUGP(DMAIN, "Data.req(ctx=0x%x)\n", context_id);
Harald Welte350814a2015-09-10 22:32:15 +0200160 /* FIXME */
Harald Welte0f0ea812015-09-11 18:58:28 +0200161 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
162
163 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200164
165}
166
Harald Welte350814a2015-09-10 22:32:15 +0200167static int rua_rx_init_udt(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200168{
169 RUA_ConnectionlessTransferIEs_t ies;
170 int rc;
171
172 rc = rua_decode_connectionlesstransferies(&ies, in);
173 if (rc < 0)
174 return rc;
175
176 DEBUGP(DMAIN, "UData.req()\n");
177
Harald Welte350814a2015-09-10 22:32:15 +0200178 /* FIXME: pass on to RANAP */
179 rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size);
180 /* FIXME: what to do with the asn1c-allocated memory */
181
182 return rc;
Harald Welte64b4ebe2015-09-10 19:29:59 +0200183}
184
Harald Welte350814a2015-09-10 22:32:15 +0200185
186static int rua_rx_init_err_ind(struct msgb *msg, ANY_t *in)
Harald Welte64b4ebe2015-09-10 19:29:59 +0200187{
188 RUA_ErrorIndicationIEs_t ies;
189 int rc;
190
191 rc = rua_decode_errorindicationies(&ies, in);
192 if (rc < 0)
193 return rc;
194
195}
Harald Welte318e4d52015-09-10 18:47:08 +0200196
Harald Welte350814a2015-09-10 22:32:15 +0200197static int rua_rx_initiating_msg(struct msgb *msg, RUA_InitiatingMessage_t *imsg)
Harald Welte318e4d52015-09-10 18:47:08 +0200198{
199 int rc;
200
201 switch (imsg->procedureCode) {
202 case RUA_ProcedureCode_id_Connect:
Harald Welte350814a2015-09-10 22:32:15 +0200203 rc = rua_rx_init_connect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200204 break;
205 case RUA_ProcedureCode_id_DirectTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200206 rc = rua_rx_init_dt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200207 break;
208 case RUA_ProcedureCode_id_Disconnect:
Harald Welte350814a2015-09-10 22:32:15 +0200209 rc = rua_rx_init_disconnect(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200210 break;
211 case RUA_ProcedureCode_id_ConnectionlessTransfer:
Harald Welte350814a2015-09-10 22:32:15 +0200212 rc = rua_rx_init_udt(msg, &imsg->value);
Harald Welte318e4d52015-09-10 18:47:08 +0200213 break;
214 case RUA_ProcedureCode_id_ErrorIndication:
Harald Welte350814a2015-09-10 22:32:15 +0200215 rc = rua_rx_init_err_ind(msg, &imsg->value);
Harald Welte64b4ebe2015-09-10 19:29:59 +0200216 break;
Harald Welte318e4d52015-09-10 18:47:08 +0200217 case RUA_ProcedureCode_id_privateMessage:
218 break;
219 default:
Harald Welte64b4ebe2015-09-10 19:29:59 +0200220 return -1;
Harald Welte318e4d52015-09-10 18:47:08 +0200221 }
222}
223
Harald Welte350814a2015-09-10 22:32:15 +0200224static int rua_rx_successful_outcome_msg(struct msgb *msg, RUA_SuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200225{
226
227}
228
Harald Welte350814a2015-09-10 22:32:15 +0200229static int rua_rx_unsuccessful_outcome_msg(struct msgb *msg, RUA_UnsuccessfulOutcome_t *in)
Harald Welte318e4d52015-09-10 18:47:08 +0200230{
231
232}
233
234
Harald Welte350814a2015-09-10 22:32:15 +0200235static int _hnbgw_rua_rx(struct msgb *msg, RUA_RUA_PDU_t *pdu)
Harald Welte318e4d52015-09-10 18:47:08 +0200236{
237 int rc;
238
239 /* it's a bit odd that we can't dispatch on procedure code, but
240 * that's not possible */
241 switch (pdu->present) {
242 case RUA_RUA_PDU_PR_initiatingMessage:
Harald Welte350814a2015-09-10 22:32:15 +0200243 rc = rua_rx_initiating_msg(msg, &pdu->choice.initiatingMessage);
Harald Welte318e4d52015-09-10 18:47:08 +0200244 break;
245 case RUA_RUA_PDU_PR_successfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200246 rc = rua_rx_successful_outcome_msg(msg, &pdu->choice.successfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200247 break;
248 case RUA_RUA_PDU_PR_unsuccessfulOutcome:
Harald Welte350814a2015-09-10 22:32:15 +0200249 rc = rua_rx_unsuccessful_outcome_msg(msg, &pdu->choice.unsuccessfulOutcome);
Harald Welte318e4d52015-09-10 18:47:08 +0200250 break;
251 default:
252 return -1;
253 }
254}
255
256int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg)
257{
258 RUA_RUA_PDU_t _pdu, *pdu = &_pdu;
259 asn_dec_rval_t dec_ret;
260 int rc;
261
262 /* decode and handle to _hnbgw_hnbap_rx() */
263
264 memset(pdu, 0, sizeof(*pdu));
265 dec_ret = aper_decode(NULL, &asn_DEF_RUA_RUA_PDU, (void **) &pdu,
266 msg->data, msgb_length(msg), 0, 0);
267 if (dec_ret.code != RC_OK) {
268 LOGP(DMAIN, LOGL_ERROR, "Error in ASN.1 decode\n");
269 return rc;
270 }
271
Harald Welte350814a2015-09-10 22:32:15 +0200272 rc = _hnbgw_rua_rx(msg, pdu);
Harald Welte318e4d52015-09-10 18:47:08 +0200273
274 return rc;
275}
276
277
278int hnbgw_rua_init(void)
279{
280
281}