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
This commit is contained in:
Harald Welte 2017-12-28 21:47:06 +01:00
parent 39773fd362
commit 722a802c79
3 changed files with 74 additions and 8 deletions

View File

@ -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);

View File

@ -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)
{

View File

@ -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;
}