blob: 1915ad64501c5e9af745cc9b03f196c6b5129f68 [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"
10
Harald Welteba43de42015-08-29 20:33:16 +020011#include "hnbgw.h"
Harald Welte27f9c4a2015-08-30 22:47:18 +020012#include "hnbap_common.h"
13#include "hnbap_ies_defs.h"
Harald Welteba43de42015-08-29 20:33:16 +020014
Harald Welteee77cff2015-08-30 16:57:53 +020015#define IU_MSG_NUM_IES 32
16#define IU_MSG_NUM_EXT_IES 32
17
Harald Welte27f9c4a2015-08-30 22:47:18 +020018static int hnbgw_hnbap_tx(struct hnb_context *ctx, struct msgb *msg)
Harald Welteee77cff2015-08-30 16:57:53 +020019{
Harald Welte7b54e322015-09-07 22:41:45 +020020 if (!msg)
21 return -EINVAL;
22
Harald Welte3f712562015-09-07 21:53:25 +020023 msgb_ppid(msg) = IUH_PPI_HNBAP;
24 return osmo_wqueue_enqueue(&ctx->wqueue, msg);
Harald Welte27f9c4a2015-08-30 22:47:18 +020025}
Harald Welteee77cff2015-08-30 16:57:53 +020026
Harald Welte27f9c4a2015-08-30 22:47:18 +020027static int hnbgw_tx_hnb_register_acc(struct hnb_context *ctx)
28{
29 HNBRegisterAccept_t accept_out;
30 struct msgb *msg;
31 int rc;
32
33 /* Single required response IE: RNC-ID */
34 HNBRegisterAcceptIEs_t accept = {
35 .rnc_id = ctx->gw->config.rnc_id
36 };
37
38 /* encode the Information Elements */
Harald Welte2204f9d2015-09-07 21:10:50 +020039 memset(&accept_out, 0, sizeof(accept_out));
Harald Welte27f9c4a2015-08-30 22:47:18 +020040 rc = hnbap_encode_hnbregisteraccepties(&accept_out, &accept);
41 if (rc < 0) {
42 return rc;
Harald Welteee77cff2015-08-30 16:57:53 +020043 }
44
Harald Welte27f9c4a2015-08-30 22:47:18 +020045 /* generate a successfull outcome PDU */
46 msg = hnbap_generate_successful_outcome(ProcedureCode_id_HNBRegister,
47 Criticality_reject,
48 &asn_DEF_HNBRegisterAccept,
49 &accept_out);
Harald Welteee77cff2015-08-30 16:57:53 +020050
Harald Welte27f9c4a2015-08-30 22:47:18 +020051 return hnbgw_hnbap_tx(ctx, msg);
Harald Welteee77cff2015-08-30 16:57:53 +020052}
53
54
Harald Welte27f9c4a2015-08-30 22:47:18 +020055static int hnbgw_tx_ue_register_acc(struct ue_context *ue)
Harald Welteba43de42015-08-29 20:33:16 +020056{
Harald Welte27f9c4a2015-08-30 22:47:18 +020057 UERegisterAccept_t accept_out;
58 UERegisterAcceptIEs_t accept;
59 struct msgb *msg;
Harald Welte10dfc5a2015-09-11 01:34:45 +020060 uint8_t encoded_imsi[10];
61 size_t encoded_imsi_len;
Harald Welte27f9c4a2015-08-30 22:47:18 +020062 int rc;
Harald Welteba43de42015-08-29 20:33:16 +020063
Harald Welte10dfc5a2015-09-11 01:34:45 +020064 encoded_imsi_len = encode_iu_imsi(encoded_imsi, sizeof(encoded_imsi), ue->imsi);
65
Harald Welte2204f9d2015-09-07 21:10:50 +020066 memset(&accept, 0, sizeof(accept));
Harald Welte10dfc5a2015-09-11 01:34:45 +020067 accept.uE_Identity.present = UE_Identity_PR_iMSI;
68 OCTET_STRING_fromBuf(&accept.uE_Identity.choice.iMSI, (const char *)encoded_imsi, encoded_imsi_len);
Harald Welte27f9c4a2015-08-30 22:47:18 +020069 asn1_u32_to_bitstring(&accept.context_ID, &ue->context_id);
Harald Welteba43de42015-08-29 20:33:16 +020070
Harald Welte2204f9d2015-09-07 21:10:50 +020071 memset(&accept_out, 0, sizeof(accept_out));
Harald Welte27f9c4a2015-08-30 22:47:18 +020072 rc = hnbap_encode_ueregisteraccepties(&accept_out, &accept);
73 if (rc < 0) {
74 return rc;
Harald Welteba43de42015-08-29 20:33:16 +020075 }
Harald Welte27f9c4a2015-08-30 22:47:18 +020076
77 msg = hnbap_generate_successful_outcome(ProcedureCode_id_UERegister,
78 Criticality_reject,
79 &asn_DEF_UERegisterAccept,
80 &accept_out);
81 return hnbgw_hnbap_tx(ue->hnb, msg);
Harald Welteba43de42015-08-29 20:33:16 +020082}
83
Harald Welte27f9c4a2015-08-30 22:47:18 +020084static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, ANY_t *in)
Harald Welteba43de42015-08-29 20:33:16 +020085{
Harald Welte27f9c4a2015-08-30 22:47:18 +020086 HNBRegisterRequestIEs_t ies;
87 int rc;
Harald Welteba43de42015-08-29 20:33:16 +020088
Harald Welte27f9c4a2015-08-30 22:47:18 +020089 rc = hnbap_decode_hnbregisterrequesties(&ies, in);
90 if (rc < 0)
91 return rc;
Harald Welteba43de42015-08-29 20:33:16 +020092
Harald Weltea2e6a7a2015-08-29 21:47:39 +020093 /* copy all identity parameters from the message to ctx */
Harald Welte27f9c4a2015-08-30 22:47:18 +020094 asn1_strncpy(ctx->identity_info, &ies.hnB_Identity.hNB_Identity_Info,
95 sizeof(ctx->identity_info));
96 ctx->id.lac = asn1str_to_u16(&ies.lac);
97 ctx->id.sac = asn1str_to_u16(&ies.sac);
98 ctx->id.rac = asn1str_to_u8(&ies.rac);
99 ctx->id.cid = asn1bitstr_to_u32(&ies.cellIdentity);
Harald Welteb3dae302015-08-30 12:20:09 +0200100 //ctx->id.mcc FIXME
101 //ctx->id.mnc FIXME
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200102
Harald Welteee77cff2015-08-30 16:57:53 +0200103 DEBUGP(DMAIN, "HNB-REGISTER-REQ from %s\n", ctx->identity_info);
104
Harald Welte27f9c4a2015-08-30 22:47:18 +0200105 /* Send HNBRegisterAccept */
106 return hnbgw_tx_hnb_register_acc(ctx);
Harald Welteba43de42015-08-29 20:33:16 +0200107}
108
Harald Welte27f9c4a2015-08-30 22:47:18 +0200109static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, ANY_t *in)
Harald Welteba43de42015-08-29 20:33:16 +0200110{
Harald Welte27f9c4a2015-08-30 22:47:18 +0200111 UERegisterRequestIEs_t ies;
112 struct ue_context *ue;
Harald Welte10dfc5a2015-09-11 01:34:45 +0200113 char imsi[16];
Harald Welte27f9c4a2015-08-30 22:47:18 +0200114 int rc;
Harald Welteba43de42015-08-29 20:33:16 +0200115
Harald Welte27f9c4a2015-08-30 22:47:18 +0200116 rc = hnbap_decode_ueregisterrequesties(&ies, in);
117 if (rc < 0)
118 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200119
Harald Welte10dfc5a2015-09-11 01:34:45 +0200120 switch (ies.uE_Identity.present) {
121 case UE_Identity_PR_iMSI:
122 decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSI.buf,
123 ies.uE_Identity.choice.iMSI.size);
124 break;
125 case UE_Identity_PR_iMSIDS41:
126 decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIDS41.buf,
127 ies.uE_Identity.choice.iMSIDS41.size);
128 break;
129 case UE_Identity_PR_iMSIESN:
130 decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIESN.iMSIDS41.buf,
131 ies.uE_Identity.choice.iMSIESN.iMSIDS41.size);
132 break;
133 default:
134 DEBUGP(DMAIN, "UE-REGISTER-REQ without IMSI?!?\n");
135 return -1;
136 }
Harald Welteb534e5c2015-09-11 00:15:16 +0200137
Harald Welte10dfc5a2015-09-11 01:34:45 +0200138 DEBUGP(DMAIN, "UE-REGSITER-REQ ID_type=%d imsi=%s cause=%ld\n",
139 ies.uE_Identity.present, imsi, ies.registration_Cause);
140
141 ue = ue_context_by_imsi(imsi);
142 if (!ue)
143 ue = ue_context_alloc(ctx, imsi);
Harald Welte27f9c4a2015-08-30 22:47:18 +0200144
Harald Welte27f9c4a2015-08-30 22:47:18 +0200145 /* Send UERegisterAccept */
146 return hnbgw_tx_ue_register_acc(ue);
Harald Welteba43de42015-08-29 20:33:16 +0200147}
148
Harald Welte3af1db82015-09-11 17:03:16 +0200149static int hnbgw_rx_err_ind(struct hnb_context *hnb, ANY_t *in)
150{
151 ErrorIndicationIEs_t ies;
152 int rc;
153
154 rc = hnbap_decode_hnbregisterrequesties(&ies, in);
155 if (rc < 0)
156 return rc;
157
158 LOGP(DMAIN, LOGL_NOTICE, "HNBAP ERROR.ind, cause: %s\n",
159 hnbap_cause_str(&ies.cause));
160
161 return 0;
162}
163
Harald Welte27f9c4a2015-08-30 22:47:18 +0200164static int hnbgw_rx_initiating_msg(struct hnb_context *hnb, InitiatingMessage_t *imsg)
Harald Welteba43de42015-08-29 20:33:16 +0200165{
166 int rc;
167
Harald Welteb3dae302015-08-30 12:20:09 +0200168 switch (imsg->procedureCode) {
Harald Welte27f9c4a2015-08-30 22:47:18 +0200169 case ProcedureCode_id_HNBRegister: /* 8.2 */
170 rc = hnbgw_rx_hnb_register_req(hnb, &imsg->value);
Harald Welteba43de42015-08-29 20:33:16 +0200171 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200172 case ProcedureCode_id_HNBDe_Register: /* 8.3 */
Harald Welteba43de42015-08-29 20:33:16 +0200173 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200174 case ProcedureCode_id_UERegister: /* 8.4 */
175 rc = hnbgw_rx_ue_register_req(hnb, &imsg->value);
Harald Welteba43de42015-08-29 20:33:16 +0200176 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200177 case ProcedureCode_id_UEDe_Register: /* 8.5 */
Harald Welteba43de42015-08-29 20:33:16 +0200178 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200179 case ProcedureCode_id_ErrorIndication: /* 8.6 */
Harald Welte3af1db82015-09-11 17:03:16 +0200180 rc = hnbgw_rx_err_ind(hnb, &imsg->value);
181 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200182 case ProcedureCode_id_TNLUpdate: /* 8.9 */
183 case ProcedureCode_id_HNBConfigTransfer: /* 8.10 */
184 case ProcedureCode_id_RelocationComplete: /* 8.11 */
185 case ProcedureCode_id_U_RNTIQuery: /* 8.12 */
186 case ProcedureCode_id_privateMessage:
Harald Welte3af1db82015-09-11 17:03:16 +0200187 LOGP(DMAIN, LOGL_NOTICE, "Unimplemented HNBAP Procedure %u\n",
188 imsg->procedureCode);
Harald Welteba43de42015-08-29 20:33:16 +0200189 break;
190 default:
Harald Welte3af1db82015-09-11 17:03:16 +0200191 LOGP(DMAIN, LOGL_NOTICE, "Unknown HNBAP Procedure %u\n",
192 imsg->procedureCode);
Harald Welteba43de42015-08-29 20:33:16 +0200193 break;
194 }
195}
196
Harald Welte27f9c4a2015-08-30 22:47:18 +0200197static int hnbgw_rx_successful_outcome_msg(struct hnb_context *hnb, SuccessfulOutcome_t *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200198{
199
200}
201
Harald Welte27f9c4a2015-08-30 22:47:18 +0200202static int hnbgw_rx_unsuccessful_outcome_msg(struct hnb_context *hnb, UnsuccessfulOutcome_t *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200203{
204
205}
206
207
Harald Welte27f9c4a2015-08-30 22:47:18 +0200208static int _hnbgw_hnbap_rx(struct hnb_context *hnb, HNBAP_PDU_t *pdu)
Harald Welteba43de42015-08-29 20:33:16 +0200209{
Harald Welteb3dae302015-08-30 12:20:09 +0200210 int rc;
211
Harald Welteba43de42015-08-29 20:33:16 +0200212 /* it's a bit odd that we can't dispatch on procedure code, but
213 * that's not possible */
Harald Welte27f9c4a2015-08-30 22:47:18 +0200214 switch (pdu->present) {
215 case HNBAP_PDU_PR_initiatingMessage:
216 rc = hnbgw_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage);
Harald Welteba43de42015-08-29 20:33:16 +0200217 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200218 case HNBAP_PDU_PR_successfulOutcome:
219 rc = hnbgw_rx_successful_outcome_msg(hnb, &pdu->choice.successfulOutcome);
Harald Welteba43de42015-08-29 20:33:16 +0200220 break;
Harald Welte27f9c4a2015-08-30 22:47:18 +0200221 case HNBAP_PDU_PR_unsuccessfulOutcome:
222 rc = hnbgw_rx_unsuccessful_outcome_msg(hnb, &pdu->choice.unsuccessfulOutcome);
Harald Welteba43de42015-08-29 20:33:16 +0200223 break;
224 default:
Harald Welte3af1db82015-09-11 17:03:16 +0200225 LOGP(DMAIN, LOGL_NOTICE, "Unknown HNBAP Presence %u\n",
226 pdu->present);
Harald Welteba43de42015-08-29 20:33:16 +0200227 return -1;
228 }
229}
230
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200231int hnbgw_hnbap_rx(struct hnb_context *hnb, struct msgb *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200232{
Harald Welte27f9c4a2015-08-30 22:47:18 +0200233 HNBAP_PDU_t _pdu, *pdu = &_pdu;
234 asn_dec_rval_t dec_ret;
Harald Welteee77cff2015-08-30 16:57:53 +0200235 int rc;
236
237 /* decode and handle to _hnbgw_hnbap_rx() */
238
Harald Welte2204f9d2015-09-07 21:10:50 +0200239 memset(pdu, 0, sizeof(*pdu));
Harald Welte27f9c4a2015-08-30 22:47:18 +0200240 dec_ret = aper_decode(NULL, &asn_DEF_HNBAP_PDU, (void **) &pdu,
241 msg->data, msgb_length(msg), 0, 0);
242 if (dec_ret.code != RC_OK) {
243 LOGP(DMAIN, LOGL_ERROR, "Error in ASN.1 decode\n");
Harald Welteee77cff2015-08-30 16:57:53 +0200244 return rc;
245 }
246
247 rc = _hnbgw_hnbap_rx(hnb, pdu);
Harald Welteee77cff2015-08-30 16:57:53 +0200248
249 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200250}
251
252
253int hnbgw_hnbap_init(void)
254{
255
256}