blob: 4896f343d4b215840b3070fa84bf1fe030b07b4e [file] [log] [blame]
Harald Welteba43de42015-08-29 20:33:16 +02001#include <osmocom/core/msgb.h>
Harald Welteb3dae302015-08-30 12:20:09 +02002#include <osmocom/core/utils.h>
Harald Welte10dfc5a2015-09-11 01:34:45 +02003#include <osmocom/gsm/gsm48.h>
Harald Welteba43de42015-08-29 20:33:16 +02004
Harald Welteb3dae302015-08-30 12:20:09 +02005#include <unistd.h>
Harald Welteee77cff2015-08-30 16:57:53 +02006#include <errno.h>
Harald Welteb3dae302015-08-30 12:20:09 +02007#include <string.h>
8
Harald Welte30afef32015-08-30 12:28:29 +02009#include "asn1helpers.h"
Harald Welte1d2c39d2015-09-11 17:49:37 +020010#include "iu_helpers.h"
Harald Welte30afef32015-08-30 12:28:29 +020011
Harald Welteba43de42015-08-29 20:33:16 +020012#include "hnbgw.h"
Harald Welte27f9c4a2015-08-30 22:47:18 +020013#include "hnbap_common.h"
14#include "hnbap_ies_defs.h"
Harald Welteba43de42015-08-29 20:33:16 +020015
Harald Welteee77cff2015-08-30 16:57:53 +020016#define IU_MSG_NUM_IES 32
17#define IU_MSG_NUM_EXT_IES 32
18
Harald Welte27f9c4a2015-08-30 22:47:18 +020019static int hnbgw_hnbap_tx(struct hnb_context *ctx, struct msgb *msg)
Harald Welteee77cff2015-08-30 16:57:53 +020020{
Harald Welte7b54e322015-09-07 22:41:45 +020021 if (!msg)
22 return -EINVAL;
23
Harald Welte3f712562015-09-07 21:53:25 +020024 msgb_ppid(msg) = IUH_PPI_HNBAP;
25 return osmo_wqueue_enqueue(&ctx->wqueue, msg);
Harald Welte27f9c4a2015-08-30 22:47:18 +020026}
Harald Welteee77cff2015-08-30 16:57:53 +020027
Harald Welte27f9c4a2015-08-30 22:47:18 +020028static int hnbgw_tx_hnb_register_acc(struct hnb_context *ctx)
29{
30 HNBRegisterAccept_t accept_out;
31 struct msgb *msg;
32 int rc;
33
34 /* Single required response IE: RNC-ID */
35 HNBRegisterAcceptIEs_t accept = {
36 .rnc_id = ctx->gw->config.rnc_id
37 };
38
39 /* encode the Information Elements */
Harald Welte2204f9d2015-09-07 21:10:50 +020040 memset(&accept_out, 0, sizeof(accept_out));
Harald Welte27f9c4a2015-08-30 22:47:18 +020041 rc = hnbap_encode_hnbregisteraccepties(&accept_out, &accept);
42 if (rc < 0) {
43 return rc;
Harald Welteee77cff2015-08-30 16:57:53 +020044 }
45
Harald Welte27f9c4a2015-08-30 22:47:18 +020046 /* generate a successfull outcome PDU */
47 msg = hnbap_generate_successful_outcome(ProcedureCode_id_HNBRegister,
48 Criticality_reject,
49 &asn_DEF_HNBRegisterAccept,
50 &accept_out);
Harald Welteee77cff2015-08-30 16:57:53 +020051
Harald Welte27f9c4a2015-08-30 22:47:18 +020052 return hnbgw_hnbap_tx(ctx, msg);
Harald Welteee77cff2015-08-30 16:57:53 +020053}
54
55
Harald Welte27f9c4a2015-08-30 22:47:18 +020056static int hnbgw_tx_ue_register_acc(struct ue_context *ue)
Harald Welteba43de42015-08-29 20:33:16 +020057{
Harald Welte27f9c4a2015-08-30 22:47:18 +020058 UERegisterAccept_t accept_out;
59 UERegisterAcceptIEs_t accept;
60 struct msgb *msg;
Harald Welte10dfc5a2015-09-11 01:34:45 +020061 uint8_t encoded_imsi[10];
62 size_t encoded_imsi_len;
Harald Welte27f9c4a2015-08-30 22:47:18 +020063 int rc;
Harald Welteba43de42015-08-29 20:33:16 +020064
Harald Welte1d2c39d2015-09-11 17:49:37 +020065 encoded_imsi_len = encode_iu_imsi(encoded_imsi,
66 sizeof(encoded_imsi), ue->imsi);
Harald Welte10dfc5a2015-09-11 01:34:45 +020067
Harald Welte2204f9d2015-09-07 21:10:50 +020068 memset(&accept, 0, sizeof(accept));
Harald Welte10dfc5a2015-09-11 01:34:45 +020069 accept.uE_Identity.present = UE_Identity_PR_iMSI;
Harald Welte1d2c39d2015-09-11 17:49:37 +020070 OCTET_STRING_fromBuf(&accept.uE_Identity.choice.iMSI,
71 (const char *)encoded_imsi, encoded_imsi_len);
Harald Welte27f9c4a2015-08-30 22:47:18 +020072 asn1_u32_to_bitstring(&accept.context_ID, &ue->context_id);
Harald Welte62868802015-09-18 01:23:55 +020073 accept.context_ID.size = 3; /* 24bit field */
Harald Welteba43de42015-08-29 20:33:16 +020074
Harald Welte2204f9d2015-09-07 21:10:50 +020075 memset(&accept_out, 0, sizeof(accept_out));
Harald Welte27f9c4a2015-08-30 22:47:18 +020076 rc = hnbap_encode_ueregisteraccepties(&accept_out, &accept);
77 if (rc < 0) {
78 return rc;
Harald Welteba43de42015-08-29 20:33:16 +020079 }
Harald Welte27f9c4a2015-08-30 22:47:18 +020080
81 msg = hnbap_generate_successful_outcome(ProcedureCode_id_UERegister,
82 Criticality_reject,
83 &asn_DEF_UERegisterAccept,
84 &accept_out);
85 return hnbgw_hnbap_tx(ue->hnb, msg);
Harald Welteba43de42015-08-29 20:33:16 +020086}
87
Harald Welte27f9c4a2015-08-30 22:47:18 +020088static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, ANY_t *in)
Harald Welteba43de42015-08-29 20:33:16 +020089{
Harald Welte27f9c4a2015-08-30 22:47:18 +020090 HNBRegisterRequestIEs_t ies;
91 int rc;
Harald Welteba43de42015-08-29 20:33:16 +020092
Harald Welte27f9c4a2015-08-30 22:47:18 +020093 rc = hnbap_decode_hnbregisterrequesties(&ies, in);
94 if (rc < 0)
95 return rc;
Harald Welteba43de42015-08-29 20:33:16 +020096
Harald Weltea2e6a7a2015-08-29 21:47:39 +020097 /* copy all identity parameters from the message to ctx */
Harald Welte27f9c4a2015-08-30 22:47:18 +020098 asn1_strncpy(ctx->identity_info, &ies.hnB_Identity.hNB_Identity_Info,
99 sizeof(ctx->identity_info));
100 ctx->id.lac = asn1str_to_u16(&ies.lac);
101 ctx->id.sac = asn1str_to_u16(&ies.sac);
102 ctx->id.rac = asn1str_to_u8(&ies.rac);
103 ctx->id.cid = asn1bitstr_to_u32(&ies.cellIdentity);
Harald Welteb3dae302015-08-30 12:20:09 +0200104 //ctx->id.mcc FIXME
105 //ctx->id.mnc FIXME
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200106
Harald Welteee77cff2015-08-30 16:57:53 +0200107 DEBUGP(DMAIN, "HNB-REGISTER-REQ from %s\n", ctx->identity_info);
108
Harald Welte27f9c4a2015-08-30 22:47:18 +0200109 /* Send HNBRegisterAccept */
110 return hnbgw_tx_hnb_register_acc(ctx);
Harald Welteba43de42015-08-29 20:33:16 +0200111}
112
Harald Welte27f9c4a2015-08-30 22:47:18 +0200113static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, ANY_t *in)
Harald Welteba43de42015-08-29 20:33:16 +0200114{
Harald Welte27f9c4a2015-08-30 22:47:18 +0200115 UERegisterRequestIEs_t ies;
116 struct ue_context *ue;
Harald Welte10dfc5a2015-09-11 01:34:45 +0200117 char imsi[16];
Harald Welte27f9c4a2015-08-30 22:47:18 +0200118 int rc;
Harald Welteba43de42015-08-29 20:33:16 +0200119
Harald Welte27f9c4a2015-08-30 22:47:18 +0200120 rc = hnbap_decode_ueregisterrequesties(&ies, in);
121 if (rc < 0)
122 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200123
Harald Welte10dfc5a2015-09-11 01:34:45 +0200124 switch (ies.uE_Identity.present) {
125 case UE_Identity_PR_iMSI:
126 decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSI.buf,
127 ies.uE_Identity.choice.iMSI.size);
128 break;
129 case UE_Identity_PR_iMSIDS41:
130 decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIDS41.buf,
131 ies.uE_Identity.choice.iMSIDS41.size);
132 break;
133 case UE_Identity_PR_iMSIESN:
134 decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIESN.iMSIDS41.buf,
135 ies.uE_Identity.choice.iMSIESN.iMSIDS41.size);
136 break;
137 default:
Harald Welte1d2c39d2015-09-11 17:49:37 +0200138 LOGP(DMAIN, LOGL_NOTICE, "UE-REGISTER-REQ without IMSI?!?\n");
Harald Welte10dfc5a2015-09-11 01:34:45 +0200139 return -1;
140 }
Harald Welteb534e5c2015-09-11 00:15:16 +0200141
Harald Welte10dfc5a2015-09-11 01:34:45 +0200142 DEBUGP(DMAIN, "UE-REGSITER-REQ ID_type=%d imsi=%s cause=%ld\n",
143 ies.uE_Identity.present, imsi, ies.registration_Cause);
144
145 ue = ue_context_by_imsi(imsi);
146 if (!ue)
147 ue = ue_context_alloc(ctx, imsi);
Harald Welte27f9c4a2015-08-30 22:47:18 +0200148
Harald Welte27f9c4a2015-08-30 22:47:18 +0200149 /* Send UERegisterAccept */
150 return hnbgw_tx_ue_register_acc(ue);
Harald Welteba43de42015-08-29 20:33:16 +0200151}
152
Harald Welte3af1db82015-09-11 17:03:16 +0200153static int hnbgw_rx_err_ind(struct hnb_context *hnb, ANY_t *in)
154{
155 ErrorIndicationIEs_t ies;
156 int rc;
157
Harald Welte1d2c39d2015-09-11 17:49:37 +0200158 rc = hnbap_decode_errorindicationies(&ies, in);
Harald Welte3af1db82015-09-11 17:03:16 +0200159 if (rc < 0)
160 return rc;
161
162 LOGP(DMAIN, LOGL_NOTICE, "HNBAP ERROR.ind, cause: %s\n",
163 hnbap_cause_str(&ies.cause));
164
165 return 0;
166}
167
Harald Welte27f9c4a2015-08-30 22:47:18 +0200168static int hnbgw_rx_initiating_msg(struct hnb_context *hnb, InitiatingMessage_t *imsg)
Harald Welteba43de42015-08-29 20:33:16 +0200169{
170 int rc;
171
Harald Welteb3dae302015-08-30 12:20:09 +0200172 switch (imsg->procedureCode) {
Harald Welte27f9c4a2015-08-30 22:47:18 +0200173 case ProcedureCode_id_HNBRegister: /* 8.2 */
174 rc = hnbgw_rx_hnb_register_req(hnb, &imsg->value);
Harald Welteba43de42015-08-29 20:33:16 +0200175 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200176 case ProcedureCode_id_HNBDe_Register: /* 8.3 */
Harald Welteba43de42015-08-29 20:33:16 +0200177 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200178 case ProcedureCode_id_UERegister: /* 8.4 */
179 rc = hnbgw_rx_ue_register_req(hnb, &imsg->value);
Harald Welteba43de42015-08-29 20:33:16 +0200180 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200181 case ProcedureCode_id_UEDe_Register: /* 8.5 */
Harald Welteba43de42015-08-29 20:33:16 +0200182 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200183 case ProcedureCode_id_ErrorIndication: /* 8.6 */
Harald Welte3af1db82015-09-11 17:03:16 +0200184 rc = hnbgw_rx_err_ind(hnb, &imsg->value);
185 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200186 case ProcedureCode_id_TNLUpdate: /* 8.9 */
187 case ProcedureCode_id_HNBConfigTransfer: /* 8.10 */
188 case ProcedureCode_id_RelocationComplete: /* 8.11 */
189 case ProcedureCode_id_U_RNTIQuery: /* 8.12 */
190 case ProcedureCode_id_privateMessage:
Harald Welte1d2c39d2015-09-11 17:49:37 +0200191 LOGP(DMAIN, LOGL_NOTICE, "Unimplemented HNBAP Procedure %ld\n",
Harald Welte3af1db82015-09-11 17:03:16 +0200192 imsg->procedureCode);
Harald Welteba43de42015-08-29 20:33:16 +0200193 break;
194 default:
Harald Welte1d2c39d2015-09-11 17:49:37 +0200195 LOGP(DMAIN, LOGL_NOTICE, "Unknown HNBAP Procedure %ld\n",
Harald Welte3af1db82015-09-11 17:03:16 +0200196 imsg->procedureCode);
Harald Welteba43de42015-08-29 20:33:16 +0200197 break;
198 }
199}
200
Harald Welte27f9c4a2015-08-30 22:47:18 +0200201static int hnbgw_rx_successful_outcome_msg(struct hnb_context *hnb, SuccessfulOutcome_t *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200202{
203
204}
205
Harald Welte27f9c4a2015-08-30 22:47:18 +0200206static int hnbgw_rx_unsuccessful_outcome_msg(struct hnb_context *hnb, UnsuccessfulOutcome_t *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200207{
208
209}
210
211
Harald Welte27f9c4a2015-08-30 22:47:18 +0200212static int _hnbgw_hnbap_rx(struct hnb_context *hnb, HNBAP_PDU_t *pdu)
Harald Welteba43de42015-08-29 20:33:16 +0200213{
Harald Welteb3dae302015-08-30 12:20:09 +0200214 int rc;
215
Harald Welteba43de42015-08-29 20:33:16 +0200216 /* it's a bit odd that we can't dispatch on procedure code, but
217 * that's not possible */
Harald Welte27f9c4a2015-08-30 22:47:18 +0200218 switch (pdu->present) {
219 case HNBAP_PDU_PR_initiatingMessage:
220 rc = hnbgw_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage);
Harald Welteba43de42015-08-29 20:33:16 +0200221 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200222 case HNBAP_PDU_PR_successfulOutcome:
223 rc = hnbgw_rx_successful_outcome_msg(hnb, &pdu->choice.successfulOutcome);
Harald Welteba43de42015-08-29 20:33:16 +0200224 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200225 case HNBAP_PDU_PR_unsuccessfulOutcome:
226 rc = hnbgw_rx_unsuccessful_outcome_msg(hnb, &pdu->choice.unsuccessfulOutcome);
Harald Welteba43de42015-08-29 20:33:16 +0200227 break;
228 default:
Harald Welte3af1db82015-09-11 17:03:16 +0200229 LOGP(DMAIN, LOGL_NOTICE, "Unknown HNBAP Presence %u\n",
230 pdu->present);
Harald Welteba43de42015-08-29 20:33:16 +0200231 return -1;
232 }
233}
234
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200235int hnbgw_hnbap_rx(struct hnb_context *hnb, struct msgb *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200236{
Harald Welte27f9c4a2015-08-30 22:47:18 +0200237 HNBAP_PDU_t _pdu, *pdu = &_pdu;
238 asn_dec_rval_t dec_ret;
Harald Welteee77cff2015-08-30 16:57:53 +0200239 int rc;
240
241 /* decode and handle to _hnbgw_hnbap_rx() */
242
Harald Welte2204f9d2015-09-07 21:10:50 +0200243 memset(pdu, 0, sizeof(*pdu));
Harald Welte27f9c4a2015-08-30 22:47:18 +0200244 dec_ret = aper_decode(NULL, &asn_DEF_HNBAP_PDU, (void **) &pdu,
245 msg->data, msgb_length(msg), 0, 0);
246 if (dec_ret.code != RC_OK) {
247 LOGP(DMAIN, LOGL_ERROR, "Error in ASN.1 decode\n");
Harald Welteee77cff2015-08-30 16:57:53 +0200248 return rc;
249 }
250
251 rc = _hnbgw_hnbap_rx(hnb, pdu);
Harald Welteee77cff2015-08-30 16:57:53 +0200252
253 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200254}
255
256
257int hnbgw_hnbap_init(void)
258{
259
260}