blob: bc503d3921551a4e971f68f3c572ae508860519e [file] [log] [blame]
Harald Welte77847ad2015-10-06 22:07:04 +02001/* hnb-gw specific code for HNBAP */
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
Harald Welteba43de42015-08-29 20:33:16 +020021#include <osmocom/core/msgb.h>
Harald Welteb3dae302015-08-30 12:20:09 +020022#include <osmocom/core/utils.h>
Stefan Sperlingc964a2c2018-02-19 17:02:12 +010023#include <osmocom/core/socket.h>
Harald Welte10dfc5a2015-09-11 01:34:45 +020024#include <osmocom/gsm/gsm48.h>
Harald Welteffa7c0a2015-12-23 00:03:41 +010025#include <osmocom/netif/stream.h>
Harald Welteba43de42015-08-29 20:33:16 +020026
Harald Welteb3dae302015-08-30 12:20:09 +020027#include <unistd.h>
Harald Welteee77cff2015-08-30 16:57:53 +020028#include <errno.h>
Harald Welteb3dae302015-08-30 12:20:09 +020029#include <string.h>
30
Harald Welte30afef32015-08-30 12:28:29 +020031#include "asn1helpers.h"
Neels Hofmeyr83457922016-08-26 23:56:44 +020032#include <osmocom/hnbap/hnbap_common.h>
Neels Hofmeyr96979af2016-01-05 15:19:44 +010033#include <osmocom/ranap/iu_helpers.h>
Harald Welte30afef32015-08-30 12:28:29 +020034
Neels Hofmeyrdf63de22016-08-18 13:13:55 +020035#include <osmocom/iuh/hnbgw.h>
Neels Hofmeyr83457922016-08-26 23:56:44 +020036#include <osmocom/hnbap/hnbap_ies_defs.h>
Harald Welteba43de42015-08-29 20:33:16 +020037
Harald Welteee77cff2015-08-30 16:57:53 +020038#define IU_MSG_NUM_IES 32
39#define IU_MSG_NUM_EXT_IES 32
40
Harald Welte27f9c4a2015-08-30 22:47:18 +020041static int hnbgw_hnbap_tx(struct hnb_context *ctx, struct msgb *msg)
Harald Welteee77cff2015-08-30 16:57:53 +020042{
Harald Welte7b54e322015-09-07 22:41:45 +020043 if (!msg)
44 return -EINVAL;
45
Harald Welteffa7c0a2015-12-23 00:03:41 +010046 msgb_sctp_ppid(msg) = IUH_PPI_HNBAP;
Daniel Willmann6480cad2016-01-06 18:06:26 +010047 osmo_stream_srv_send(ctx->conn, msg);
48
49 return 0;
Harald Welte27f9c4a2015-08-30 22:47:18 +020050}
Harald Welteee77cff2015-08-30 16:57:53 +020051
Stefan Sperlingc964a2c2018-02-19 17:02:12 +010052static int hnbgw_tx_hnb_register_rej(struct hnb_context *ctx)
53{
54 HNBRegisterReject_t reject_out;
55 HNBRegisterRejectIEs_t reject;
56 struct msgb *msg;
57 int rc;
58
59 reject.presenceMask = 0,
60 reject.cause.present = Cause_PR_radioNetwork;
61 reject.cause.choice.radioNetwork = CauseRadioNetwork_unspecified;
62
63 /* encode the Information Elements */
64 memset(&reject_out, 0, sizeof(reject_out));
65 rc = hnbap_encode_hnbregisterrejecties(&reject_out, &reject);
66 if (rc < 0) {
Harald Weltef05c5bf2020-12-30 14:17:34 +010067 LOGHNB(ctx, DHNBAP, LOGL_ERROR, "Failure to encode HNB-REGISTER-REJECT to %s: rc=%d\n",
68 ctx->identity_info, rc);
Stefan Sperlingc964a2c2018-02-19 17:02:12 +010069 return rc;
70 }
71
72 /* generate a successfull outcome PDU */
73 msg = hnbap_generate_unsuccessful_outcome(ProcedureCode_id_HNBRegister,
74 Criticality_reject,
75 &asn_DEF_HNBRegisterReject,
76 &reject_out);
77
78 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBRegisterReject, &reject_out);
79
80 rc = hnbgw_hnbap_tx(ctx, msg);
81 if (rc == 0) {
82 /* Tell libosmo-netif to destroy this connection when it is done
83 * sending our HNB-REGISTER-REJECT response. */
84 osmo_stream_srv_set_flush_and_destroy(ctx->conn);
85 } else {
86 /* The message was not queued. Destroy the connection right away. */
Alexander Couzensad4ea3b2018-07-24 19:04:47 +020087 hnb_context_release(ctx);
Harald Welte9aad1852018-10-21 11:45:26 +020088 return rc;
Stefan Sperlingc964a2c2018-02-19 17:02:12 +010089 }
Harald Welte9aad1852018-10-21 11:45:26 +020090
91 return 0;
Stefan Sperlingc964a2c2018-02-19 17:02:12 +010092}
93
Harald Welte27f9c4a2015-08-30 22:47:18 +020094static int hnbgw_tx_hnb_register_acc(struct hnb_context *ctx)
95{
96 HNBRegisterAccept_t accept_out;
97 struct msgb *msg;
98 int rc;
99
100 /* Single required response IE: RNC-ID */
101 HNBRegisterAcceptIEs_t accept = {
102 .rnc_id = ctx->gw->config.rnc_id
103 };
104
105 /* encode the Information Elements */
Harald Welte2204f9d2015-09-07 21:10:50 +0200106 memset(&accept_out, 0, sizeof(accept_out));
Harald Welte27f9c4a2015-08-30 22:47:18 +0200107 rc = hnbap_encode_hnbregisteraccepties(&accept_out, &accept);
108 if (rc < 0) {
Harald Weltef05c5bf2020-12-30 14:17:34 +0100109 LOGHNB(ctx, DHNBAP, LOGL_ERROR, "Failure to encode HNB-REGISTER-ACCEPT to %s: rc=%d\n",
110 ctx->identity_info, rc);
Harald Welte27f9c4a2015-08-30 22:47:18 +0200111 return rc;
Harald Welteee77cff2015-08-30 16:57:53 +0200112 }
113
Harald Welte27f9c4a2015-08-30 22:47:18 +0200114 /* generate a successfull outcome PDU */
115 msg = hnbap_generate_successful_outcome(ProcedureCode_id_HNBRegister,
116 Criticality_reject,
117 &asn_DEF_HNBRegisterAccept,
118 &accept_out);
Harald Welteee77cff2015-08-30 16:57:53 +0200119
Daniel Willmann59d17d82015-12-17 17:56:56 +0100120 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBRegisterAccept, &accept_out);
121
Harald Weltef05c5bf2020-12-30 14:17:34 +0100122 LOGHNB(ctx, DHNBAP, LOGL_NOTICE, "Accepting HNB-REGISTER-REQ from %s\n", ctx->identity_info);
Neels Hofmeyr39d7b5c2019-03-04 22:37:59 +0100123
Harald Welte27f9c4a2015-08-30 22:47:18 +0200124 return hnbgw_hnbap_tx(ctx, msg);
Harald Welteee77cff2015-08-30 16:57:53 +0200125}
126
127
Harald Welte27f9c4a2015-08-30 22:47:18 +0200128static int hnbgw_tx_ue_register_acc(struct ue_context *ue)
Harald Welteba43de42015-08-29 20:33:16 +0200129{
Harald Welte27f9c4a2015-08-30 22:47:18 +0200130 UERegisterAccept_t accept_out;
131 UERegisterAcceptIEs_t accept;
132 struct msgb *msg;
Harald Welte10dfc5a2015-09-11 01:34:45 +0200133 uint8_t encoded_imsi[10];
Daniel Willmann92247312015-12-09 19:04:33 +0100134 uint32_t ctx_id;
Harald Welte10dfc5a2015-09-11 01:34:45 +0200135 size_t encoded_imsi_len;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200136 int rc;
Harald Welteba43de42015-08-29 20:33:16 +0200137
Harald Welte056984f2016-01-03 16:31:31 +0100138 encoded_imsi_len = ranap_imsi_encode(encoded_imsi,
Harald Welte1d2c39d2015-09-11 17:49:37 +0200139 sizeof(encoded_imsi), ue->imsi);
Harald Welte10dfc5a2015-09-11 01:34:45 +0200140
Harald Welte2204f9d2015-09-07 21:10:50 +0200141 memset(&accept, 0, sizeof(accept));
Harald Welte10dfc5a2015-09-11 01:34:45 +0200142 accept.uE_Identity.present = UE_Identity_PR_iMSI;
Harald Welte1d2c39d2015-09-11 17:49:37 +0200143 OCTET_STRING_fromBuf(&accept.uE_Identity.choice.iMSI,
144 (const char *)encoded_imsi, encoded_imsi_len);
Daniel Willmann92247312015-12-09 19:04:33 +0100145 asn1_u24_to_bitstring(&accept.context_ID, &ctx_id, ue->context_id);
Harald Welteba43de42015-08-29 20:33:16 +0200146
Harald Welte2204f9d2015-09-07 21:10:50 +0200147 memset(&accept_out, 0, sizeof(accept_out));
Harald Welte27f9c4a2015-08-30 22:47:18 +0200148 rc = hnbap_encode_ueregisteraccepties(&accept_out, &accept);
149 if (rc < 0) {
150 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200151 }
Harald Welte27f9c4a2015-08-30 22:47:18 +0200152
153 msg = hnbap_generate_successful_outcome(ProcedureCode_id_UERegister,
154 Criticality_reject,
155 &asn_DEF_UERegisterAccept,
156 &accept_out);
Daniel Willmann541e4292015-12-22 16:25:29 +0100157
158 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, &accept.uE_Identity.choice.iMSI);
159 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_UERegisterAccept, &accept_out);
160
Harald Welte27f9c4a2015-08-30 22:47:18 +0200161 return hnbgw_hnbap_tx(ue->hnb, msg);
Harald Welteba43de42015-08-29 20:33:16 +0200162}
163
Neels Hofmeyr1a0bb512016-04-25 14:55:35 +0200164static int hnbgw_tx_ue_register_rej_tmsi(struct hnb_context *hnb, UE_Identity_t *ue_id)
165{
166 UERegisterReject_t reject_out;
167 UERegisterRejectIEs_t reject;
168 struct msgb *msg;
169 int rc;
170
171 memset(&reject, 0, sizeof(reject));
172 reject.uE_Identity.present = ue_id->present;
173
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200174 /* Copy the identity over to the reject message */
175 switch (ue_id->present) {
176 case UE_Identity_PR_tMSILAI:
Harald Weltef05c5bf2020-12-30 14:17:34 +0100177 LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id tMSI %d %s\n", ue_id->choice.tMSILAI.tMSI.size,
178 osmo_hexdump(ue_id->choice.tMSILAI.tMSI.buf, ue_id->choice.tMSILAI.tMSI.size));
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200179
Harald Weltef05c5bf2020-12-30 14:17:34 +0100180 LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id pLMNID %d %s\n", ue_id->choice.tMSILAI.lAI.pLMNID.size,
181 osmo_hexdump(ue_id->choice.tMSILAI.lAI.pLMNID.buf, ue_id->choice.tMSILAI.lAI.pLMNID.size));
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200182
Harald Weltef05c5bf2020-12-30 14:17:34 +0100183 LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id lAC %d %s\n", ue_id->choice.tMSILAI.lAI.lAC.size,
184 osmo_hexdump(ue_id->choice.tMSILAI.lAI.lAC.buf, ue_id->choice.tMSILAI.lAI.lAC.size));
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200185
186 BIT_STRING_fromBuf(&reject.uE_Identity.choice.tMSILAI.tMSI,
187 ue_id->choice.tMSILAI.tMSI.buf,
188 ue_id->choice.tMSILAI.tMSI.size * 8
189 - ue_id->choice.tMSILAI.tMSI.bits_unused);
190 OCTET_STRING_fromBuf(&reject.uE_Identity.choice.tMSILAI.lAI.pLMNID,
Pau Espin Pedrola008b172020-03-20 20:29:22 +0100191 (const char *)ue_id->choice.tMSILAI.lAI.pLMNID.buf,
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200192 ue_id->choice.tMSILAI.lAI.pLMNID.size);
193 OCTET_STRING_fromBuf(&reject.uE_Identity.choice.tMSILAI.lAI.lAC,
Pau Espin Pedrola008b172020-03-20 20:29:22 +0100194 (const char *)ue_id->choice.tMSILAI.lAI.lAC.buf,
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200195 ue_id->choice.tMSILAI.lAI.lAC.size);
196 break;
197
198 case UE_Identity_PR_pTMSIRAI:
Harald Weltef05c5bf2020-12-30 14:17:34 +0100199 LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id pTMSI %d %s\n", ue_id->choice.pTMSIRAI.pTMSI.size,
200 osmo_hexdump(ue_id->choice.pTMSIRAI.pTMSI.buf, ue_id->choice.pTMSIRAI.pTMSI.size));
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200201
Harald Weltef05c5bf2020-12-30 14:17:34 +0100202 LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id pLMNID %d %s\n", ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.size,
203 osmo_hexdump(ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.buf, ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.size));
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200204
Harald Weltef05c5bf2020-12-30 14:17:34 +0100205 LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id lAC %d %s\n", ue_id->choice.pTMSIRAI.rAI.lAI.lAC.size,
206 osmo_hexdump(ue_id->choice.pTMSIRAI.rAI.lAI.lAC.buf, ue_id->choice.pTMSIRAI.rAI.lAI.lAC.size));
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200207
Harald Weltef05c5bf2020-12-30 14:17:34 +0100208 LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id rAC %d %s\n", ue_id->choice.pTMSIRAI.rAI.rAC.size,
209 osmo_hexdump(ue_id->choice.pTMSIRAI.rAI.rAC.buf, ue_id->choice.pTMSIRAI.rAI.rAC.size));
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200210
211 BIT_STRING_fromBuf(&reject.uE_Identity.choice.pTMSIRAI.pTMSI,
212 ue_id->choice.pTMSIRAI.pTMSI.buf,
213 ue_id->choice.pTMSIRAI.pTMSI.size * 8
214 - ue_id->choice.pTMSIRAI.pTMSI.bits_unused);
215 OCTET_STRING_fromBuf(&reject.uE_Identity.choice.pTMSIRAI.rAI.lAI.pLMNID,
Pau Espin Pedrola008b172020-03-20 20:29:22 +0100216 (const char *)ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.buf,
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200217 ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.size);
218 OCTET_STRING_fromBuf(&reject.uE_Identity.choice.pTMSIRAI.rAI.lAI.lAC,
Pau Espin Pedrola008b172020-03-20 20:29:22 +0100219 (const char *)ue_id->choice.pTMSIRAI.rAI.lAI.lAC.buf,
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200220 ue_id->choice.pTMSIRAI.rAI.lAI.lAC.size);
221 OCTET_STRING_fromBuf(&reject.uE_Identity.choice.pTMSIRAI.rAI.rAC,
Pau Espin Pedrola008b172020-03-20 20:29:22 +0100222 (const char *)ue_id->choice.pTMSIRAI.rAI.rAC.buf,
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200223 ue_id->choice.pTMSIRAI.rAI.rAC.size);
224 break;
225
226 default:
Harald Weltef05c5bf2020-12-30 14:17:34 +0100227 LOGHNB(hnb, DHNBAP, LOGL_ERROR, "Cannot compose UE Register Reject:"
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200228 " unsupported UE ID (present=%d)\n", ue_id->present);
Neels Hofmeyr1a0bb512016-04-25 14:55:35 +0200229 return -1;
230 }
231
Harald Weltef05c5bf2020-12-30 14:17:34 +0100232 LOGHNB(hnb, DHNBAP, LOGL_ERROR, "Rejecting UE Register Request: TMSI identity registration is switched off\n");
Neels Hofmeyr1a0bb512016-04-25 14:55:35 +0200233
234 reject.cause.present = Cause_PR_radioNetwork;
235 reject.cause.choice.radioNetwork = CauseRadioNetwork_invalid_UE_identity;
236
237 memset(&reject_out, 0, sizeof(reject_out));
238 rc = hnbap_encode_ueregisterrejecties(&reject_out, &reject);
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200239 if (rc < 0)
Neels Hofmeyr1a0bb512016-04-25 14:55:35 +0200240 return rc;
Neels Hofmeyr1a0bb512016-04-25 14:55:35 +0200241
242 msg = hnbap_generate_unsuccessful_outcome(ProcedureCode_id_UERegister,
243 Criticality_reject,
244 &asn_DEF_UERegisterReject,
245 &reject_out);
246
Neels Hofmeyrc94ed092016-09-26 01:27:55 +0200247 /* Free copied identity IEs */
248 switch (ue_id->present) {
249 case UE_Identity_PR_tMSILAI:
250 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_BIT_STRING,
251 &reject.uE_Identity.choice.tMSILAI.tMSI);
252 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
253 &reject.uE_Identity.choice.tMSILAI.lAI.pLMNID);
254 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
255 &reject.uE_Identity.choice.tMSILAI.lAI.lAC);
256 break;
257
258 case UE_Identity_PR_pTMSIRAI:
259 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_BIT_STRING,
260 &reject.uE_Identity.choice.pTMSIRAI.pTMSI);
261 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
262 &reject.uE_Identity.choice.pTMSIRAI.rAI.lAI.pLMNID);
263 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
264 &reject.uE_Identity.choice.pTMSIRAI.rAI.lAI.lAC);
265 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
266 &reject.uE_Identity.choice.pTMSIRAI.rAI.rAC);
267 break;
268
269 default:
270 /* should never happen after above switch() */
271 break;
272 }
273
Neels Hofmeyr1a0bb512016-04-25 14:55:35 +0200274 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_UERegisterReject, &reject_out);
275
276 return hnbgw_hnbap_tx(hnb, msg);
277}
278
Neels Hofmeyr12181a92016-04-25 15:05:32 +0200279static int hnbgw_tx_ue_register_acc_tmsi(struct hnb_context *hnb, UE_Identity_t *ue_id)
280{
281 UERegisterAccept_t accept_out;
282 UERegisterAcceptIEs_t accept;
283 struct msgb *msg;
284 uint32_t ctx_id;
285 uint32_t tmsi = 0;
286 struct ue_context *ue;
287 int rc;
288
289 memset(&accept, 0, sizeof(accept));
290 accept.uE_Identity.present = ue_id->present;
291
292 switch (ue_id->present) {
293 case UE_Identity_PR_tMSILAI:
294 BIT_STRING_fromBuf(&accept.uE_Identity.choice.tMSILAI.tMSI,
295 ue_id->choice.tMSILAI.tMSI.buf,
296 ue_id->choice.tMSILAI.tMSI.size * 8
297 - ue_id->choice.tMSILAI.tMSI.bits_unused);
298 tmsi = *(uint32_t*)accept.uE_Identity.choice.tMSILAI.tMSI.buf;
299 OCTET_STRING_fromBuf(&accept.uE_Identity.choice.tMSILAI.lAI.pLMNID,
Pau Espin Pedrola008b172020-03-20 20:29:22 +0100300 (const char *)ue_id->choice.tMSILAI.lAI.pLMNID.buf,
Neels Hofmeyr12181a92016-04-25 15:05:32 +0200301 ue_id->choice.tMSILAI.lAI.pLMNID.size);
302 OCTET_STRING_fromBuf(&accept.uE_Identity.choice.tMSILAI.lAI.lAC,
Pau Espin Pedrola008b172020-03-20 20:29:22 +0100303 (const char *)ue_id->choice.tMSILAI.lAI.lAC.buf,
Neels Hofmeyr12181a92016-04-25 15:05:32 +0200304 ue_id->choice.tMSILAI.lAI.lAC.size);
305 break;
306
307 case UE_Identity_PR_pTMSIRAI:
308 BIT_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.pTMSI,
309 ue_id->choice.pTMSIRAI.pTMSI.buf,
310 ue_id->choice.pTMSIRAI.pTMSI.size * 8
311 - ue_id->choice.pTMSIRAI.pTMSI.bits_unused);
312 tmsi = *(uint32_t*)accept.uE_Identity.choice.pTMSIRAI.pTMSI.buf;
313 OCTET_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.pLMNID,
Pau Espin Pedrola008b172020-03-20 20:29:22 +0100314 (const char *)ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.buf,
Neels Hofmeyr12181a92016-04-25 15:05:32 +0200315 ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.size);
316 OCTET_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.lAC,
Pau Espin Pedrola008b172020-03-20 20:29:22 +0100317 (const char *)ue_id->choice.pTMSIRAI.rAI.lAI.lAC.buf,
Neels Hofmeyr12181a92016-04-25 15:05:32 +0200318 ue_id->choice.pTMSIRAI.rAI.lAI.lAC.size);
319 OCTET_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.rAI.rAC,
Pau Espin Pedrola008b172020-03-20 20:29:22 +0100320 (const char *)ue_id->choice.pTMSIRAI.rAI.rAC.buf,
Neels Hofmeyr12181a92016-04-25 15:05:32 +0200321 ue_id->choice.pTMSIRAI.rAI.rAC.size);
322 break;
323
324 default:
Harald Weltef05c5bf2020-12-30 14:17:34 +0100325 LOGHNB(hnb, DHNBAP, LOGL_ERROR, "Unsupportedccept UE ID (present=%d)\n", ue_id->present);
Neels Hofmeyr12181a92016-04-25 15:05:32 +0200326 return -1;
327 }
328
329 tmsi = ntohl(tmsi);
Harald Weltef05c5bf2020-12-30 14:17:34 +0100330 LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "HNBAP register with TMSI %x\n", tmsi);
Neels Hofmeyr12181a92016-04-25 15:05:32 +0200331
332 ue = ue_context_by_tmsi(hnb->gw, tmsi);
333 if (!ue)
334 ue = ue_context_alloc(hnb, NULL, tmsi);
335
336 asn1_u24_to_bitstring(&accept.context_ID, &ctx_id, ue->context_id);
337
338 memset(&accept_out, 0, sizeof(accept_out));
339 rc = hnbap_encode_ueregisteraccepties(&accept_out, &accept);
340 if (rc < 0)
341 return rc;
342
343 msg = hnbap_generate_successful_outcome(ProcedureCode_id_UERegister,
344 Criticality_reject,
345 &asn_DEF_UERegisterAccept,
346 &accept_out);
347
348 switch (ue_id->present) {
349 case UE_Identity_PR_tMSILAI:
350 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_BIT_STRING,
351 &accept.uE_Identity.choice.tMSILAI.tMSI);
352 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
353 &accept.uE_Identity.choice.tMSILAI.lAI.pLMNID);
354 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
355 &accept.uE_Identity.choice.tMSILAI.lAI.lAC);
356 break;
357
358 case UE_Identity_PR_pTMSIRAI:
359 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_BIT_STRING,
360 &accept.uE_Identity.choice.pTMSIRAI.pTMSI);
361 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
362 &accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.pLMNID);
363 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
364 &accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.lAC);
365 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
366 &accept.uE_Identity.choice.pTMSIRAI.rAI.rAC);
367 break;
368
369 default:
370 /* should never happen after above switch() */
371 break;
372 }
373
374 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_UERegisterAccept, &accept_out);
375
376 return hnbgw_hnbap_tx(hnb, msg);
377}
378
Daniel Willmannb433b972016-01-06 18:08:21 +0100379static int hnbgw_rx_hnb_deregister(struct hnb_context *ctx, ANY_t *in)
380{
381 HNBDe_RegisterIEs_t ies;
382 int rc;
383
384 rc = hnbap_decode_hnbde_registeries(&ies, in);
385 if (rc < 0)
386 return rc;
387
Harald Weltef05c5bf2020-12-30 14:17:34 +0100388 LOGHNB(ctx, DHNBAP, LOGL_DEBUG, "HNB-DE-REGISTER cause=%s\n", hnbap_cause_str(&ies.cause));
Daniel Willmannb433b972016-01-06 18:08:21 +0100389
Daniel Willmannd10002c2016-01-07 12:27:41 +0100390 hnbap_free_hnbde_registeries(&ies);
Alexander Couzensad4ea3b2018-07-24 19:04:47 +0200391 hnb_context_release(ctx);
Daniel Willmannb433b972016-01-06 18:08:21 +0100392
393 return 0;
394}
395
Harald Welte27f9c4a2015-08-30 22:47:18 +0200396static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, ANY_t *in)
Harald Welteba43de42015-08-29 20:33:16 +0200397{
Stefan Sperlingc964a2c2018-02-19 17:02:12 +0100398 struct hnb_context *hnb;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200399 HNBRegisterRequestIEs_t ies;
400 int rc;
Harald Welteba43de42015-08-29 20:33:16 +0200401
Harald Welte27f9c4a2015-08-30 22:47:18 +0200402 rc = hnbap_decode_hnbregisterrequesties(&ies, in);
Neels Hofmeyr2293df02018-01-18 19:01:09 +0100403 if (rc < 0) {
Harald Weltef05c5bf2020-12-30 14:17:34 +0100404 LOGHNB(ctx, DHNBAP, LOGL_ERROR, "Failure to decode HNB-REGISTER-REQ from %s: rc=%d\n",
405 ctx->identity_info, rc);
Harald Welte27f9c4a2015-08-30 22:47:18 +0200406 return rc;
Neels Hofmeyr2293df02018-01-18 19:01:09 +0100407 }
Harald Welteba43de42015-08-29 20:33:16 +0200408
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200409 /* copy all identity parameters from the message to ctx */
Harald Welte27f9c4a2015-08-30 22:47:18 +0200410 asn1_strncpy(ctx->identity_info, &ies.hnB_Identity.hNB_Identity_Info,
411 sizeof(ctx->identity_info));
412 ctx->id.lac = asn1str_to_u16(&ies.lac);
413 ctx->id.sac = asn1str_to_u16(&ies.sac);
414 ctx->id.rac = asn1str_to_u8(&ies.rac);
Daniel Willmannd6a45b42015-12-08 13:55:17 +0100415 ctx->id.cid = asn1bitstr_to_u28(&ies.cellIdentity);
Neels Hofmeyr66d6d762017-12-20 05:25:02 +0100416 gsm48_mcc_mnc_from_bcd(ies.plmNidentity.buf, &ctx->id.mcc, &ctx->id.mnc);
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200417
Stefan Sperlingc964a2c2018-02-19 17:02:12 +0100418 llist_for_each_entry(hnb, &ctx->gw->hnb_list, list) {
419 if (hnb->hnb_registered && ctx != hnb && memcmp(&ctx->id, &hnb->id, sizeof(ctx->id)) == 0) {
420 struct osmo_fd *ofd = osmo_stream_srv_get_ofd(ctx->conn);
421 char *name = osmo_sock_get_name(ctx, ofd->fd);
Harald Weltef05c5bf2020-12-30 14:17:34 +0100422 LOGHNB(ctx, DHNBAP, LOGL_ERROR, "rejecting HNB-REGISTER-REQ with duplicate cell identity "
423 "MCC=%u,MNC=%u,LAC=%u,RAC=%u,SAC=%u,CID=%u from %s\n",
424 ctx->id.mcc, ctx->id.mnc, ctx->id.lac, ctx->id.rac, ctx->id.sac, ctx->id.cid, name);
Stefan Sperlingc964a2c2018-02-19 17:02:12 +0100425 talloc_free(name);
426 return hnbgw_tx_hnb_register_rej(ctx);
427 }
428 }
429
430 ctx->hnb_registered = true;
431
Harald Weltef05c5bf2020-12-30 14:17:34 +0100432 LOGHNB(ctx, DHNBAP, LOGL_DEBUG, "HNB-REGISTER-REQ from %s\n", ctx->identity_info);
Harald Welteee77cff2015-08-30 16:57:53 +0200433
Harald Welte27f9c4a2015-08-30 22:47:18 +0200434 /* Send HNBRegisterAccept */
Daniel Willmannd10002c2016-01-07 12:27:41 +0100435 rc = hnbgw_tx_hnb_register_acc(ctx);
436 hnbap_free_hnbregisterrequesties(&ies);
437 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200438}
439
Harald Welte27f9c4a2015-08-30 22:47:18 +0200440static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, ANY_t *in)
Harald Welteba43de42015-08-29 20:33:16 +0200441{
Harald Welte27f9c4a2015-08-30 22:47:18 +0200442 UERegisterRequestIEs_t ies;
443 struct ue_context *ue;
Harald Welte10dfc5a2015-09-11 01:34:45 +0200444 char imsi[16];
Harald Welte27f9c4a2015-08-30 22:47:18 +0200445 int rc;
Harald Welteba43de42015-08-29 20:33:16 +0200446
Harald Welte27f9c4a2015-08-30 22:47:18 +0200447 rc = hnbap_decode_ueregisterrequesties(&ies, in);
448 if (rc < 0)
449 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200450
Harald Welte10dfc5a2015-09-11 01:34:45 +0200451 switch (ies.uE_Identity.present) {
452 case UE_Identity_PR_iMSI:
Harald Welte056984f2016-01-03 16:31:31 +0100453 ranap_bcd_decode(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSI.buf,
Harald Welte10dfc5a2015-09-11 01:34:45 +0200454 ies.uE_Identity.choice.iMSI.size);
455 break;
456 case UE_Identity_PR_iMSIDS41:
Harald Welte056984f2016-01-03 16:31:31 +0100457 ranap_bcd_decode(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIDS41.buf,
Harald Welte10dfc5a2015-09-11 01:34:45 +0200458 ies.uE_Identity.choice.iMSIDS41.size);
459 break;
460 case UE_Identity_PR_iMSIESN:
Harald Welte056984f2016-01-03 16:31:31 +0100461 ranap_bcd_decode(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIESN.iMSIDS41.buf,
Harald Welte10dfc5a2015-09-11 01:34:45 +0200462 ies.uE_Identity.choice.iMSIESN.iMSIDS41.size);
463 break;
Neels Hofmeyr12181a92016-04-25 15:05:32 +0200464 case UE_Identity_PR_tMSILAI:
465 case UE_Identity_PR_pTMSIRAI:
466 if (ctx->gw->config.hnbap_allow_tmsi)
467 rc = hnbgw_tx_ue_register_acc_tmsi(ctx, &ies.uE_Identity);
468 else
469 rc = hnbgw_tx_ue_register_rej_tmsi(ctx, &ies.uE_Identity);
470 /* all has been handled by TMSI, skip the IMSI code below */
471 hnbap_free_ueregisterrequesties(&ies);
472 return rc;
Harald Welte10dfc5a2015-09-11 01:34:45 +0200473 default:
Harald Weltef05c5bf2020-12-30 14:17:34 +0100474 LOGHNB(ctx, DHNBAP, LOGL_NOTICE, "UE-REGISTER-REQ with unsupported UE Id type %d\n",
475 ies.uE_Identity.present);
Neels Hofmeyrb248c8c2016-04-25 14:51:27 +0200476 hnbap_free_ueregisterrequesties(&ies);
Neels Hofmeyr1a0bb512016-04-25 14:55:35 +0200477 return rc;
Harald Welte10dfc5a2015-09-11 01:34:45 +0200478 }
Harald Welteb534e5c2015-09-11 00:15:16 +0200479
Harald Weltef05c5bf2020-12-30 14:17:34 +0100480 LOGHNB(ctx, DHNBAP, LOGL_DEBUG, "UE-REGISTER-REQ ID_type=%d imsi=%s cause=%ld\n",
Harald Welte10dfc5a2015-09-11 01:34:45 +0200481 ies.uE_Identity.present, imsi, ies.registration_Cause);
482
Harald Weltec4338de2015-12-24 00:40:52 +0100483 ue = ue_context_by_imsi(ctx->gw, imsi);
Harald Welte10dfc5a2015-09-11 01:34:45 +0200484 if (!ue)
Neels Hofmeyrf33e8352016-09-22 18:06:59 +0200485 ue = ue_context_alloc(ctx, imsi, 0);
Harald Welte27f9c4a2015-08-30 22:47:18 +0200486
Daniel Willmannd10002c2016-01-07 12:27:41 +0100487 hnbap_free_ueregisterrequesties(&ies);
Harald Welte27f9c4a2015-08-30 22:47:18 +0200488 /* Send UERegisterAccept */
489 return hnbgw_tx_ue_register_acc(ue);
Harald Welteba43de42015-08-29 20:33:16 +0200490}
491
Daniel Willmannefceb182015-12-15 20:30:12 +0100492static int hnbgw_rx_ue_deregister(struct hnb_context *ctx, ANY_t *in)
493{
494 UEDe_RegisterIEs_t ies;
495 struct ue_context *ue;
496 int rc;
497 uint32_t ctxid;
498
499 rc = hnbap_decode_uede_registeries(&ies, in);
500 if (rc < 0)
501 return rc;
502
503 ctxid = asn1bitstr_to_u24(&ies.context_ID);
504
Harald Weltef05c5bf2020-12-30 14:17:34 +0100505 LOGHNB(ctx, DHNBAP, LOGL_DEBUG, "UE-DE-REGISTER context=%u cause=%s\n", ctxid, hnbap_cause_str(&ies.cause));
Daniel Willmannefceb182015-12-15 20:30:12 +0100506
Harald Weltec4338de2015-12-24 00:40:52 +0100507 ue = ue_context_by_id(ctx->gw, ctxid);
Daniel Willmannefceb182015-12-15 20:30:12 +0100508 if (ue)
509 ue_context_free(ue);
510
Daniel Willmannd10002c2016-01-07 12:27:41 +0100511 hnbap_free_uede_registeries(&ies);
Daniel Willmannefceb182015-12-15 20:30:12 +0100512 return 0;
513}
514
Harald Welte3af1db82015-09-11 17:03:16 +0200515static int hnbgw_rx_err_ind(struct hnb_context *hnb, ANY_t *in)
516{
517 ErrorIndicationIEs_t ies;
518 int rc;
519
Harald Welte1d2c39d2015-09-11 17:49:37 +0200520 rc = hnbap_decode_errorindicationies(&ies, in);
Harald Welte3af1db82015-09-11 17:03:16 +0200521 if (rc < 0)
522 return rc;
523
Harald Weltef05c5bf2020-12-30 14:17:34 +0100524 LOGHNB(hnb, DHNBAP, LOGL_NOTICE, "HNBAP ERROR.ind, cause: %s\n", hnbap_cause_str(&ies.cause));
Harald Welte3af1db82015-09-11 17:03:16 +0200525
Daniel Willmannd10002c2016-01-07 12:27:41 +0100526 hnbap_free_errorindicationies(&ies);
Harald Welte3af1db82015-09-11 17:03:16 +0200527 return 0;
528}
529
Harald Welte27f9c4a2015-08-30 22:47:18 +0200530static int hnbgw_rx_initiating_msg(struct hnb_context *hnb, InitiatingMessage_t *imsg)
Harald Welteba43de42015-08-29 20:33:16 +0200531{
Harald Welteda86fe52017-11-21 08:14:37 +0100532 int rc = 0;
Harald Welteba43de42015-08-29 20:33:16 +0200533
Harald Welteb3dae302015-08-30 12:20:09 +0200534 switch (imsg->procedureCode) {
Harald Welte27f9c4a2015-08-30 22:47:18 +0200535 case ProcedureCode_id_HNBRegister: /* 8.2 */
536 rc = hnbgw_rx_hnb_register_req(hnb, &imsg->value);
Harald Welteba43de42015-08-29 20:33:16 +0200537 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200538 case ProcedureCode_id_HNBDe_Register: /* 8.3 */
Daniel Willmannb433b972016-01-06 18:08:21 +0100539 rc = hnbgw_rx_hnb_deregister(hnb, &imsg->value);
Harald Welteba43de42015-08-29 20:33:16 +0200540 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200541 case ProcedureCode_id_UERegister: /* 8.4 */
542 rc = hnbgw_rx_ue_register_req(hnb, &imsg->value);
Harald Welteba43de42015-08-29 20:33:16 +0200543 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200544 case ProcedureCode_id_UEDe_Register: /* 8.5 */
Daniel Willmannefceb182015-12-15 20:30:12 +0100545 rc = hnbgw_rx_ue_deregister(hnb, &imsg->value);
Harald Welteba43de42015-08-29 20:33:16 +0200546 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200547 case ProcedureCode_id_ErrorIndication: /* 8.6 */
Harald Welte3af1db82015-09-11 17:03:16 +0200548 rc = hnbgw_rx_err_ind(hnb, &imsg->value);
549 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200550 case ProcedureCode_id_TNLUpdate: /* 8.9 */
551 case ProcedureCode_id_HNBConfigTransfer: /* 8.10 */
552 case ProcedureCode_id_RelocationComplete: /* 8.11 */
553 case ProcedureCode_id_U_RNTIQuery: /* 8.12 */
554 case ProcedureCode_id_privateMessage:
Harald Weltef05c5bf2020-12-30 14:17:34 +0100555 LOGHNB(hnb, DHNBAP, LOGL_NOTICE, "Unimplemented HNBAP Procedure %ld\n", imsg->procedureCode);
Harald Welteba43de42015-08-29 20:33:16 +0200556 break;
557 default:
Harald Weltef05c5bf2020-12-30 14:17:34 +0100558 LOGHNB(hnb, DHNBAP, LOGL_NOTICE, "Unknown HNBAP Procedure %ld\n", imsg->procedureCode);
Harald Welteba43de42015-08-29 20:33:16 +0200559 break;
560 }
Harald Welteda86fe52017-11-21 08:14:37 +0100561
562 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200563}
564
Harald Welte27f9c4a2015-08-30 22:47:18 +0200565static int hnbgw_rx_successful_outcome_msg(struct hnb_context *hnb, SuccessfulOutcome_t *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200566{
Neels Hofmeyr02296af2018-01-15 23:30:06 +0100567 /* We don't care much about HNBAP */
568 return 0;
Harald Welteba43de42015-08-29 20:33:16 +0200569}
570
Harald Welte27f9c4a2015-08-30 22:47:18 +0200571static int hnbgw_rx_unsuccessful_outcome_msg(struct hnb_context *hnb, UnsuccessfulOutcome_t *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200572{
Neels Hofmeyr02296af2018-01-15 23:30:06 +0100573 /* We don't care much about HNBAP */
Harald Weltef05c5bf2020-12-30 14:17:34 +0100574 LOGHNB(hnb, DHNBAP, LOGL_ERROR, "Received Unsuccessful Outcome, procedureCode %ld, criticality %ld,"
575 " cell mcc %u mnc %u lac %u rac %u sac %u cid %u\n", msg->procedureCode, msg->criticality,
576 hnb->id.mcc, hnb->id.mnc, hnb->id.lac, hnb->id.rac, hnb->id.sac, hnb->id.cid);
Neels Hofmeyr02296af2018-01-15 23:30:06 +0100577 return 0;
Harald Welteba43de42015-08-29 20:33:16 +0200578}
579
580
Harald Welte27f9c4a2015-08-30 22:47:18 +0200581static int _hnbgw_hnbap_rx(struct hnb_context *hnb, HNBAP_PDU_t *pdu)
Harald Welteba43de42015-08-29 20:33:16 +0200582{
Daniel Willmann5f810f42015-12-17 17:57:51 +0100583 int rc = 0;
Harald Welteb3dae302015-08-30 12:20:09 +0200584
Harald Welteba43de42015-08-29 20:33:16 +0200585 /* it's a bit odd that we can't dispatch on procedure code, but
586 * that's not possible */
Harald Welte27f9c4a2015-08-30 22:47:18 +0200587 switch (pdu->present) {
588 case HNBAP_PDU_PR_initiatingMessage:
589 rc = hnbgw_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage);
Harald Welteba43de42015-08-29 20:33:16 +0200590 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200591 case HNBAP_PDU_PR_successfulOutcome:
592 rc = hnbgw_rx_successful_outcome_msg(hnb, &pdu->choice.successfulOutcome);
Harald Welteba43de42015-08-29 20:33:16 +0200593 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200594 case HNBAP_PDU_PR_unsuccessfulOutcome:
595 rc = hnbgw_rx_unsuccessful_outcome_msg(hnb, &pdu->choice.unsuccessfulOutcome);
Harald Welteba43de42015-08-29 20:33:16 +0200596 break;
597 default:
Harald Weltef05c5bf2020-12-30 14:17:34 +0100598 LOGHNB(hnb, DHNBAP, LOGL_NOTICE, "Unknown HNBAP Presence %u\n", pdu->present);
Daniel Willmann5f810f42015-12-17 17:57:51 +0100599 rc = -1;
Harald Welteba43de42015-08-29 20:33:16 +0200600 }
Daniel Willmann5f810f42015-12-17 17:57:51 +0100601
602 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200603}
604
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200605int hnbgw_hnbap_rx(struct hnb_context *hnb, struct msgb *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200606{
Harald Welte27f9c4a2015-08-30 22:47:18 +0200607 HNBAP_PDU_t _pdu, *pdu = &_pdu;
608 asn_dec_rval_t dec_ret;
Harald Welteee77cff2015-08-30 16:57:53 +0200609 int rc;
610
611 /* decode and handle to _hnbgw_hnbap_rx() */
612
Harald Welte2204f9d2015-09-07 21:10:50 +0200613 memset(pdu, 0, sizeof(*pdu));
Harald Welte27f9c4a2015-08-30 22:47:18 +0200614 dec_ret = aper_decode(NULL, &asn_DEF_HNBAP_PDU, (void **) &pdu,
615 msg->data, msgb_length(msg), 0, 0);
616 if (dec_ret.code != RC_OK) {
Harald Weltef05c5bf2020-12-30 14:17:34 +0100617 LOGHNB(hnb, DHNBAP, LOGL_ERROR, "Error in ASN.1 decode\n");
Neels Hofmeyra6a68e62016-11-25 13:21:02 +0100618 return -1;
Harald Welteee77cff2015-08-30 16:57:53 +0200619 }
620
621 rc = _hnbgw_hnbap_rx(hnb, pdu);
Harald Welteee77cff2015-08-30 16:57:53 +0200622
Daniel Willmann59d17d82015-12-17 17:56:56 +0100623 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBAP_PDU, pdu);
624
Harald Welteee77cff2015-08-30 16:57:53 +0200625 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200626}
627
628
629int hnbgw_hnbap_init(void)
630{
Harald Welteda86fe52017-11-21 08:14:37 +0100631 return 0;
Harald Welteba43de42015-08-29 20:33:16 +0200632}