blob: 25bc272815b40c95177d91249a26415a0a257dac [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 Welteba43de42015-08-29 20:33:16 +020073
Harald Welte2204f9d2015-09-07 21:10:50 +020074 memset(&accept_out, 0, sizeof(accept_out));
Harald Welte27f9c4a2015-08-30 22:47:18 +020075 rc = hnbap_encode_ueregisteraccepties(&accept_out, &accept);
76 if (rc < 0) {
77 return rc;
Harald Welteba43de42015-08-29 20:33:16 +020078 }
Harald Welte27f9c4a2015-08-30 22:47:18 +020079
80 msg = hnbap_generate_successful_outcome(ProcedureCode_id_UERegister,
81 Criticality_reject,
82 &asn_DEF_UERegisterAccept,
83 &accept_out);
84 return hnbgw_hnbap_tx(ue->hnb, msg);
Harald Welteba43de42015-08-29 20:33:16 +020085}
86
Harald Welte27f9c4a2015-08-30 22:47:18 +020087static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, ANY_t *in)
Harald Welteba43de42015-08-29 20:33:16 +020088{
Harald Welte27f9c4a2015-08-30 22:47:18 +020089 HNBRegisterRequestIEs_t ies;
90 int rc;
Harald Welteba43de42015-08-29 20:33:16 +020091
Harald Welte27f9c4a2015-08-30 22:47:18 +020092 rc = hnbap_decode_hnbregisterrequesties(&ies, in);
93 if (rc < 0)
94 return rc;
Harald Welteba43de42015-08-29 20:33:16 +020095
Harald Weltea2e6a7a2015-08-29 21:47:39 +020096 /* copy all identity parameters from the message to ctx */
Harald Welte27f9c4a2015-08-30 22:47:18 +020097 asn1_strncpy(ctx->identity_info, &ies.hnB_Identity.hNB_Identity_Info,
98 sizeof(ctx->identity_info));
99 ctx->id.lac = asn1str_to_u16(&ies.lac);
100 ctx->id.sac = asn1str_to_u16(&ies.sac);
101 ctx->id.rac = asn1str_to_u8(&ies.rac);
102 ctx->id.cid = asn1bitstr_to_u32(&ies.cellIdentity);
Harald Welteb3dae302015-08-30 12:20:09 +0200103 //ctx->id.mcc FIXME
104 //ctx->id.mnc FIXME
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200105
Harald Welteee77cff2015-08-30 16:57:53 +0200106 DEBUGP(DMAIN, "HNB-REGISTER-REQ from %s\n", ctx->identity_info);
107
Harald Welte27f9c4a2015-08-30 22:47:18 +0200108 /* Send HNBRegisterAccept */
109 return hnbgw_tx_hnb_register_acc(ctx);
Harald Welteba43de42015-08-29 20:33:16 +0200110}
111
Harald Welte27f9c4a2015-08-30 22:47:18 +0200112static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, ANY_t *in)
Harald Welteba43de42015-08-29 20:33:16 +0200113{
Harald Welte27f9c4a2015-08-30 22:47:18 +0200114 UERegisterRequestIEs_t ies;
115 struct ue_context *ue;
Harald Welte10dfc5a2015-09-11 01:34:45 +0200116 char imsi[16];
Harald Welte27f9c4a2015-08-30 22:47:18 +0200117 int rc;
Harald Welteba43de42015-08-29 20:33:16 +0200118
Harald Welte27f9c4a2015-08-30 22:47:18 +0200119 rc = hnbap_decode_ueregisterrequesties(&ies, in);
120 if (rc < 0)
121 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200122
Harald Welte10dfc5a2015-09-11 01:34:45 +0200123 switch (ies.uE_Identity.present) {
124 case UE_Identity_PR_iMSI:
125 decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSI.buf,
126 ies.uE_Identity.choice.iMSI.size);
127 break;
128 case UE_Identity_PR_iMSIDS41:
129 decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIDS41.buf,
130 ies.uE_Identity.choice.iMSIDS41.size);
131 break;
132 case UE_Identity_PR_iMSIESN:
133 decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIESN.iMSIDS41.buf,
134 ies.uE_Identity.choice.iMSIESN.iMSIDS41.size);
135 break;
136 default:
Harald Welte1d2c39d2015-09-11 17:49:37 +0200137 LOGP(DMAIN, LOGL_NOTICE, "UE-REGISTER-REQ without IMSI?!?\n");
Harald Welte10dfc5a2015-09-11 01:34:45 +0200138 return -1;
139 }
Harald Welteb534e5c2015-09-11 00:15:16 +0200140
Harald Welte10dfc5a2015-09-11 01:34:45 +0200141 DEBUGP(DMAIN, "UE-REGSITER-REQ ID_type=%d imsi=%s cause=%ld\n",
142 ies.uE_Identity.present, imsi, ies.registration_Cause);
143
144 ue = ue_context_by_imsi(imsi);
145 if (!ue)
146 ue = ue_context_alloc(ctx, imsi);
Harald Welte27f9c4a2015-08-30 22:47:18 +0200147
Harald Welte27f9c4a2015-08-30 22:47:18 +0200148 /* Send UERegisterAccept */
149 return hnbgw_tx_ue_register_acc(ue);
Harald Welteba43de42015-08-29 20:33:16 +0200150}
151
Harald Welte3af1db82015-09-11 17:03:16 +0200152static int hnbgw_rx_err_ind(struct hnb_context *hnb, ANY_t *in)
153{
154 ErrorIndicationIEs_t ies;
155 int rc;
156
Harald Welte1d2c39d2015-09-11 17:49:37 +0200157 rc = hnbap_decode_errorindicationies(&ies, in);
Harald Welte3af1db82015-09-11 17:03:16 +0200158 if (rc < 0)
159 return rc;
160
161 LOGP(DMAIN, LOGL_NOTICE, "HNBAP ERROR.ind, cause: %s\n",
162 hnbap_cause_str(&ies.cause));
163
164 return 0;
165}
166
Harald Welte27f9c4a2015-08-30 22:47:18 +0200167static int hnbgw_rx_initiating_msg(struct hnb_context *hnb, InitiatingMessage_t *imsg)
Harald Welteba43de42015-08-29 20:33:16 +0200168{
169 int rc;
170
Harald Welteb3dae302015-08-30 12:20:09 +0200171 switch (imsg->procedureCode) {
Harald Welte27f9c4a2015-08-30 22:47:18 +0200172 case ProcedureCode_id_HNBRegister: /* 8.2 */
173 rc = hnbgw_rx_hnb_register_req(hnb, &imsg->value);
Harald Welteba43de42015-08-29 20:33:16 +0200174 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200175 case ProcedureCode_id_HNBDe_Register: /* 8.3 */
Harald Welteba43de42015-08-29 20:33:16 +0200176 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200177 case ProcedureCode_id_UERegister: /* 8.4 */
178 rc = hnbgw_rx_ue_register_req(hnb, &imsg->value);
Harald Welteba43de42015-08-29 20:33:16 +0200179 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200180 case ProcedureCode_id_UEDe_Register: /* 8.5 */
Harald Welteba43de42015-08-29 20:33:16 +0200181 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200182 case ProcedureCode_id_ErrorIndication: /* 8.6 */
Harald Welte3af1db82015-09-11 17:03:16 +0200183 rc = hnbgw_rx_err_ind(hnb, &imsg->value);
184 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200185 case ProcedureCode_id_TNLUpdate: /* 8.9 */
186 case ProcedureCode_id_HNBConfigTransfer: /* 8.10 */
187 case ProcedureCode_id_RelocationComplete: /* 8.11 */
188 case ProcedureCode_id_U_RNTIQuery: /* 8.12 */
189 case ProcedureCode_id_privateMessage:
Harald Welte1d2c39d2015-09-11 17:49:37 +0200190 LOGP(DMAIN, LOGL_NOTICE, "Unimplemented HNBAP Procedure %ld\n",
Harald Welte3af1db82015-09-11 17:03:16 +0200191 imsg->procedureCode);
Harald Welteba43de42015-08-29 20:33:16 +0200192 break;
193 default:
Harald Welte1d2c39d2015-09-11 17:49:37 +0200194 LOGP(DMAIN, LOGL_NOTICE, "Unknown HNBAP Procedure %ld\n",
Harald Welte3af1db82015-09-11 17:03:16 +0200195 imsg->procedureCode);
Harald Welteba43de42015-08-29 20:33:16 +0200196 break;
197 }
198}
199
Harald Welte27f9c4a2015-08-30 22:47:18 +0200200static int hnbgw_rx_successful_outcome_msg(struct hnb_context *hnb, SuccessfulOutcome_t *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200201{
202
203}
204
Harald Welte27f9c4a2015-08-30 22:47:18 +0200205static int hnbgw_rx_unsuccessful_outcome_msg(struct hnb_context *hnb, UnsuccessfulOutcome_t *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200206{
207
208}
209
210
Harald Welte27f9c4a2015-08-30 22:47:18 +0200211static int _hnbgw_hnbap_rx(struct hnb_context *hnb, HNBAP_PDU_t *pdu)
Harald Welteba43de42015-08-29 20:33:16 +0200212{
Harald Welteb3dae302015-08-30 12:20:09 +0200213 int rc;
214
Harald Welteba43de42015-08-29 20:33:16 +0200215 /* it's a bit odd that we can't dispatch on procedure code, but
216 * that's not possible */
Harald Welte27f9c4a2015-08-30 22:47:18 +0200217 switch (pdu->present) {
218 case HNBAP_PDU_PR_initiatingMessage:
219 rc = hnbgw_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage);
Harald Welteba43de42015-08-29 20:33:16 +0200220 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200221 case HNBAP_PDU_PR_successfulOutcome:
222 rc = hnbgw_rx_successful_outcome_msg(hnb, &pdu->choice.successfulOutcome);
Harald Welteba43de42015-08-29 20:33:16 +0200223 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200224 case HNBAP_PDU_PR_unsuccessfulOutcome:
225 rc = hnbgw_rx_unsuccessful_outcome_msg(hnb, &pdu->choice.unsuccessfulOutcome);
Harald Welteba43de42015-08-29 20:33:16 +0200226 break;
227 default:
Harald Welte3af1db82015-09-11 17:03:16 +0200228 LOGP(DMAIN, LOGL_NOTICE, "Unknown HNBAP Presence %u\n",
229 pdu->present);
Harald Welteba43de42015-08-29 20:33:16 +0200230 return -1;
231 }
232}
233
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200234int hnbgw_hnbap_rx(struct hnb_context *hnb, struct msgb *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200235{
Harald Welte27f9c4a2015-08-30 22:47:18 +0200236 HNBAP_PDU_t _pdu, *pdu = &_pdu;
237 asn_dec_rval_t dec_ret;
Harald Welteee77cff2015-08-30 16:57:53 +0200238 int rc;
239
240 /* decode and handle to _hnbgw_hnbap_rx() */
241
Harald Welte2204f9d2015-09-07 21:10:50 +0200242 memset(pdu, 0, sizeof(*pdu));
Harald Welte27f9c4a2015-08-30 22:47:18 +0200243 dec_ret = aper_decode(NULL, &asn_DEF_HNBAP_PDU, (void **) &pdu,
244 msg->data, msgb_length(msg), 0, 0);
245 if (dec_ret.code != RC_OK) {
246 LOGP(DMAIN, LOGL_ERROR, "Error in ASN.1 decode\n");
Harald Welteee77cff2015-08-30 16:57:53 +0200247 return rc;
248 }
249
250 rc = _hnbgw_hnbap_rx(hnb, pdu);
Harald Welteee77cff2015-08-30 16:57:53 +0200251
252 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200253}
254
255
256int hnbgw_hnbap_init(void)
257{
258
259}