aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2017-12-28 21:47:06 +0100
committerHarald Welte <laforge@gnumonks.org>2017-12-28 21:49:59 +0100
commit722a802c79fc40d17e42982412382034e62829ab (patch)
treec754e29b11e2a23420ba3d034490307de4733c18 /src
parent39773fd362669ab614c767f4d818200090d93233 (diff)
Reject any HNBAP-REGISTER messages for HNB's with identical CIDlaforge/reject-id-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
Diffstat (limited to 'src')
-rw-r--r--src/hnbgw.c11
-rw-r--r--src/hnbgw_hnbap.c70
2 files changed, 73 insertions, 8 deletions
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;
}