laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/36081?usp=email )
Change subject: Introduce concept of per-HNB persistent data structure ......................................................................
Introduce concept of per-HNB persistent data structure
This allows us to add a new "hnb-policy closed", which means we do not accept any random HNB connection anymore, but only those whose identity is pre-configured explicitly using administrative means.
Furthermore, this new data structure will allow us (in future patches) to keep persistent data like uptime / downtime of each HNB.
Related: SYS#6773 Change-Id: Ife89a7a206836bd89334d19d3cf8c92969dd74de --- M include/osmocom/hnbgw/hnbgw.h M include/osmocom/hnbgw/vty.h M src/osmo-hnbgw/hnbgw.c M src/osmo-hnbgw/hnbgw_hnbap.c M src/osmo-hnbgw/hnbgw_rua.c M src/osmo-hnbgw/hnbgw_vty.c 6 files changed, 167 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/81/36081/1
diff --git a/include/osmocom/hnbgw/hnbgw.h b/include/osmocom/hnbgw/hnbgw.h index f4f7dc1..59bb96b 100644 --- a/include/osmocom/hnbgw/hnbgw.h +++ b/include/osmocom/hnbgw/hnbgw.h @@ -233,6 +233,18 @@
/* linked list of hnbgw_context_map */ struct llist_head map_list; + + /*! pointer to the associated hnb persistent state */ + struct hnb_persistent *persistent; +}; + +/* persistent data for one HNB. This continues to exist even as conn / hnb_context is deleted on disconnect */ +struct hnb_persistent { + /*! Entry in HNBGW-global list of hnb_persistent */ + struct llist_head list; + + /*! copied from HNB-Identity-Info IE */ + char identity_info[256]; };
struct ue_context { @@ -259,6 +271,7 @@ bool hnbap_allow_tmsi; /*! print hnb-id (true) or MCC-MNC-LAC-RAC-SAC (false) in logs */ bool log_prefix_hnb_id; + bool accept_all_hnb; struct mgcp_client_conf *mgcp_client; struct { char *local_addr; @@ -275,6 +288,8 @@ struct osmo_stream_srv_link *iuh; /* list of struct hnb_context */ struct llist_head hnb_list; + /* list of struct hnb_persistent */ + struct llist_head hnb_persistent_list; /* list of struct ue_context */ struct llist_head ue_list; /* next availble UE Context ID */ @@ -323,6 +338,10 @@ void hnb_context_release(struct hnb_context *ctx); void hnb_context_release_ue_state(struct hnb_context *ctx);
+struct hnb_persistent *hnb_persistent_alloc(const char *identity); +struct hnb_persistent *hnb_persistent_find_by_identity(const char *identity); +void hnb_persistent_free(struct hnb_persistent *hnbp); + void hnbgw_vty_init(void); int hnbgw_vty_go_parent(struct vty *vty);
diff --git a/include/osmocom/hnbgw/vty.h b/include/osmocom/hnbgw/vty.h index da0c469..9134521 100644 --- a/include/osmocom/hnbgw/vty.h +++ b/include/osmocom/hnbgw/vty.h @@ -4,6 +4,7 @@
enum osmo_iuh_vty_node { HNBGW_NODE = _LAST_OSMOVTY_NODE + 1, + HNB_NODE, IUH_NODE, IUCS_NODE, IUPS_NODE, diff --git a/src/osmo-hnbgw/hnbgw.c b/src/osmo-hnbgw/hnbgw.c index 695822e..8a7626f 100644 --- a/src/osmo-hnbgw/hnbgw.c +++ b/src/osmo-hnbgw/hnbgw.c @@ -1,6 +1,6 @@ /* kitchen sink for OsmoHNBGW implementation */
-/* (C) 2015 by Harald Welte laforge@gnumonks.org +/* (C) 2015,2024 by Harald Welte laforge@gnumonks.org * (C) 2016-2023 by sysmocom s.f.m.c. GmbH info@sysmocom.de * All Rights Reserved * @@ -266,7 +266,40 @@ talloc_free(ctx); }
+/*********************************************************************** + * HNB Persistent Data + ***********************************************************************/
+struct hnb_persistent *hnb_persistent_alloc(const char *identity) +{ + struct hnb_persistent *hnbp = talloc_zero(g_hnbgw, struct hnb_persistent); + if (!hnbp) + return NULL; + + llist_add(&g_hnbgw->hnb_persistent_list, &hnbp->list); + OSMO_STRLCPY_ARRAY(hnbp->identity_info, identity); + + return hnbp; +} + +struct hnb_persistent *hnb_persistent_find_by_identity(const char *identity) +{ + struct hnb_persistent *hnbp; + + llist_for_each_entry(hnbp, &g_hnbgw->hnb_persistent_list, list) { + if (!strcmp(hnbp->identity_info, identity)) + return hnbp; + } + + return NULL; +} + +void hnb_persistent_free(struct hnb_persistent *hnbp) +{ + /* FIXME: check if in use? */ + llist_del(&hnbp->list); + talloc_free(hnbp); +}
/*********************************************************************** * SCTP Socket / stream handling @@ -585,6 +618,7 @@
g_hnbgw->next_ue_ctx_id = 23; INIT_LLIST_HEAD(&g_hnbgw->hnb_list); + INIT_LLIST_HEAD(&g_hnbgw->hnb_persistent_list); INIT_LLIST_HEAD(&g_hnbgw->ue_list); INIT_LLIST_HEAD(&g_hnbgw->sccp.users);
diff --git a/src/osmo-hnbgw/hnbgw_hnbap.c b/src/osmo-hnbgw/hnbgw_hnbap.c index 06d1a9d..f8c6bd6 100644 --- a/src/osmo-hnbgw/hnbgw_hnbap.c +++ b/src/osmo-hnbgw/hnbgw_hnbap.c @@ -404,21 +404,34 @@
static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, ANY_t *in) { + struct hnb_persistent *hnbp; struct hnb_context *hnb, *tmp; HNBAP_HNBRegisterRequestIEs_t ies; int rc; struct osmo_plmn_id plmn; struct osmo_fd *ofd = osmo_stream_srv_get_ofd(ctx->conn); + char identity_str[256];
rc = hnbap_decode_hnbregisterrequesties(&ies, in); if (rc < 0) { LOGHNB(ctx, DHNBAP, LOGL_ERROR, "Failure to decode HNB-REGISTER-REQ: rc=%d\n", rc); return rc; } + asn1_strncpy(identity_str, &ies.hnB_Identity.hNB_Identity_Info, sizeof(identity_str)); + + hnbp = hnb_persistent_find_by_identity(identity_str); + if (!hnbp && g_hnbgw->config.accept_all_hnb) + hnbp = hnb_persistent_alloc(identity_str); + + if (!hnbp) { + LOGHNB(ctx, DHNBAP, LOGL_NOTICE, "Rejecting unknonwn HNB with identity %s\n", identity_str); + hnbap_free_hnbregisterrequesties(&ies); + return hnbgw_tx_hnb_register_rej(ctx); + } + ctx->persistent = hnbp;
/* copy all identity parameters from the message to ctx */ - asn1_strncpy(ctx->identity_info, &ies.hnB_Identity.hNB_Identity_Info, - sizeof(ctx->identity_info)); + OSMO_STRLCPY_ARRAY(ctx->identity_info, identity_str); ctx->id.lac = asn1str_to_u16(&ies.lac); ctx->id.sac = asn1str_to_u16(&ies.sac); ctx->id.rac = asn1str_to_u8(&ies.rac); diff --git a/src/osmo-hnbgw/hnbgw_rua.c b/src/osmo-hnbgw/hnbgw_rua.c index d73f22d..76e3231 100644 --- a/src/osmo-hnbgw/hnbgw_rua.c +++ b/src/osmo-hnbgw/hnbgw_rua.c @@ -579,6 +579,10 @@ asn_dec_rval_t dec_ret; int rc;
+ /* RUA is only processed after HNB registration, and as soon as the HNB is registered, + * it should have a persistent config associated with it */ + OSMO_ASSERT(hnb->persistent); + /* decode and handle to _hnbgw_hnbap_rx() */
memset(pdu, 0, sizeof(*pdu)); diff --git a/src/osmo-hnbgw/hnbgw_vty.c b/src/osmo-hnbgw/hnbgw_vty.c index cb34d7f..59afd6c 100644 --- a/src/osmo-hnbgw/hnbgw_vty.c +++ b/src/osmo-hnbgw/hnbgw_vty.c @@ -1,6 +1,7 @@ /* HNB-GW interface to quagga VTY */
/* (C) 2016 by sysmocom s.f.m.c. GmbH info@sysmocom.de + * (C) 2024 by Harald Welte laforge@gnumonks.org * All Rights Reserved * * This program is free software; you can redistribute it and/or modify @@ -53,6 +54,12 @@ return CMD_SUCCESS; }
+static struct cmd_node hnb_node = { + HNB_NODE, + "%s(config-hnbgw-hnb)# ", + 1, +}; + static struct cmd_node iuh_node = { IUH_NODE, "%s(config-hnbgw-iuh)# ", @@ -355,6 +362,19 @@ return CMD_SUCCESS; }
+DEFUN(cfg_hnbgw_hnb_policy, cfg_hnbgw_hnb_policy_cmd, + "hnb-policy (accept-all|closed)", + "Configure the policy of which HNB connections to accept\n" + "Accept HNB of any identity\n" + "Accept only HNB whose identity is explicitly configured via VTY\n") +{ + if (!strcmp(argv[0], "accept-all")) + g_hnbgw->config.accept_all_hnb = true; + else + g_hnbgw->config.accept_all_hnb = false; + return CMD_SUCCESS; +} + DEFUN_DEPRECATED(cfg_hnbgw_max_sccp_cr_payload_len, cfg_hnbgw_max_sccp_cr_payload_len_cmd, "sccp cr max-payload-len <0-999999>", "Configure SCCP behavior\n" @@ -799,6 +819,43 @@ return CMD_SUCCESS; }
+#define HNB_STR "hNodeB specific configuration\n" + +DEFUN(cfg_hnbgw_hnb, cfg_hnbgw_hnb_cmd, + "hnb IDENTITY_INFO", + HNB_STR + "Identity of hNodeB\n") +{ + struct hnb_persistent *hnbp = hnb_persistent_find_by_identity(argv[0]); + if (!hnbp) + hnbp = hnb_persistent_alloc(argv[0]); + if (!hnbp) { + vty_out(vty, "%% Could not create HNB '%s'%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + vty->index = hnbp; + vty->node = HNB_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_hnbgw_no_hnb, cfg_hnbgw_no_hnb_cmd, + "no hnb IDENTITY_INFO", + NO_STR "Remve configuration for specified hNodeB\n" + "Identity of hNodeB\n") +{ + struct hnb_persistent *hnbp = hnb_persistent_find_by_identity(argv[0]); + + if (!hnbp) { + vty_out(vty, "%% Could not find any HNB for identity '%s'%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + hnb_persistent_free(hnbp); + return CMD_SUCCESS; +} + #if ENABLE_PFCP
static struct cmd_node pfcp_node = { @@ -889,8 +946,15 @@ cnpool_write_nri(vty, cnpool, false); }
+static void write_one_hnbp(struct vty *vty, const struct hnb_persistent *hnbp) +{ + vty_out(vty, " hnb %s%s", hnbp->identity_info, VTY_NEWLINE); +} + static int config_write_hnbgw(struct vty *vty) { + const struct hnb_persistent *hnbp; + vty_out(vty, "hnbgw%s", VTY_NEWLINE);
if (g_hnbgw->config.plmn.mcc) @@ -903,8 +967,15 @@
vty_out(vty, " log-prefix %s%s", g_hnbgw->config.log_prefix_hnb_id ? "hnb-id" : "umts-cell-id", VTY_NEWLINE); + + if (!g_hnbgw->config.accept_all_hnb) + vty_out(vty, " hnb-policy closed%s", VTY_NEWLINE); + osmo_tdef_vty_groups_write(vty, " ");
+ llist_for_each_entry(hnbp, &g_hnbgw->hnb_persistent_list, list) + write_one_hnbp(vty, hnbp); + _config_write_cnpool(vty, &g_hnbgw->sccp.cnpool_iucs); _config_write_cnpool(vty, &g_hnbgw->sccp.cnpool_iups);
@@ -1003,6 +1074,7 @@ install_element(HNBGW_NODE, &cfg_hnbgw_rnc_id_cmd); install_element(HNBGW_NODE, &cfg_hnbgw_log_prefix_cmd); install_element(HNBGW_NODE, &cfg_hnbgw_max_sccp_cr_payload_len_cmd); + install_element(HNBGW_NODE, &cfg_hnbgw_hnb_policy_cmd);
install_element(HNBGW_NODE, &cfg_hnbgw_iuh_cmd); install_node(&iuh_node, config_write_hnbgw_iuh); @@ -1027,6 +1099,10 @@ install_element(IUCS_NODE, &cfg_hnbgw_cnpool_remote_addr_cmd); install_element(IUPS_NODE, &cfg_hnbgw_cnpool_remote_addr_cmd);
+ install_element(HNBGW_NODE, &cfg_hnbgw_hnb_cmd); + install_element(HNBGW_NODE, &cfg_hnbgw_no_hnb_cmd); + install_node(&hnb_node, NULL); + install_element_ve(&show_cnlink_cmd); install_element_ve(&show_hnb_cmd); install_element_ve(&show_one_hnb_cmd);