diff --git a/configs/samples/geolocation.conf.sample b/configs/samples/geolocation.conf.sample
index 305f087fb2..5b0052f115 100644
--- a/configs/samples/geolocation.conf.sample
+++ b/configs/samples/geolocation.conf.sample
@@ -285,6 +285,13 @@ would have an empty element in it. If suppress_empty_ca_elements
were set to "yes", the FLR element would be dropped from the PIDF-LO
document altogether.
+-- format, location_info, location_source, method, confidence ---------
+You can specify the location object's format, location_info,
+method, location_source and confidence parameters directly on
+a profile object for simple scenarios where the location
+information isn't common with any other profiles. This is
+mutually exclusive with setting location_reference on the
+profile.
-- Profile Example ----------------------------------------------------
diff --git a/doc/CHANGES-staging/res_geolocation.txt b/doc/CHANGES-staging/res_geolocation.txt
index ddf855b22a..b543c6e29c 100644
--- a/doc/CHANGES-staging/res_geolocation.txt
+++ b/doc/CHANGES-staging/res_geolocation.txt
@@ -33,3 +33,10 @@ set.
Added profile parameter "suppress_empty_ca_elements" that
will cause Civic Address elements that are empty to be
suppressed from the outgoing PIDF-LO document.
+
+You can now specify the location object's format, location_info,
+method, location_source and confidence parameters directly on
+a profile object for simple scenarios where the location
+information isn't common with any other profiles. This is
+mutually exclusive with setting location_reference on the
+profile.
diff --git a/doc/appdocsxml.dtd b/doc/appdocsxml.dtd
index fbcad6ddfe..426d959466 100644
--- a/doc/appdocsxml.dtd
+++ b/doc/appdocsxml.dtd
@@ -69,10 +69,10 @@
-
+
-
+
diff --git a/include/asterisk/res_geolocation.h b/include/asterisk/res_geolocation.h
index 87f89a2cdd..378a6c736a 100644
--- a/include/asterisk/res_geolocation.h
+++ b/include/asterisk/res_geolocation.h
@@ -75,6 +75,8 @@ struct ast_geoloc_profile {
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(location_reference);
AST_STRING_FIELD(notes);
+ AST_STRING_FIELD(method);
+ AST_STRING_FIELD(location_source);
);
enum ast_geoloc_pidf_element pidf_element;
enum ast_geoloc_precedence precedence;
@@ -83,6 +85,9 @@ struct ast_geoloc_profile {
struct ast_variable *location_variables;
struct ast_variable *usage_rules;
int suppress_empty_ca_elements;
+ enum ast_geoloc_format format;
+ struct ast_variable *location_info;
+ struct ast_variable *confidence;
};
struct ast_geoloc_eprofile {
diff --git a/res/res_geolocation/geoloc_config.c b/res/res_geolocation/geoloc_config.c
index ee542f046b..dea7a22050 100644
--- a/res/res_geolocation/geoloc_config.c
+++ b/res/res_geolocation/geoloc_config.c
@@ -67,13 +67,17 @@ static void *geoloc_location_alloc(const char *name)
return location;
}
-
CONFIG_ENUM(profile, pidf_element)
CONFIG_ENUM(profile, precedence)
CONFIG_VAR_LIST(profile, location_refinement)
CONFIG_VAR_LIST(profile, location_variables)
CONFIG_VAR_LIST(profile, usage_rules)
+CONFIG_ENUM_HANDLER(profile, format)
+CONFIG_ENUM_TO_STR(profile, format)
+CONFIG_VAR_LIST(profile, location_info)
+CONFIG_VAR_LIST(profile, confidence)
+
static void geoloc_profile_destructor(void *obj) {
struct ast_geoloc_profile *profile = obj;
@@ -81,6 +85,8 @@ static void geoloc_profile_destructor(void *obj) {
ast_variables_destroy(profile->location_refinement);
ast_variables_destroy(profile->location_variables);
ast_variables_destroy(profile->usage_rules);
+ ast_variables_destroy(profile->location_info);
+ ast_variables_destroy(profile->confidence);
}
static void *geoloc_profile_alloc(const char *name)
@@ -94,60 +100,83 @@ static void *geoloc_profile_alloc(const char *name)
return profile;
}
-static int geoloc_location_apply_handler(const struct ast_sorcery *sorcery, void *obj)
+static enum ast_geoloc_validate_result validate_location_info(const char *id,
+ enum ast_geoloc_format format, struct ast_variable *location_info)
{
- struct ast_geoloc_location *location = obj;
- const char *location_id = ast_sorcery_object_get_id(location);
+ enum ast_geoloc_validate_result result;
const char *failed;
const char *uri;
- enum ast_geoloc_validate_result result;
- switch (location->format) {
+ switch (format) {
case AST_GEOLOC_FORMAT_NONE:
case AST_GEOLOC_FORMAT_LAST:
- ast_log(LOG_ERROR, "Location '%s' must have a format\n", location_id);
+ ast_log(LOG_ERROR, "Location '%s' must have a format\n", id);
return -1;
case AST_GEOLOC_FORMAT_CIVIC_ADDRESS:
- result = ast_geoloc_civicaddr_validate_varlist(location->location_info, &failed);
+ result = ast_geoloc_civicaddr_validate_varlist(location_info, &failed);
if (result != AST_GEOLOC_VALIDATE_SUCCESS) {
ast_log(LOG_ERROR, "Location '%s' has invalid item '%s' in the location\n",
- location_id, failed);
- return -1;
+ id, failed);
+ return result;
}
break;
case AST_GEOLOC_FORMAT_GML:
- result = ast_geoloc_gml_validate_varlist(location->location_info, &failed);
+ result = ast_geoloc_gml_validate_varlist(location_info, &failed);
if (result != AST_GEOLOC_VALIDATE_SUCCESS) {
ast_log(LOG_ERROR, "%s for item '%s' in location '%s'\n",
- ast_geoloc_validate_result_to_str(result), failed, location_id);
- return -1;
+ ast_geoloc_validate_result_to_str(result), failed, id);
+ return result;
}
break;
case AST_GEOLOC_FORMAT_URI:
- uri = ast_variable_find_in_list(location->location_info, "URI");
+ uri = ast_variable_find_in_list(location_info, "URI");
if (!uri) {
- struct ast_str *str = ast_variable_list_join(location->location_info, ",", "=", "\"", NULL);
+ struct ast_str *str = ast_variable_list_join(location_info, ",", "=", "\"", NULL);
ast_log(LOG_ERROR, "Geolocation location '%s' format is set to '%s' but no 'URI' was found in location parameter '%s'\n",
- location_id, format_names[AST_GEOLOC_FORMAT_URI], ast_str_buffer(str));
+ id, format_names[AST_GEOLOC_FORMAT_URI], ast_str_buffer(str));
ast_free(str);
- return -1;
+ return AST_GEOLOC_VALIDATE_NOT_ENOUGH_VARNAMES;
}
break;
}
- if (!ast_strlen_zero(location->location_source)) {
+ return AST_GEOLOC_VALIDATE_SUCCESS;
+}
+
+static int validate_location_source(const char *id, const char *location_source)
+{
+ if (!ast_strlen_zero(location_source)) {
struct ast_sockaddr loc_source_addr;
- int rc = ast_sockaddr_parse(&loc_source_addr, location->location_source, PARSE_PORT_FORBID);
+ int rc = ast_sockaddr_parse(&loc_source_addr, location_source, PARSE_PORT_FORBID);
if (rc == 1) {
ast_log(LOG_ERROR, "Geolocation location '%s' location_source '%s' must be a FQDN."
" RFC8787 expressly forbids IP addresses.\n",
- location_id, location->location_source);
+ id, location_source);
return -1;
}
}
+ return 0;
+}
+
+static int geoloc_location_apply_handler(const struct ast_sorcery *sorcery, void *obj)
+{
+ struct ast_geoloc_location *location = obj;
+ const char *location_id = ast_sorcery_object_get_id(location);
+ enum ast_geoloc_validate_result result;
+ int rc = 0;
+
+ result = validate_location_info(location_id, location->format, location->location_info);
+ if (result != AST_GEOLOC_VALIDATE_SUCCESS) {
+ return -1;
+ }
+
+ rc = validate_location_source(location_id, location->location_source);
+ if (rc != 0) {
+ return -1;
+ }
return 0;
}
@@ -156,48 +185,52 @@ static int geoloc_profile_apply_handler(const struct ast_sorcery *sorcery, void
{
struct ast_geoloc_profile *profile = obj;
struct ast_geoloc_location *location;
- const char *profile_id = ast_sorcery_object_get_id(profile);
- const char *failed;
+ const char *id = ast_sorcery_object_get_id(profile);
enum ast_geoloc_validate_result result;
+ enum ast_geoloc_format format;
+ int rc = 0;
- if (ast_strlen_zero(profile->location_reference)) {
- if (profile->location_refinement ||
- profile->location_variables) {
- ast_log(LOG_ERROR, "Profile '%s' can't have location_refinement or location_variables without a location_reference",
- profile_id);
+ if (!ast_strlen_zero(profile->location_reference)) {
+ if (profile->location_info ||
+ profile->format != AST_GEOLOC_FORMAT_NONE) {
+ ast_log(LOG_ERROR, "Profile '%s' can't have location_reference and location_info or format at the same time",
+ id);
return -1;
}
return 0;
}
- location = ast_sorcery_retrieve_by_id(geoloc_sorcery, "location", profile->location_reference);
- if (!location) {
- ast_log(LOG_ERROR, "Profile '%s' has a location_reference '%s' that doesn't exist",
- profile_id, profile->location_reference);
- return -1;
+ if (profile->location_info) {
+ result = validate_location_info(id, profile->format, profile->location_info);
+ if (result != AST_GEOLOC_VALIDATE_SUCCESS) {
+ return -1;
+ }
+
+ rc = validate_location_source(id, profile->location_source);
+ if (rc != 0) {
+ return -1;
+ }
+
+ return 0;
+ }
+
+ if (!ast_strlen_zero(profile->location_reference)) {
+ location = ast_sorcery_retrieve_by_id(geoloc_sorcery, "location", profile->location_reference);
+ if (!location) {
+ ast_log(LOG_ERROR, "Profile '%s' has a location_reference '%s' that doesn't exist",
+ id, profile->location_reference);
+ return -1;
+ }
+ format = location->format;
+ ao2_ref(location, -1);
}
if (profile->location_refinement) {
- switch (location->format) {
- case AST_GEOLOC_FORMAT_NONE:
- case AST_GEOLOC_FORMAT_LAST:
- break;
- case AST_GEOLOC_FORMAT_CIVIC_ADDRESS:
- result = ast_geoloc_civicaddr_validate_varlist(profile->location_refinement, &failed);
- if (result != AST_GEOLOC_VALIDATE_SUCCESS) {
- ast_log(LOG_ERROR, "Profile '%s' error: %s: for item '%s' in the location_refinement\n",
- profile_id, ast_geoloc_validate_result_to_str(result), failed);
- ao2_ref(location, -1);
- return -1;
- }
- break;
- case AST_GEOLOC_FORMAT_GML:
- break;
- case AST_GEOLOC_FORMAT_URI:
- break;
+ result = validate_location_info(id, format, profile->location_refinement);
+ if (result != AST_GEOLOC_VALIDATE_SUCCESS) {
+ return -1;
}
}
- ao2_ref(location, -1);
return 0;
}
@@ -217,7 +250,6 @@ static char *geoloc_config_list_locations(struct ast_cli_entry *e, int cmd, stru
int using_regex = 0;
char *result = CLI_SUCCESS;
int ret = 0;
- char *format_name;
int count = 0;
switch (cmd) {
@@ -285,14 +317,12 @@ static char *geoloc_config_list_locations(struct ast_cli_entry *e, int cmd, stru
break;
}
- format_to_str(loc, NULL, &format_name);
ast_cli(a->fd, "%-46.46s %-13s %-s\n",
ast_sorcery_object_get_id(loc),
- format_name,
+ format_names[loc->format],
ast_str_buffer(str));
ao2_unlock(loc);
ast_free(str);
- ast_free(format_name);
count++;
}
ao2_iterator_destroy(&iter);
@@ -311,7 +341,6 @@ static char *geoloc_config_list_profiles(struct ast_cli_entry *e, int cmd, struc
int using_regex = 0;
char *result = CLI_SUCCESS;
int ret = 0;
- char *precedence;
int count = 0;
switch (cmd) {
@@ -368,13 +397,11 @@ static char *geoloc_config_list_profiles(struct ast_cli_entry *e, int cmd, struc
for (; (profile = ao2_iterator_next(&iter)); ao2_ref(profile, -1)) {
ao2_lock(profile);
- precedence_to_str(profile, NULL, &precedence);
ast_cli(a->fd, "%-46.46s %-16s %-s\n",
ast_sorcery_object_get_id(profile),
- precedence,
+ precedence_names[profile->precedence],
profile->location_reference);
ao2_unlock(profile);
- ast_free(precedence);
count++;
}
ao2_iterator_destroy(&iter);
@@ -441,7 +468,7 @@ static char *geoloc_config_show_profiles(struct ast_cli_entry *e, int cmd, struc
return CLI_FAILURE;
}
- ast_cli(a->fd, "Geolocation Profile Objects:\n\n");
+ ast_cli(a->fd, "Geolocation Profile Objects:\n");
iter = ao2_iterator_init(sorted_container, AO2_ITERATOR_UNLINK);
for (; (profile = ao2_iterator_next(&iter)); ) {
@@ -450,26 +477,28 @@ static char *geoloc_config_show_profiles(struct ast_cli_entry *e, int cmd, struc
struct ast_str *variables_str = NULL;
struct ast_str *resolved_str = NULL;
struct ast_str *usage_rules_str = NULL;
+ struct ast_str *confidence_str = NULL;
struct ast_geoloc_eprofile *eprofile = ast_geoloc_eprofile_create_from_profile(profile);
ao2_ref(profile, -1);
- if (!ast_strlen_zero(eprofile->location_reference)) {
- loc_str = ast_variable_list_join(eprofile->location_info, ",", "=", "\"", NULL);
- resolved_str = ast_variable_list_join(eprofile->effective_location, ",", "=", "\"", NULL);
- }
+ loc_str = ast_variable_list_join(eprofile->location_info, ",", "=", "\"", NULL);
+ resolved_str = ast_variable_list_join(eprofile->effective_location, ",", "=", "\"", NULL);
refinement_str = ast_variable_list_join(eprofile->location_refinement, ",", "=", "\"", NULL);
variables_str = ast_variable_list_join(eprofile->location_variables, ",", "=", "\"", NULL);
usage_rules_str = ast_variable_list_join(eprofile->usage_rules, ",", "=", "\"", NULL);
+ confidence_str = ast_variable_list_join(eprofile->confidence, ",", "=", "\"", NULL);
- ast_cli(a->fd,
+ ast_cli(a->fd,"\n"
"id: %-s\n"
"profile_precedence: %-s\n"
"pidf_element: %-s\n"
"location_reference: %-s\n"
- "Location_format: %-s\n"
- "location_details: %-s\n"
+ "location_format: %-s\n"
+ "location_info: %-s\n"
"location_method: %-s\n"
+ "location_source: %-s\n"
+ "location_confidence: %-s\n"
"location_refinement: %-s\n"
"location_variables: %-s\n"
"allow_routing_use: %-s\n"
@@ -484,6 +513,8 @@ static char *geoloc_config_show_profiles(struct ast_cli_entry *e, int cmd, struc
format_names[eprofile->format],
S_COR(loc_str, ast_str_buffer(loc_str), ""),
S_OR(eprofile->method, ""),
+ S_OR(eprofile->location_source, ""),
+ S_COR(confidence_str, ast_str_buffer(confidence_str), ""),
S_COR(refinement_str, ast_str_buffer(refinement_str), ""),
S_COR(variables_str, ast_str_buffer(variables_str), ""),
S_COR(eprofile->allow_routing_use, "yes", "no"),
@@ -499,6 +530,7 @@ static char *geoloc_config_show_profiles(struct ast_cli_entry *e, int cmd, struc
ast_free(variables_str);
ast_free(resolved_str);
ast_free(usage_rules_str);
+ ast_free(confidence_str);
count++;
}
ao2_iterator_destroy(&iter);
@@ -643,11 +675,11 @@ int geoloc_config_load(void)
ast_sorcery_object_field_register(geoloc_sorcery, "location", "type", "", OPT_NOOP_T, 0, 0);
ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "format", AST_GEOLOC_FORMAT_NONE,
- format_handler, format_to_str, NULL, 0, 0);
+ location_format_handler, location_format_to_str, NULL, 0, 0);
ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "location_info", NULL,
- location_info_handler, location_info_to_str, location_info_dup, 0, 0);
+ location_location_info_handler, location_location_info_to_str, location_location_info_dup, 0, 0);
ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "confidence", NULL,
- confidence_handler, confidence_to_str, confidence_dup, 0, 0);
+ location_confidence_handler, location_confidence_to_str, location_confidence_dup, 0, 0);
ast_sorcery_object_field_register(geoloc_sorcery, "location", "location_source", "", OPT_STRINGFIELD_T,
0, STRFLDSET(struct ast_geoloc_location, location_source));
ast_sorcery_object_field_register(geoloc_sorcery, "location", "method", "", OPT_STRINGFIELD_T,
@@ -678,17 +710,17 @@ int geoloc_config_load(void)
ast_sorcery_object_field_register(geoloc_sorcery, "profile", "type", "", OPT_NOOP_T, 0, 0);
ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "pidf_element",
- pidf_element_names[AST_PIDF_ELEMENT_DEVICE], pidf_element_handler, pidf_element_to_str, NULL, 0, 0);
+ pidf_element_names[AST_PIDF_ELEMENT_DEVICE], profile_pidf_element_handler, profile_pidf_element_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(geoloc_sorcery, "profile", "location_reference", "", OPT_STRINGFIELD_T,
0, STRFLDSET(struct ast_geoloc_profile, location_reference));
ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "profile_precedence", "discard_incoming",
- precedence_handler, precedence_to_str, NULL, 0, 0);
+ profile_precedence_handler, profile_precedence_to_str, NULL, 0, 0);
ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "usage_rules", NULL,
- usage_rules_handler, usage_rules_to_str, usage_rules_dup, 0, 0);
+ profile_usage_rules_handler, profile_usage_rules_to_str, profile_usage_rules_dup, 0, 0);
ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "location_info_refinement", NULL,
- location_refinement_handler, location_refinement_to_str, location_refinement_dup, 0, 0);
+ profile_location_refinement_handler, profile_location_refinement_to_str, profile_location_refinement_dup, 0, 0);
ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "location_variables", NULL,
- location_variables_handler, location_variables_to_str, location_variables_dup, 0, 0);
+ profile_location_variables_handler, profile_location_variables_to_str, profile_location_variables_dup, 0, 0);
ast_sorcery_object_field_register(geoloc_sorcery, "profile", "notes", "", OPT_STRINGFIELD_T,
0, STRFLDSET(struct ast_geoloc_profile, notes));
ast_sorcery_object_field_register(geoloc_sorcery, "profile", "allow_routing_use",
@@ -696,6 +728,17 @@ int geoloc_config_load(void)
ast_sorcery_object_field_register(geoloc_sorcery, "profile", "suppress_empty_ca_elements",
"no", OPT_BOOL_T, 1, FLDSET(struct ast_geoloc_profile, suppress_empty_ca_elements));
+ ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "format", AST_GEOLOC_FORMAT_NONE,
+ profile_format_handler, profile_format_to_str, NULL, 0, 0);
+ ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "location_info", NULL,
+ profile_location_info_handler, profile_location_info_to_str, profile_location_info_dup, 0, 0);
+ ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "confidence", NULL,
+ profile_confidence_handler, profile_confidence_to_str, profile_confidence_dup, 0, 0);
+ ast_sorcery_object_field_register(geoloc_sorcery, "profile", "location_source", "", OPT_STRINGFIELD_T,
+ 0, STRFLDSET(struct ast_geoloc_profile, location_source));
+ ast_sorcery_object_field_register(geoloc_sorcery, "profile", "method", "", OPT_STRINGFIELD_T,
+ 0, STRFLDSET(struct ast_geoloc_profile, method));
+
ast_sorcery_load(geoloc_sorcery);
diff --git a/res/res_geolocation/geoloc_doc.xml b/res/res_geolocation/geoloc_doc.xml
index 0e1b31dbfc..4f7cdc2339 100644
--- a/res/res_geolocation/geoloc_doc.xml
+++ b/res/res_geolocation/geoloc_doc.xml
@@ -207,6 +207,11 @@
+
+
+
+
+
diff --git a/res/res_geolocation/geoloc_eprofile.c b/res/res_geolocation/geoloc_eprofile.c
index 5f20612cde..1deb76e654 100644
--- a/res/res_geolocation/geoloc_eprofile.c
+++ b/res/res_geolocation/geoloc_eprofile.c
@@ -177,11 +177,22 @@ struct ast_geoloc_eprofile *ast_geoloc_eprofile_create_from_profile(struct ast_g
eprofile->allow_routing_use = profile->allow_routing_use;
eprofile->pidf_element = profile->pidf_element;
eprofile->suppress_empty_ca_elements = profile->suppress_empty_ca_elements;
+ eprofile->format = profile->format;
+
rc = ast_string_field_set(eprofile, location_reference, profile->location_reference);
if (rc == 0) {
ast_string_field_set(eprofile, notes, profile->notes);
}
+ if (rc == 0) {
+ ast_string_field_set(eprofile, method, profile->method);
+ }
+ if (rc == 0) {
+ ast_string_field_set(eprofile, location_source, profile->location_source);
+ }
+ if (rc == 0) {
+ rc = DUP_VARS(eprofile->location_info, profile->location_info);
+ }
if (rc == 0) {
rc = DUP_VARS(eprofile->location_refinement, profile->location_refinement);
}
@@ -191,6 +202,9 @@ struct ast_geoloc_eprofile *ast_geoloc_eprofile_create_from_profile(struct ast_g
if (rc == 0) {
rc = DUP_VARS(eprofile->usage_rules, profile->usage_rules);
}
+ if (rc == 0) {
+ rc = DUP_VARS(eprofile->confidence, profile->confidence);
+ }
if (rc != 0) {
ao2_unlock(profile);
ao2_ref(eprofile, -1);
diff --git a/res/res_geolocation/geoloc_private.h b/res/res_geolocation/geoloc_private.h
index ff5e2af99f..910dbc5a3a 100644
--- a/res/res_geolocation/geoloc_private.h
+++ b/res/res_geolocation/geoloc_private.h
@@ -38,7 +38,7 @@ int ast_geoloc_ ## _stem ## _str_to_enum(const char *str) \
}
#define CONFIG_ENUM_HANDLER(_object, _stem) \
-static int _stem ## _handler(const struct aco_option *opt, struct ast_variable *var, void *obj) \
+static int _object ## _ ## _stem ## _handler(const struct aco_option *opt, struct ast_variable *var, void *obj) \
{ \
struct ast_geoloc_ ## _object *_thisobject = obj; \
int enumval = ast_geoloc_ ## _stem ## _str_to_enum(var->value); \
@@ -61,7 +61,7 @@ const char * ast_geoloc_ ## _stem ## _to_name(int ix) \
}
#define CONFIG_ENUM_TO_STR(_object, _stem) \
-static int _stem ## _to_str(const void *obj, const intptr_t *args, char **buf) \
+static int _object ## _ ## _stem ## _to_str(const void *obj, const intptr_t *args, char **buf) \
{ \
const struct ast_geoloc_ ## _object *_thisobject = obj; \
if (!ARRAY_IN_BOUNDS(_thisobject->_stem, _stem ## _names)) { \
@@ -79,7 +79,7 @@ CONFIG_ENUM_HANDLER(_object, _stem) \
CONFIG_ENUM_TO_STR(_object, _stem)
#define CONFIG_VAR_LIST_HANDLER(_object, _stem) \
-static int _stem ## _handler(const struct aco_option *opt, struct ast_variable *var, void *obj) \
+static int _object ## _ ## _stem ## _handler(const struct aco_option *opt, struct ast_variable *var, void *obj) \
{ \
struct ast_geoloc_ ## _object *_thisobject = obj; \
struct ast_variable *new_var; \
@@ -101,7 +101,7 @@ static int _stem ## _handler(const struct aco_option *opt, struct ast_variable *
}
#define CONFIG_VAR_LIST_DUP(_object, _stem) \
-static int _stem ## _dup(const void *obj, struct ast_variable **fields) \
+static int _object ## _ ## _stem ## _dup(const void *obj, struct ast_variable **fields) \
{ \
const struct ast_geoloc_ ## _object *_thisobject = obj; \
if (_thisobject->_stem) { \
@@ -111,7 +111,7 @@ static int _stem ## _dup(const void *obj, struct ast_variable **fields) \
}
#define CONFIG_VAR_LIST_TO_STR(_object, _stem) \
-static int _stem ## _to_str(const void *obj, const intptr_t *args, char **buf) \
+static int _object ## _ ## _stem ## _to_str(const void *obj, const intptr_t *args, char **buf) \
{ \
const struct ast_geoloc_ ## _object *_thisobject = obj; \
struct ast_str *str = ast_variable_list_join(_thisobject->_stem, ",", "=", "\"", NULL); \