From ae510dc4a743e981b40fc5e1fdb4c109f2425e27 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 3 Oct 2017 17:46:14 +0800 Subject: rate_ctr: Enforce counter (and ctr_group) names are valid identifiers As rate counters are automatically exposed on the CTRL interface, we need to make sure they don't contain special characters such as '.' which are not permitted/supported by CTRL. In order to be able to run old versions of osmocom programs with libosmocore versions after this commit, we introduce some special name mangling: Any '.' in the names are replaced with ':' during counter group registration, if valid identifiers can be obtained this way. Change-Id: Ifc6ac824f5dae9a848bb4a5d067c64a69eb40b56 --- src/rate_ctr.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) (limited to 'src/rate_ctr.c') diff --git a/src/rate_ctr.c b/src/rate_ctr.c index a04a7760..6de59a02 100644 --- a/src/rate_ctr.c +++ b/src/rate_ctr.c @@ -1,4 +1,4 @@ -/* (C) 2009-2010 by Harald Welte +/* (C) 2009-2017 by Harald Welte * * All Rights Reserved * @@ -55,6 +55,7 @@ * * \file rate_ctr.c */ +#include #include #include @@ -63,11 +64,117 @@ #include #include #include +#include static LLIST_HEAD(rate_ctr_groups); static void *tall_rate_ctr_ctx; + +static bool rate_ctrl_group_desc_validate(const struct rate_ctr_group_desc *desc, bool quiet) +{ + unsigned int i; + const struct rate_ctr_desc *ctr_desc = desc->ctr_desc; + + if (!desc) { + LOGP(DLGLOBAL, LOGL_ERROR, "NULL is not a valid counter group descriptor\n"); + return false; + } + + DEBUGP(DLGLOBAL, "validating counter group %p(%s) with %u counters\n", desc, + desc->group_name_prefix, desc->num_ctr); + + if (!osmo_identifier_valid(desc->group_name_prefix)) { + if (!quiet) + LOGP(DLGLOBAL, LOGL_ERROR, "'%s' is not a valid counter group identifier\n", + desc->group_name_prefix); + return false; + } + + for (i = 0; i < desc->num_ctr; i++) { + if (!osmo_identifier_valid(ctr_desc[i].name)) { + if (!quiet) + LOGP(DLGLOBAL, LOGL_ERROR, "'%s' is not a valid counter identifier\n", + ctr_desc[i].name); + return false; + } + } + + return true; +} + +/* return 'in' if it doesn't contaon any '.'; otherwise allocate a copy and + * replace all '.' with ':' */ +static char *mangle_identifier_ifneeded(const void *ctx, const char *in) +{ + char *out; + unsigned int i; + + if (!in) + return NULL; + + if (!strchr(in, '.')) + return (char *)in; + + out = talloc_strdup(ctx, in); + OSMO_ASSERT(out); + + for (i = 0; i < strlen(out); i++) { + if (out[i] == '.') + out[i] = ':'; + } + + return out; +} + +/* "mangle" a rate counter group descriptor, i.e. replace any '.' with ':' */ +static struct rate_ctr_group_desc * +rate_ctr_group_desc_mangle(void *ctx, const struct rate_ctr_group_desc *desc) +{ + struct rate_ctr_group_desc *desc_new = talloc_zero(ctx, struct rate_ctr_group_desc); + int i; + + OSMO_ASSERT(desc_new); + + /* mangle the name_prefix but copy/keep the rest */ + desc_new->group_name_prefix = mangle_identifier_ifneeded(desc_new, desc->group_name_prefix); + desc_new->group_description = desc->group_description; + desc_new->class_id = desc->class_id; + desc_new->num_ctr = desc->num_ctr; + desc_new->ctr_desc = talloc_array(desc_new, struct rate_ctr_desc, desc_new->num_ctr); + OSMO_ASSERT(desc_new->ctr_desc); + + for (i = 0; i < desc->num_ctr; i++) { + struct rate_ctr_desc *ctrd_new = (struct rate_ctr_desc *) desc_new->ctr_desc; + const struct rate_ctr_desc *ctrd = desc->ctr_desc; + + if (!ctrd[i].name) { + LOGP(DLGLOBAL, LOGL_ERROR, "counter group '%s'[%d] == NULL, aborting\n", + desc->group_name_prefix, i); + goto err_free; + } + + ctrd_new[i].name = mangle_identifier_ifneeded(desc_new->ctr_desc, ctrd[i].name); + ctrd_new[i].description = ctrd[i].description; + } + + if (!rate_ctrl_group_desc_validate(desc_new, false)) { + /* simple mangling of identifiers ('.' -> ':') was not sufficient to render a valid + * descriptor, we have to bail out */ + LOGP(DLGLOBAL, LOGL_ERROR, "counter group '%s' still invalid after mangling\n", + desc->group_name_prefix); + goto err_free; + } + + LOGP(DLGLOBAL, LOGL_INFO, "Needed to mangle ounter group '%s' names still using '.' as " + "separator, please consider updating the application\n", desc->group_name_prefix); + + return desc_new; +err_free: + talloc_free(desc_new); + return NULL; +} + /*! Allocate a new group of counters according to description * \param[in] ctx \ref talloc context * \param[in] desc Rate counter group description @@ -80,6 +187,15 @@ struct rate_ctr_group *rate_ctr_group_alloc(void *ctx, unsigned int size; struct rate_ctr_group *group; + /* attempt to mangle all '.' in identifiers to ':' for backwards compat */ + if (!rate_ctrl_group_desc_validate(desc, true)) { + /* don't use 'ctx' here as it would screw up memory leak debugging e.g. + * in osmo-msc */ + desc = rate_ctr_group_desc_mangle(NULL, desc); + if (!desc) + return NULL; + } + size = sizeof(struct rate_ctr_group) + desc->num_ctr * sizeof(struct rate_ctr); -- cgit v1.2.3