From 722a802c79fc40d17e42982412382034e62829ab Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 28 Dec 2017 21:47:06 +0100 Subject: Reject any HNBAP-REGISTER messages for HNB's with identical CID According to some references found in the nano3G MIB help, the CellID as reported in the HNB-REGISTER-REQ is combined from 16-bit CellID and the 12bit RNC-ID. The HNB-GW should use this value in the register-req to ensure it is unique in the network. We should probably reject register requests from non-unique / overlapping values. Change-Id: Ib58cc9f3c0e700f8bc5930f4df0d2dfe7888b991 Closes: OS#2789 --- include/osmocom/iuh/hnbgw.h | 1 + src/hnbgw.c | 11 +++++++ src/hnbgw_hnbap.c | 70 +++++++++++++++++++++++++++++++++++++++------ 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/include/osmocom/iuh/hnbgw.h b/include/osmocom/iuh/hnbgw.h index 58bdab4..8bbb821 100644 --- a/include/osmocom/iuh/hnbgw.h +++ b/include/osmocom/iuh/hnbgw.h @@ -151,6 +151,7 @@ void ue_context_free(struct ue_context *ue); struct hnb_context *hnb_context_alloc(struct hnb_gw *gw, struct osmo_stream_srv_link *link, int new_fd); void hnb_context_release(struct hnb_context *ctx); +struct hnb_context *hnb_context_find_by_cid(struct hnb_gw *gw, uint32_t cid); void hnbgw_vty_init(struct hnb_gw *gw, void *tall_ctx); int hnbgw_vty_go_parent(struct vty *vty); diff --git a/src/hnbgw.c b/src/hnbgw.c index 752fc0f..af490b5 100644 --- a/src/hnbgw.c +++ b/src/hnbgw.c @@ -283,6 +283,17 @@ void hnb_context_release(struct hnb_context *ctx) talloc_free(ctx); } +struct hnb_context *hnb_context_find_by_cid(struct hnb_gw *gw, uint32_t cid) +{ + struct hnb_context *ctx; + + llist_for_each_entry(ctx, &gw->hnb_list, list) { + if (ctx->id.cid == cid) + return ctx; + } + return NULL; +} + /*! call-back when the listen FD has something to read */ static int accept_cb(struct osmo_stream_srv_link *srv, int fd) { diff --git a/src/hnbgw_hnbap.c b/src/hnbgw_hnbap.c index 058a42a..063ba2a 100644 --- a/src/hnbgw_hnbap.c +++ b/src/hnbgw_hnbap.c @@ -77,6 +77,42 @@ static int hnbgw_tx_hnb_register_acc(struct hnb_context *ctx) return hnbgw_hnbap_tx(ctx, msg); } +static int hnbgw_tx_hnb_register_rej(struct hnb_context *ctx) +{ + HNBRegisterReject_t reject_out; + struct msgb *msg; + int rc; + + /* Single required response IE: Cause */ + HNBRegisterRejectIEs_t reject = { + .cause = { + .present = Cause_PR_radioNetwork, + .choice = { + .radioNetwork = CauseRadioNetwork_hNB_parameter_mismatch, + }, + }, + }; + + /* encode the Information Elements */ + memset(&reject_out, 0, sizeof(reject_out)); + rc = hnbap_encode_hnbregisterrejecties(&reject_out, &reject); + if (rc < 0) { + return rc; + } + + /* generate a successfull outcome PDU */ + msg = hnbap_generate_successful_outcome(ProcedureCode_id_HNBRegister, + Criticality_reject, + &asn_DEF_HNBRegisterReject, + &reject_out); + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBRegisterReject, &reject_out); + + return hnbgw_hnbap_tx(ctx, msg); +} + + + static int hnbgw_tx_ue_register_acc(struct ue_context *ue) { @@ -367,7 +403,8 @@ static int hnbgw_rx_hnb_deregister(struct hnb_context *ctx, ANY_t *in) static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, ANY_t *in) { HNBRegisterRequestIEs_t ies; - int rc; + uint16_t lac, sac, rac, mcc, mnc; + int cid, rc; rc = hnbap_decode_hnbregisterrequesties(&ies, in); if (rc < 0) @@ -376,17 +413,34 @@ static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, ANY_t *in) /* copy all identity parameters from the message to ctx */ asn1_strncpy(ctx->identity_info, &ies.hnB_Identity.hNB_Identity_Info, sizeof(ctx->identity_info)); - ctx->id.lac = asn1str_to_u16(&ies.lac); - ctx->id.sac = asn1str_to_u16(&ies.sac); - ctx->id.rac = asn1str_to_u8(&ies.rac); - ctx->id.cid = asn1bitstr_to_u28(&ies.cellIdentity); - gsm48_mcc_mnc_from_bcd(ies.plmNidentity.buf, &ctx->id.mcc, &ctx->id.mnc); + lac = asn1str_to_u16(&ies.lac); + sac = asn1str_to_u16(&ies.sac); + rac = asn1str_to_u8(&ies.rac); + cid = asn1bitstr_to_u28(&ies.cellIdentity); + gsm48_mcc_mnc_from_bcd(ies.plmNidentity.buf, &mcc, &mnc); + hnbap_free_hnbregisterrequesties(&ies); - DEBUGP(DHNBAP, "HNB-REGISTER-REQ from %s\n", ctx->identity_info); + DEBUGP(DHNBAP, "HNB-REGISTER-REQ (LAC=%u, SAC=%u, RAC=%u, CID=%u) from %s\n", + lac, sac, rac, cid, ctx->identity_info); + + if (hnb_context_find_by_cid(ctx->gw, cid)) { + LOGP(DHNBAP, LOGL_ERROR, "HNB-REGISTER-REQ from %s for already-existing " + "CID=%u, rejecting\n", ctx->identity_info, cid); + hnbgw_tx_hnb_register_rej(ctx); + hnb_context_release(ctx); + return 0; + } + + ctx->id.mcc = mcc; + ctx->id.mcc = mnc; + ctx->id.lac = lac; + ctx->id.sac = sac; + ctx->id.rac = rac; + ctx->id.cid = cid; /* Send HNBRegisterAccept */ rc = hnbgw_tx_hnb_register_acc(ctx); - hnbap_free_hnbregisterrequesties(&ies); + return rc; } -- cgit v1.2.3