blob: 1513099516370bbe6d25da7935152e0f98414b17 [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>
Harald Welte80401ad2015-09-11 19:48:06 +020025#include <osmocom/gsm/gsm48.h>
Harald Welte350814a2015-09-10 22:32:15 +020026
27#include <unistd.h>
28#include <errno.h>
29#include <string.h>
30
31#include "asn1helpers.h"
32
33#include "hnbgw.h"
Harald Weltee2e5d4d2015-09-10 23:49:45 +020034#include "hnbgw_rua.h"
Harald Welte08d5da62015-12-16 17:31:43 +010035#include "ranap_common.h"
36#include "ranap_ies_defs.h"
Harald Welte350814a2015-09-10 22:32:15 +020037
Harald Weltee2e5d4d2015-09-10 23:49:45 +020038static int ranap_tx_reset_ack(struct hnb_context *hnb,
39 RANAP_CN_DomainIndicator_t domain)
Harald Welte350814a2015-09-10 22:32:15 +020040{
Harald Weltee2e5d4d2015-09-10 23:49:45 +020041 struct msgb *msg;
42 int rc;
Harald Welte350814a2015-09-10 22:32:15 +020043
Harald Weltec4338de2015-12-24 00:40:52 +010044 msg = ranap_new_msg_reset_ack(domain, NULL);
Harald Weltee2e5d4d2015-09-10 23:49:45 +020045 if (!msg)
46 return -1;
47
Harald Weltec4338de2015-12-24 00:40:52 +010048 rc = rua_tx_udt(hnb, msg->data, msgb_length(msg));
Harald Weltee2e5d4d2015-09-10 23:49:45 +020049
Harald Weltec4338de2015-12-24 00:40:52 +010050 msgb_free(msg);
Harald Weltee2e5d4d2015-09-10 23:49:45 +020051
52 return rc;
Harald Welte350814a2015-09-10 22:32:15 +020053}
Harald Welte350814a2015-09-10 22:32:15 +020054
55static int ranap_rx_init_reset(struct hnb_context *hnb, ANY_t *in)
56{
57 RANAP_ResetIEs_t ies;
Harald Welteea98b6f2015-12-24 15:09:06 +010058 int rc, is_ps = 0;
Harald Welte350814a2015-09-10 22:32:15 +020059
60 rc = ranap_decode_reseties(&ies, in);
61 if (rc < 0)
62 return rc;
63
Harald Welteea98b6f2015-12-24 15:09:06 +010064 if (ies.cN_DomainIndicator == RANAP_CN_DomainIndicator_ps_domain)
65 is_ps=1;
66
67 DEBUGP(DRANAP, "RESET.req(%s)\n", is_ps ? "ps" : "cs");
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 Welte80401ad2015-09-11 19:48:06 +020076int ranap_parse_lai(struct gprs_ra_id *ra_id, const RANAP_LAI_t *lai)
77{
78 uint8_t *ptr = lai->pLMNidentity.buf;
79
80 /* TS 25.413 9.2.3.55 */
81 if (lai->pLMNidentity.size != 3)
82 return -1;
83
84 ra_id->mcc = (ptr[0] & 0xF) * 100 +
85 (ptr[0] >> 4) * 10 +
86 (ptr[1] & 0xF);
87 ra_id->mnc = (ptr[2] & 0xF) +
88 (ptr[2] >> 4) * 10;
89 if ((ptr[1] >> 4) != 0xF)
90 ra_id->mnc += (ptr[1] >> 4) * 100;
91
92 ra_id->lac = asn1str_to_u16(&lai->lAC);
93
94 /* TS 25.413 9.2.3.6 */
95 if (ra_id->lac == 0 || ra_id->lac == 0xfffe)
96 return -1;
97
98 return 0;
99}
100
Harald Welte1c2ada02015-09-11 20:10:17 +0200101static int ranap_rx_dt(struct hnb_context *hnb, ANY_t *in)
102{
103 RANAP_DirectTransferIEs_t ies;
104 int sapi = 0;
105 int rc;
106
107 rc = ranap_decode_directtransferies(&ies, in);
108 if (rc < 0)
109 return rc;
110
111 if (ies.presenceMask & DIRECTTRANSFERIES_RANAP_SAPI_PRESENT)
112 sapi = ies.sapi;
113
114 if (ies.presenceMask & DIRECTTRANSFERIES_RANAP_LAI_PRESENT) {
115 /* FIXME: Update LAI associated with UE */
116 }
117
118 if (ies.presenceMask & DIRECTTRANSFERIES_RANAP_RAC_PRESENT) {
119 /* FIXME: Update RAC associated with UE */
120 }
121
Harald Weltef42317b2015-12-23 15:36:31 +0100122 DEBUGP(DRANAP, "DirectTransfer: %s\n",
Harald Welte1c2ada02015-09-11 20:10:17 +0200123 osmo_hexdump(ies.nas_pdu.buf, ies.nas_pdu.size));
124 /* FIXME: hand NAS PDU into MSC */
125}
126
Harald Welte350814a2015-09-10 22:32:15 +0200127static int ranap_rx_initiating_msg(struct hnb_context *hnb, RANAP_InitiatingMessage_t *imsg)
128{
129 int rc;
130
Harald Weltec4338de2015-12-24 00:40:52 +0100131 /* according tot the spec, we can primarily receive Overload,
132 * Reset, Reset ACK, Error Indication, reset Resource, Reset
133 * Resurce Acknowledge as connecitonless RANAP. There are some
134 * more messages regarding Information Transfer, Direct
135 * Information Transfer and Uplink Information Trnansfer that we
136 * can ignore. In either case, it is RANAP that we need to
137 * decode... */
Harald Welte350814a2015-09-10 22:32:15 +0200138 switch (imsg->procedureCode) {
139 case RANAP_ProcedureCode_id_Reset:
Harald Weltec4338de2015-12-24 00:40:52 +0100140 /* Reset request */
Harald Welte350814a2015-09-10 22:32:15 +0200141 rc = ranap_rx_init_reset(hnb, &imsg->value);
142 break;
Harald Weltec4338de2015-12-24 00:40:52 +0100143 case RANAP_ProcedureCode_id_OverloadControl: /* Overload ind */
Harald Welte80401ad2015-09-11 19:48:06 +0200144 break;
Harald Weltec4338de2015-12-24 00:40:52 +0100145 case RANAP_ProcedureCode_id_ErrorIndication: /* Error ind */
146 break;
147 case RANAP_ProcedureCode_id_ResetResource: /* request */
148 case RANAP_ProcedureCode_id_InformationTransfer:
149 case RANAP_ProcedureCode_id_DirectInformationTransfer:
150 case RANAP_ProcedureCode_id_UplinkInformationExchange:
151 LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP "
152 "Procedure %u from HNB, ignoring\n", imsg->procedureCode);
153 break;
154 default:
155 LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP "
156 "Procedure %u from HNB, ignoring\n", imsg->procedureCode);
Harald Welte1c2ada02015-09-11 20:10:17 +0200157 break;
Harald Welte350814a2015-09-10 22:32:15 +0200158 }
159}
160
Harald Weltec4338de2015-12-24 00:40:52 +0100161static int ranap_rx_successful_msg(struct hnb_context *hnb, RANAP_SuccessfulOutcome_t *imsg)
162{
163 int rc;
164
165 /* according tot the spec, we can primarily receive Overload,
166 * Reset, Reset ACK, Error Indication, reset Resource, Reset
167 * Resurce Acknowledge as connecitonless RANAP. There are some
168 * more messages regarding Information Transfer, Direct
169 * Information Transfer and Uplink Information Trnansfer that we
170 * can ignore. In either case, it is RANAP that we need to
171 * decode... */
172 switch (imsg->procedureCode) {
173 case RANAP_ProcedureCode_id_Reset: /* Reset acknowledge */
174 break;
175 case RANAP_ProcedureCode_id_ResetResource: /* response */
176 case RANAP_ProcedureCode_id_InformationTransfer:
177 case RANAP_ProcedureCode_id_DirectInformationTransfer:
178 case RANAP_ProcedureCode_id_UplinkInformationExchange:
179 LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP "
180 "Procedure %u from HNB, ignoring\n", imsg->procedureCode);
181 break;
182 default:
183 LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP "
184 "Procedure %u from HNB, ignoring\n", imsg->procedureCode);
185 break;
186 }
187}
188
189
190
Harald Welte350814a2015-09-10 22:32:15 +0200191static int _hnbgw_ranap_rx(struct hnb_context *hnb, RANAP_RANAP_PDU_t *pdu)
192{
193 int rc;
194
195 switch (pdu->present) {
196 case RANAP_RANAP_PDU_PR_initiatingMessage:
197 rc = ranap_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage);
198 break;
199 case RANAP_RANAP_PDU_PR_successfulOutcome:
Harald Weltec4338de2015-12-24 00:40:52 +0100200 rc = ranap_rx_successful_msg(hnb, &pdu->choice.successfulOutcome);
Harald Welte350814a2015-09-10 22:32:15 +0200201 break;
202 case RANAP_RANAP_PDU_PR_unsuccessfulOutcome:
Harald Weltec4338de2015-12-24 00:40:52 +0100203 LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP "
204 "unsuccessful outcome procedure %u from HNB, ignoring\n",
205 pdu->choice.unsuccessfulOutcome.procedureCode);
Harald Welte350814a2015-09-10 22:32:15 +0200206 break;
207 default:
Harald Weltec4338de2015-12-24 00:40:52 +0100208 LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP "
209 "presence %u from HNB, ignoring\n", pdu->present);
Harald Welte350814a2015-09-10 22:32:15 +0200210 break;
211 }
212}
213
214
215int hnbgw_ranap_rx(struct msgb *msg, uint8_t *data, size_t len)
216{
217 RANAP_RANAP_PDU_t _pdu, *pdu = &_pdu;
218 asn_dec_rval_t dec_ret;
219 int rc;
220
221 memset(pdu, 0, sizeof(*pdu));
222 dec_ret = aper_decode(NULL,&asn_DEF_RANAP_RANAP_PDU, (void **) &pdu,
223 data, len, 0, 0);
224 if (dec_ret.code != RC_OK) {
Harald Weltef42317b2015-12-23 15:36:31 +0100225 LOGP(DRANAP, LOGL_ERROR, "Error in RANAP ASN.1 decode\n");
Harald Welte350814a2015-09-10 22:32:15 +0200226 return rc;
227 }
228
229 rc = _hnbgw_ranap_rx(msg->dst, pdu);
230
231 return rc;
232}
233
234int hnbgw_ranap_init(void)
235{
236
237}