aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/iuh/hnbgw.h1
-rw-r--r--src/hnbgw_hnbap.c118
-rw-r--r--src/hnbgw_vty.c15
3 files changed, 130 insertions, 4 deletions
diff --git a/include/osmocom/iuh/hnbgw.h b/include/osmocom/iuh/hnbgw.h
index bee7fb6..dfe287c 100644
--- a/include/osmocom/iuh/hnbgw.h
+++ b/include/osmocom/iuh/hnbgw.h
@@ -117,6 +117,7 @@ struct hnb_gw {
* plane traffic from HNBs */
uint16_t iuh_cs_mux_port;
uint16_t rnc_id;
+ bool hnbap_allow_tmsi;
} config;
/*! SCTP listen socket for incoming connections */
struct osmo_stream_srv_link *iuh;
diff --git a/src/hnbgw_hnbap.c b/src/hnbgw_hnbap.c
index 78f4692..59150c9 100644
--- a/src/hnbgw_hnbap.c
+++ b/src/hnbgw_hnbap.c
@@ -244,6 +244,108 @@ static int hnbgw_tx_ue_register_rej_tmsi(struct hnb_context *hnb, UE_Identity_t
return hnbgw_hnbap_tx(hnb, msg);
}
+static int hnbgw_tx_ue_register_acc_tmsi(struct hnb_context *hnb, UE_Identity_t *ue_id)
+{
+ UERegisterAccept_t accept_out;
+ UERegisterAcceptIEs_t accept;
+ struct msgb *msg;
+ uint32_t ctx_id;
+ uint32_t tmsi = 0;
+ struct ue_context *ue;
+ int rc;
+
+ memset(&accept, 0, sizeof(accept));
+ accept.uE_Identity.present = ue_id->present;
+
+ switch (ue_id->present) {
+ case UE_Identity_PR_tMSILAI:
+ BIT_STRING_fromBuf(&accept.uE_Identity.choice.tMSILAI.tMSI,
+ ue_id->choice.tMSILAI.tMSI.buf,
+ ue_id->choice.tMSILAI.tMSI.size * 8
+ - ue_id->choice.tMSILAI.tMSI.bits_unused);
+ tmsi = *(uint32_t*)accept.uE_Identity.choice.tMSILAI.tMSI.buf;
+ OCTET_STRING_fromBuf(&accept.uE_Identity.choice.tMSILAI.lAI.pLMNID,
+ ue_id->choice.tMSILAI.lAI.pLMNID.buf,
+ ue_id->choice.tMSILAI.lAI.pLMNID.size);
+ OCTET_STRING_fromBuf(&accept.uE_Identity.choice.tMSILAI.lAI.lAC,
+ ue_id->choice.tMSILAI.lAI.lAC.buf,
+ ue_id->choice.tMSILAI.lAI.lAC.size);
+ break;
+
+ case UE_Identity_PR_pTMSIRAI:
+ BIT_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.pTMSI,
+ ue_id->choice.pTMSIRAI.pTMSI.buf,
+ ue_id->choice.pTMSIRAI.pTMSI.size * 8
+ - ue_id->choice.pTMSIRAI.pTMSI.bits_unused);
+ tmsi = *(uint32_t*)accept.uE_Identity.choice.pTMSIRAI.pTMSI.buf;
+ OCTET_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.pLMNID,
+ ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.buf,
+ ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.size);
+ OCTET_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.lAC,
+ ue_id->choice.pTMSIRAI.rAI.lAI.lAC.buf,
+ ue_id->choice.pTMSIRAI.rAI.lAI.lAC.size);
+ OCTET_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.rAI.rAC,
+ ue_id->choice.pTMSIRAI.rAI.rAC.buf,
+ ue_id->choice.pTMSIRAI.rAI.rAC.size);
+ break;
+
+ default:
+ LOGP(DHNBAP, LOGL_ERROR, "Unsupportedccept UE ID (present=%d)\n",
+ ue_id->present);
+ return -1;
+ }
+
+ tmsi = ntohl(tmsi);
+ LOGP(DHNBAP, LOGL_DEBUG, "HNBAP register with TMSI %x\n",
+ tmsi);
+
+ ue = ue_context_by_tmsi(hnb->gw, tmsi);
+ if (!ue)
+ ue = ue_context_alloc(hnb, NULL, tmsi);
+
+ asn1_u24_to_bitstring(&accept.context_ID, &ctx_id, ue->context_id);
+
+ memset(&accept_out, 0, sizeof(accept_out));
+ rc = hnbap_encode_ueregisteraccepties(&accept_out, &accept);
+ if (rc < 0)
+ return rc;
+
+ msg = hnbap_generate_successful_outcome(ProcedureCode_id_UERegister,
+ Criticality_reject,
+ &asn_DEF_UERegisterAccept,
+ &accept_out);
+
+ switch (ue_id->present) {
+ case UE_Identity_PR_tMSILAI:
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_BIT_STRING,
+ &accept.uE_Identity.choice.tMSILAI.tMSI);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
+ &accept.uE_Identity.choice.tMSILAI.lAI.pLMNID);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
+ &accept.uE_Identity.choice.tMSILAI.lAI.lAC);
+ break;
+
+ case UE_Identity_PR_pTMSIRAI:
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_BIT_STRING,
+ &accept.uE_Identity.choice.pTMSIRAI.pTMSI);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
+ &accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.pLMNID);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
+ &accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.lAC);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING,
+ &accept.uE_Identity.choice.pTMSIRAI.rAI.rAC);
+ break;
+
+ default:
+ /* should never happen after above switch() */
+ break;
+ }
+
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_UERegisterAccept, &accept_out);
+
+ return hnbgw_hnbap_tx(hnb, msg);
+}
+
static int hnbgw_rx_hnb_deregister(struct hnb_context *ctx, ANY_t *in)
{
HNBDe_RegisterIEs_t ies;
@@ -313,11 +415,19 @@ static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, ANY_t *in)
ranap_bcd_decode(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIESN.iMSIDS41.buf,
ies.uE_Identity.choice.iMSIESN.iMSIDS41.size);
break;
+ case UE_Identity_PR_tMSILAI:
+ case UE_Identity_PR_pTMSIRAI:
+ if (ctx->gw->config.hnbap_allow_tmsi)
+ rc = hnbgw_tx_ue_register_acc_tmsi(ctx, &ies.uE_Identity);
+ else
+ rc = hnbgw_tx_ue_register_rej_tmsi(ctx, &ies.uE_Identity);
+ /* all has been handled by TMSI, skip the IMSI code below */
+ hnbap_free_ueregisterrequesties(&ies);
+ return rc;
default:
- LOGP(DHNBAP, LOGL_NOTICE, "UE-REGISTER-REQ without IMSI\n");
- /* TODO: this is probably a TMSI registration. Store TMSIs
- * and look them up to accept UE Registration. */
- rc = hnbgw_tx_ue_register_rej_tmsi(ctx, &ies.uE_Identity);
+ LOGP(DHNBAP, LOGL_NOTICE,
+ "UE-REGISTER-REQ with unsupported UE Id type %d\n",
+ ies.uE_Identity.present);
hnbap_free_ueregisterrequesties(&ies);
return rc;
}
diff --git a/src/hnbgw_vty.c b/src/hnbgw_vty.c
index 2e3d1e9..d6fad64 100644
--- a/src/hnbgw_vty.c
+++ b/src/hnbgw_vty.c
@@ -114,6 +114,16 @@ DEFUN(cfg_hnbgw_iuh_bind, cfg_hnbgw_iuh_bind_cmd, "bind A.B.C.D",
return CMD_SUCCESS;
}
+DEFUN(cfg_hnbgw_iuh_hnbap_allow_tmsi, cfg_hnbgw_iuh_hnbap_allow_tmsi_cmd,
+ "hnbap-allow-tmsi (0|1)",
+ "Allow HNBAP UE Register messages with TMSI or PTMSI identity\n"
+ "Only accept IMSI identity, reject TMSI or PTMSI\n"
+ "Accept IMSI, TMSI or PTMSI as UE identity\n")
+{
+ g_hnb_gw->config.hnbap_allow_tmsi = (*argv[0] == '1');
+ return CMD_SUCCESS;
+}
+
static int config_write_hnbgw(struct vty *vty)
{
vty_out(vty, "hnbgw%s", VTY_NEWLINE);
@@ -130,6 +140,9 @@ static int config_write_hnbgw_iuh(struct vty *vty)
if (addr && (strcmp(addr, HNBGW_IUH_BIND_ADDR_DEFAULT) != 0))
vty_out(vty, " bind %s%s", addr, VTY_NEWLINE);
+ if (g_hnb_gw->config.hnbap_allow_tmsi)
+ vty_out(vty, " hnbap-allow-tmsi 1%s", VTY_NEWLINE);
+
return CMD_SUCCESS;
}
@@ -145,7 +158,9 @@ void hnbgw_vty_init(struct hnb_gw *gw, void *tall_ctx)
install_element(HNBGW_NODE, &cfg_hnbgw_iuh_cmd);
install_node(&iuh_node, config_write_hnbgw_iuh);
vty_install_default(IUH_NODE);
+
install_element(IUH_NODE, &cfg_hnbgw_iuh_bind_cmd);
+ install_element(IUH_NODE, &cfg_hnbgw_iuh_hnbap_allow_tmsi_cmd);
install_element_ve(&show_hnb_cmd);
install_element_ve(&show_ue_cmd);