blob: 3f7c2bfa182ff2551c3c19b0c061090fd02f73b4 [file] [log] [blame]
Harald Welte77847ad2015-10-06 22:07:04 +02001/* hnb-gw specific code for RANAP */
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
22
Harald Welte350814a2015-09-10 22:32:15 +020023#include <osmocom/core/msgb.h>
24#include <osmocom/core/utils.h>
25
26#include <unistd.h>
27#include <errno.h>
28#include <string.h>
29
30#include "asn1helpers.h"
31
32#include "hnbgw.h"
Harald Weltee2e5d4d2015-09-10 23:49:45 +020033#include "hnbgw_rua.h"
Neels Hofmeyr96979af2016-01-05 15:19:44 +010034#include <osmocom/ranap/ranap_common.h>
35#include <osmocom/ranap/ranap_ies_defs.h>
Harald Welte350814a2015-09-10 22:32:15 +020036
Harald Weltee2e5d4d2015-09-10 23:49:45 +020037static int ranap_tx_reset_ack(struct hnb_context *hnb,
38 RANAP_CN_DomainIndicator_t domain)
Harald Welte350814a2015-09-10 22:32:15 +020039{
Harald Weltee2e5d4d2015-09-10 23:49:45 +020040 struct msgb *msg;
41 int rc;
Harald Welte350814a2015-09-10 22:32:15 +020042
Harald Weltec4338de2015-12-24 00:40:52 +010043 msg = ranap_new_msg_reset_ack(domain, NULL);
Harald Weltee2e5d4d2015-09-10 23:49:45 +020044 if (!msg)
45 return -1;
46
Harald Weltec4338de2015-12-24 00:40:52 +010047 rc = rua_tx_udt(hnb, msg->data, msgb_length(msg));
Harald Weltee2e5d4d2015-09-10 23:49:45 +020048
Harald Weltec4338de2015-12-24 00:40:52 +010049 msgb_free(msg);
Harald Weltee2e5d4d2015-09-10 23:49:45 +020050
51 return rc;
Harald Welte350814a2015-09-10 22:32:15 +020052}
Harald Welte350814a2015-09-10 22:32:15 +020053
54static int ranap_rx_init_reset(struct hnb_context *hnb, ANY_t *in)
55{
56 RANAP_ResetIEs_t ies;
Harald Welteea98b6f2015-12-24 15:09:06 +010057 int rc, is_ps = 0;
Harald Welte350814a2015-09-10 22:32:15 +020058
59 rc = ranap_decode_reseties(&ies, in);
60 if (rc < 0)
61 return rc;
62
Harald Welteea98b6f2015-12-24 15:09:06 +010063 if (ies.cN_DomainIndicator == RANAP_CN_DomainIndicator_ps_domain)
64 is_ps=1;
65
Harald Welte23058e12015-12-25 10:25:01 +010066 LOGP(DRANAP, LOGL_INFO, "Rx RESET.req(%s,%s)\n", is_ps ? "ps" : "cs",
67 ranap_cause_str(&ies.cause));
Harald Welte350814a2015-09-10 22:32:15 +020068
Harald Welte80401ad2015-09-11 19:48:06 +020069 /* FIXME: Actually we have to wait for some guard time? */
70 /* FIXME: Reset all resources related to this HNB/RNC */
Harald Weltee2e5d4d2015-09-10 23:49:45 +020071 ranap_tx_reset_ack(hnb, ies.cN_DomainIndicator);
72
Harald Welte350814a2015-09-10 22:32:15 +020073 return 0;
74}
75
Harald Welte23058e12015-12-25 10:25:01 +010076static int ranap_rx_error_ind(struct hnb_context *hnb, ANY_t *in)
77{
78 RANAP_ErrorIndicationIEs_t ies;
79 int rc, is_ps = 0;
80
81 rc = ranap_decode_errorindicationies(&ies, in);
82 if (rc < 0)
83 return rc;
84
85 if (ies.presenceMask & ERRORINDICATIONIES_RANAP_CAUSE_PRESENT) {
86 LOGP(DRANAP, LOGL_ERROR, "Rx ERROR.ind(%s)\n",
87 ranap_cause_str(&ies.cause));
88 } else
89 LOGP(DRANAP, LOGL_ERROR, "Rx ERROR.ind\n");
90
91 return 0;
92}
93
Harald Welte1c2ada02015-09-11 20:10:17 +020094static int ranap_rx_dt(struct hnb_context *hnb, ANY_t *in)
95{
96 RANAP_DirectTransferIEs_t ies;
97 int sapi = 0;
98 int rc;
99
100 rc = ranap_decode_directtransferies(&ies, in);
101 if (rc < 0)
102 return rc;
103
104 if (ies.presenceMask & DIRECTTRANSFERIES_RANAP_SAPI_PRESENT)
105 sapi = ies.sapi;
106
107 if (ies.presenceMask & DIRECTTRANSFERIES_RANAP_LAI_PRESENT) {
108 /* FIXME: Update LAI associated with UE */
109 }
110
111 if (ies.presenceMask & DIRECTTRANSFERIES_RANAP_RAC_PRESENT) {
112 /* FIXME: Update RAC associated with UE */
113 }
114
Harald Weltef42317b2015-12-23 15:36:31 +0100115 DEBUGP(DRANAP, "DirectTransfer: %s\n",
Harald Welte1c2ada02015-09-11 20:10:17 +0200116 osmo_hexdump(ies.nas_pdu.buf, ies.nas_pdu.size));
117 /* FIXME: hand NAS PDU into MSC */
118}
119
Harald Welte350814a2015-09-10 22:32:15 +0200120static int ranap_rx_initiating_msg(struct hnb_context *hnb, RANAP_InitiatingMessage_t *imsg)
121{
122 int rc;
123
Harald Weltec4338de2015-12-24 00:40:52 +0100124 /* according tot the spec, we can primarily receive Overload,
125 * Reset, Reset ACK, Error Indication, reset Resource, Reset
126 * Resurce Acknowledge as connecitonless RANAP. There are some
127 * more messages regarding Information Transfer, Direct
128 * Information Transfer and Uplink Information Trnansfer that we
129 * can ignore. In either case, it is RANAP that we need to
130 * decode... */
Harald Welte350814a2015-09-10 22:32:15 +0200131 switch (imsg->procedureCode) {
132 case RANAP_ProcedureCode_id_Reset:
Harald Weltec4338de2015-12-24 00:40:52 +0100133 /* Reset request */
Harald Welte350814a2015-09-10 22:32:15 +0200134 rc = ranap_rx_init_reset(hnb, &imsg->value);
135 break;
Harald Weltec4338de2015-12-24 00:40:52 +0100136 case RANAP_ProcedureCode_id_OverloadControl: /* Overload ind */
Harald Welte80401ad2015-09-11 19:48:06 +0200137 break;
Harald Weltec4338de2015-12-24 00:40:52 +0100138 case RANAP_ProcedureCode_id_ErrorIndication: /* Error ind */
Harald Welte23058e12015-12-25 10:25:01 +0100139 rc = ranap_rx_error_ind(hnb, &imsg->value);
Harald Weltec4338de2015-12-24 00:40:52 +0100140 break;
141 case RANAP_ProcedureCode_id_ResetResource: /* request */
142 case RANAP_ProcedureCode_id_InformationTransfer:
143 case RANAP_ProcedureCode_id_DirectInformationTransfer:
144 case RANAP_ProcedureCode_id_UplinkInformationExchange:
145 LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP "
146 "Procedure %u from HNB, ignoring\n", imsg->procedureCode);
147 break;
148 default:
149 LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP "
150 "Procedure %u from HNB, ignoring\n", imsg->procedureCode);
Harald Welte1c2ada02015-09-11 20:10:17 +0200151 break;
Harald Welte350814a2015-09-10 22:32:15 +0200152 }
153}
154
Harald Weltec4338de2015-12-24 00:40:52 +0100155static int ranap_rx_successful_msg(struct hnb_context *hnb, RANAP_SuccessfulOutcome_t *imsg)
156{
157 int rc;
158
159 /* according tot the spec, we can primarily receive Overload,
160 * Reset, Reset ACK, Error Indication, reset Resource, Reset
161 * Resurce Acknowledge as connecitonless RANAP. There are some
162 * more messages regarding Information Transfer, Direct
163 * Information Transfer and Uplink Information Trnansfer that we
164 * can ignore. In either case, it is RANAP that we need to
165 * decode... */
166 switch (imsg->procedureCode) {
167 case RANAP_ProcedureCode_id_Reset: /* Reset acknowledge */
168 break;
169 case RANAP_ProcedureCode_id_ResetResource: /* response */
170 case RANAP_ProcedureCode_id_InformationTransfer:
171 case RANAP_ProcedureCode_id_DirectInformationTransfer:
172 case RANAP_ProcedureCode_id_UplinkInformationExchange:
173 LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP "
174 "Procedure %u from HNB, ignoring\n", imsg->procedureCode);
175 break;
176 default:
177 LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP "
178 "Procedure %u from HNB, ignoring\n", imsg->procedureCode);
179 break;
180 }
181}
182
183
184
Harald Welte350814a2015-09-10 22:32:15 +0200185static int _hnbgw_ranap_rx(struct hnb_context *hnb, RANAP_RANAP_PDU_t *pdu)
186{
187 int rc;
188
189 switch (pdu->present) {
190 case RANAP_RANAP_PDU_PR_initiatingMessage:
191 rc = ranap_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage);
192 break;
193 case RANAP_RANAP_PDU_PR_successfulOutcome:
Harald Weltec4338de2015-12-24 00:40:52 +0100194 rc = ranap_rx_successful_msg(hnb, &pdu->choice.successfulOutcome);
Harald Welte350814a2015-09-10 22:32:15 +0200195 break;
196 case RANAP_RANAP_PDU_PR_unsuccessfulOutcome:
Harald Weltec4338de2015-12-24 00:40:52 +0100197 LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP "
198 "unsuccessful outcome procedure %u from HNB, ignoring\n",
199 pdu->choice.unsuccessfulOutcome.procedureCode);
Harald Welte350814a2015-09-10 22:32:15 +0200200 break;
201 default:
Harald Weltec4338de2015-12-24 00:40:52 +0100202 LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP "
203 "presence %u from HNB, ignoring\n", pdu->present);
Harald Welte350814a2015-09-10 22:32:15 +0200204 break;
205 }
206}
207
208
209int hnbgw_ranap_rx(struct msgb *msg, uint8_t *data, size_t len)
210{
211 RANAP_RANAP_PDU_t _pdu, *pdu = &_pdu;
212 asn_dec_rval_t dec_ret;
213 int rc;
214
215 memset(pdu, 0, sizeof(*pdu));
216 dec_ret = aper_decode(NULL,&asn_DEF_RANAP_RANAP_PDU, (void **) &pdu,
217 data, len, 0, 0);
218 if (dec_ret.code != RC_OK) {
Harald Weltef42317b2015-12-23 15:36:31 +0100219 LOGP(DRANAP, LOGL_ERROR, "Error in RANAP ASN.1 decode\n");
Harald Welte350814a2015-09-10 22:32:15 +0200220 return rc;
221 }
222
223 rc = _hnbgw_ranap_rx(msg->dst, pdu);
224
225 return rc;
226}
227
228int hnbgw_ranap_init(void)
229{
230
231}