blob: c0b968f3a364b49f5f651c161f0dfaf08fa70155 [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 RANAP_ResetAcknowledge_t out;
42 RANAP_ResetAcknowledgeIEs_t ies;
43 struct msgb *msg;
44 int rc;
Harald Welte350814a2015-09-10 22:32:15 +020045
46 memset(&ies, 0, sizeof(ies));
Harald Weltee2e5d4d2015-09-10 23:49:45 +020047 ies.cN_DomainIndicator = domain;
Harald Welte350814a2015-09-10 22:32:15 +020048
Harald Weltee2e5d4d2015-09-10 23:49:45 +020049 memset(&out, 0, sizeof(out));
50 rc = ranap_encode_resetacknowledgeies(&out, &ies);
51 if (rc < 0) {
Harald Weltef42317b2015-12-23 15:36:31 +010052 LOGP(DRANAP, LOGL_ERROR, "error encoding reset ack IEs: %d\n", rc);
Harald Weltee2e5d4d2015-09-10 23:49:45 +020053 return rc;
54 }
55
56 msg = ranap_generate_successful_outcome(RANAP_ProcedureCode_id_Reset,
57 RANAP_Criticality_reject,
58 &asn_DEF_RANAP_ResetAcknowledge,
59 &out);
60 if (!msg)
61 return -1;
62
63 msg->dst = hnb;
64
65 rc = rua_tx_udt(msg);
66
67 return rc;
Harald Welte350814a2015-09-10 22:32:15 +020068}
Harald Welte350814a2015-09-10 22:32:15 +020069
70static int ranap_rx_init_reset(struct hnb_context *hnb, ANY_t *in)
71{
72 RANAP_ResetIEs_t ies;
73 int rc;
74
75 rc = ranap_decode_reseties(&ies, in);
76 if (rc < 0)
77 return rc;
78
Harald Weltef42317b2015-12-23 15:36:31 +010079 DEBUGP(DRANAP, "RESET.req\n");
Harald Welte350814a2015-09-10 22:32:15 +020080
Harald Welte80401ad2015-09-11 19:48:06 +020081 /* FIXME: Actually we have to wait for some guard time? */
82 /* FIXME: Reset all resources related to this HNB/RNC */
Harald Weltee2e5d4d2015-09-10 23:49:45 +020083 ranap_tx_reset_ack(hnb, ies.cN_DomainIndicator);
84
Harald Welte350814a2015-09-10 22:32:15 +020085 return 0;
86}
87
Harald Welte80401ad2015-09-11 19:48:06 +020088int ranap_parse_lai(struct gprs_ra_id *ra_id, const RANAP_LAI_t *lai)
89{
90 uint8_t *ptr = lai->pLMNidentity.buf;
91
92 /* TS 25.413 9.2.3.55 */
93 if (lai->pLMNidentity.size != 3)
94 return -1;
95
96 ra_id->mcc = (ptr[0] & 0xF) * 100 +
97 (ptr[0] >> 4) * 10 +
98 (ptr[1] & 0xF);
99 ra_id->mnc = (ptr[2] & 0xF) +
100 (ptr[2] >> 4) * 10;
101 if ((ptr[1] >> 4) != 0xF)
102 ra_id->mnc += (ptr[1] >> 4) * 100;
103
104 ra_id->lac = asn1str_to_u16(&lai->lAC);
105
106 /* TS 25.413 9.2.3.6 */
107 if (ra_id->lac == 0 || ra_id->lac == 0xfffe)
108 return -1;
109
110 return 0;
111}
112
113static int ranap_rx_init_ue_msg(struct hnb_context *hnb, ANY_t *in)
114{
115 RANAP_InitialUE_MessageIEs_t ies;
116 struct gprs_ra_id ra_id;
117 int rc;
118
119 rc = ranap_decode_initialue_messageies(&ies, in);
120 if (rc < 0)
121 return rc;
122
123 /* location area ID of the serving cell */
124 ranap_parse_lai(&ra_id, &ies.lai);
125
126 DEBUGP(DMAIN, "%u-%u-%u: InitialUE: %s\n", ra_id.mcc, ra_id.mnc,
127 ra_id.lac, osmo_hexdump(ies.nas_pdu.buf, ies.nas_pdu.size));
128 /* FIXME: hand NAS PDU into MSC */
129
130 return 0;
131}
132
Harald Welte1c2ada02015-09-11 20:10:17 +0200133static int ranap_rx_dt(struct hnb_context *hnb, ANY_t *in)
134{
135 RANAP_DirectTransferIEs_t ies;
136 int sapi = 0;
137 int rc;
138
139 rc = ranap_decode_directtransferies(&ies, in);
140 if (rc < 0)
141 return rc;
142
143 if (ies.presenceMask & DIRECTTRANSFERIES_RANAP_SAPI_PRESENT)
144 sapi = ies.sapi;
145
146 if (ies.presenceMask & DIRECTTRANSFERIES_RANAP_LAI_PRESENT) {
147 /* FIXME: Update LAI associated with UE */
148 }
149
150 if (ies.presenceMask & DIRECTTRANSFERIES_RANAP_RAC_PRESENT) {
151 /* FIXME: Update RAC associated with UE */
152 }
153
Harald Weltef42317b2015-12-23 15:36:31 +0100154 DEBUGP(DRANAP, "DirectTransfer: %s\n",
Harald Welte1c2ada02015-09-11 20:10:17 +0200155 osmo_hexdump(ies.nas_pdu.buf, ies.nas_pdu.size));
156 /* FIXME: hand NAS PDU into MSC */
157}
158
Harald Welte350814a2015-09-10 22:32:15 +0200159static int ranap_rx_initiating_msg(struct hnb_context *hnb, RANAP_InitiatingMessage_t *imsg)
160{
161 int rc;
162
163 switch (imsg->procedureCode) {
164 case RANAP_ProcedureCode_id_Reset:
165 rc = ranap_rx_init_reset(hnb, &imsg->value);
166 break;
Harald Welte80401ad2015-09-11 19:48:06 +0200167 case RANAP_ProcedureCode_id_InitialUE_Message:
168 rc = ranap_rx_init_ue_msg(hnb, &imsg->value);
169 break;
Harald Welte1c2ada02015-09-11 20:10:17 +0200170 case RANAP_ProcedureCode_id_DirectTransfer:
171 rc = ranap_rx_dt(hnb, &imsg->value);
172 break;
Harald Welte350814a2015-09-10 22:32:15 +0200173 }
174}
175
176static int _hnbgw_ranap_rx(struct hnb_context *hnb, RANAP_RANAP_PDU_t *pdu)
177{
178 int rc;
179
180 switch (pdu->present) {
181 case RANAP_RANAP_PDU_PR_initiatingMessage:
182 rc = ranap_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage);
183 break;
184 case RANAP_RANAP_PDU_PR_successfulOutcome:
185 break;
186 case RANAP_RANAP_PDU_PR_unsuccessfulOutcome:
187 break;
188 default:
189 break;
190 }
191}
192
193
194int hnbgw_ranap_rx(struct msgb *msg, uint8_t *data, size_t len)
195{
196 RANAP_RANAP_PDU_t _pdu, *pdu = &_pdu;
197 asn_dec_rval_t dec_ret;
198 int rc;
199
200 memset(pdu, 0, sizeof(*pdu));
201 dec_ret = aper_decode(NULL,&asn_DEF_RANAP_RANAP_PDU, (void **) &pdu,
202 data, len, 0, 0);
203 if (dec_ret.code != RC_OK) {
Harald Weltef42317b2015-12-23 15:36:31 +0100204 LOGP(DRANAP, LOGL_ERROR, "Error in RANAP ASN.1 decode\n");
Harald Welte350814a2015-09-10 22:32:15 +0200205 return rc;
206 }
207
208 rc = _hnbgw_ranap_rx(msg->dst, pdu);
209
210 return rc;
211}
212
213int hnbgw_ranap_init(void)
214{
215
216}