22 #define AST_API_MODULE
23 #include "geoloc_private.h"
27 static const char *pidf_element_names[] = {
34 static const char *format_names[] = {
41 static const char * precedence_names[] = {
48 CONFIG_ENUM(location, format)
49 CONFIG_VAR_LIST(location, location_info)
50 CONFIG_VAR_LIST(location, confidence)
52 static
void geoloc_location_destructor(
void *obj) {
60 static void *geoloc_location_alloc(
const char *name)
70 CONFIG_ENUM(profile, pidf_element)
71 CONFIG_ENUM(profile, precedence)
72 CONFIG_VAR_LIST(profile, location_refinement)
73 CONFIG_VAR_LIST(profile, location_variables)
74 CONFIG_VAR_LIST(profile, usage_rules)
76 CONFIG_ENUM_HANDLER(profile, format)
77 CONFIG_ENUM_TO_STR(profile, format)
78 CONFIG_VAR_LIST(profile, location_info)
79 CONFIG_VAR_LIST(profile, confidence)
81 static
void geoloc_profile_destructor(
void *obj) {
92 static void *geoloc_profile_alloc(
const char *name)
95 geoloc_profile_destructor);
103 static enum ast_geoloc_validate_result validate_location_info(
const char *
id,
104 enum ast_geoloc_format format,
struct ast_variable *location_info)
106 enum ast_geoloc_validate_result result;
111 case AST_GEOLOC_FORMAT_NONE:
112 case AST_GEOLOC_FORMAT_LAST:
113 ast_log(LOG_ERROR,
"Location '%s' must have a format\n",
id);
115 case AST_GEOLOC_FORMAT_CIVIC_ADDRESS:
116 result = ast_geoloc_civicaddr_validate_varlist(location_info, &failed);
117 if (result != AST_GEOLOC_VALIDATE_SUCCESS) {
118 ast_log(LOG_ERROR,
"Location '%s' has invalid item '%s' in the location\n",
123 case AST_GEOLOC_FORMAT_GML:
124 result = ast_geoloc_gml_validate_varlist(location_info, &failed);
125 if (result != AST_GEOLOC_VALIDATE_SUCCESS) {
126 ast_log(LOG_ERROR,
"%s for item '%s' in location '%s'\n",
127 ast_geoloc_validate_result_to_str(result), failed,
id);
132 case AST_GEOLOC_FORMAT_URI:
137 ast_log(LOG_ERROR,
"Geolocation location '%s' format is set to '%s' but no 'URI' was found in location parameter '%s'\n",
140 return AST_GEOLOC_VALIDATE_NOT_ENOUGH_VARNAMES;
145 return AST_GEOLOC_VALIDATE_SUCCESS;
148 static int validate_location_source(
const char *
id,
const char *location_source)
150 if (!ast_strlen_zero(location_source)) {
154 ast_log(LOG_ERROR,
"Geolocation location '%s' location_source '%s' must be a FQDN."
155 " RFC8787 expressly forbids IP addresses.\n",
156 id, location_source);
164 static int geoloc_location_apply_handler(
const struct ast_sorcery *sorcery,
void *obj)
168 enum ast_geoloc_validate_result result;
171 if (!location->location_info) {
172 ast_log(LOG_ERROR,
"Location '%s' is missing required element 'location_info'",
177 result = validate_location_info(location_id, location->format, location->location_info);
178 if (result != AST_GEOLOC_VALIDATE_SUCCESS) {
182 rc = validate_location_source(location_id, location->location_source);
190 static int geoloc_profile_apply_handler(
const struct ast_sorcery *sorcery,
void *obj)
195 enum ast_geoloc_validate_result result;
196 enum ast_geoloc_format format = AST_GEOLOC_FORMAT_NONE;
199 if (!ast_strlen_zero(profile->location_reference)) {
200 if (profile->location_info ||
201 profile->format != AST_GEOLOC_FORMAT_NONE) {
202 ast_log(LOG_ERROR,
"Profile '%s' can't have location_reference and location_info or format at the same time",
209 if (profile->location_info) {
210 result = validate_location_info(
id, profile->format, profile->location_info);
211 if (result != AST_GEOLOC_VALIDATE_SUCCESS) {
215 rc = validate_location_source(
id, profile->location_source);
223 if (!ast_strlen_zero(profile->location_reference)) {
226 ast_log(LOG_ERROR,
"Profile '%s' has a location_reference '%s' that doesn't exist",
227 id, profile->location_reference);
230 format = location->format;
234 if (profile->location_refinement) {
235 result = validate_location_info(
id, format, profile->location_refinement);
236 if (result != AST_GEOLOC_VALIDATE_SUCCESS) {
247 return geoloc_sorcery;
257 char *result = CLI_SUCCESS;
263 e->
command =
"geoloc list locations";
264 e->
usage =
"Usage: geoloc list locations [ like <pattern> ]\n"
265 " List Geolocation Location Objects\n";
271 if (a->argc != 3 && a->argc != 5) {
272 return CLI_SHOWUSAGE;
276 if (strcasecmp(a->argv[3],
"like")) {
277 return CLI_SHOWUSAGE;
284 if (!sorted_container) {
285 ast_cli(a->fd,
"Geolocation Location Objects: Unable to allocate temporary container\n");
298 ao2_ref(unsorted_container, -1);
301 ast_cli(a->fd,
"Geolocation Location Objects: Unable to sort temporary container\n");
305 ast_cli(a->fd,
"Geolocation Location Objects:\n\n");
308 "<Object ID...................................> <Format.....> <Details.............>\n"
309 "===================================================================================\n");
312 for (; (loc = ao2_iterator_next(&iter));
ao2_ref(loc, -1)) {
320 ast_cli(a->fd,
"Geolocation Location Objects: Unable to allocate temp string for '%s'\n",
322 result = CLI_FAILURE;
326 ast_cli(a->fd,
"%-46.46s %-13s %-s\n",
328 format_names[loc->format],
336 ast_cli(a->fd,
"\nTotal Location Objects: %d\n\n", count);
348 char *result = CLI_SUCCESS;
354 e->
command =
"geoloc list profiles";
355 e->
usage =
"Usage: geoloc list profiles [ like <pattern> ]\n"
356 " List Geolocation Profile Objects\n";
362 if (a->argc != 3 && a->argc != 5) {
363 return CLI_SHOWUSAGE;
367 if (strcasecmp(a->argv[3],
"like")) {
368 return CLI_SHOWUSAGE;
375 if (!sorted_container) {
376 ast_cli(a->fd,
"Geolocation Profile Objects: Unable to allocate temporary container\n");
389 ao2_ref(unsorted_container, -1);
392 ast_cli(a->fd,
"Geolocation Profile Objects: Unable to sort temporary container\n");
396 ast_cli(a->fd,
"Geolocation Profile Objects:\n\n");
399 "<Object ID...................................> <Profile Action> <Location Reference> \n"
400 "=====================================================================================\n");
403 for (; (profile = ao2_iterator_next(&iter));
ao2_ref(profile, -1)) {
406 ast_cli(a->fd,
"%-46.46s %-16s %-s\n",
408 precedence_names[profile->precedence],
409 profile->location_reference);
415 ast_cli(a->fd,
"\nTotal Profile Objects: %d\n\n", count);
427 char *result = CLI_SUCCESS;
433 e->
command =
"geoloc show profiles";
434 e->
usage =
"Usage: geoloc show profiles [ like <pattern> ]\n"
435 " List Geolocation Profile Objects\n";
441 if (a->argc != 3 && a->argc != 5) {
442 return CLI_SHOWUSAGE;
446 if (strcasecmp(a->argv[3],
"like")) {
447 return CLI_SHOWUSAGE;
455 if (!sorted_container) {
456 ast_cli(a->fd,
"Geolocation Profile Objects: Unable to allocate temporary container\n");
470 ao2_ref(unsorted_container, -1);
473 ast_cli(a->fd,
"Geolocation Profile Objects: Unable to sort temporary container\n");
477 ast_cli(a->fd,
"Geolocation Profile Objects:\n");
480 for (; (profile = ao2_iterator_next(&iter)); ) {
481 struct ast_str *loc_str = NULL;
482 struct ast_str *refinement_str = NULL;
483 struct ast_str *variables_str = NULL;
484 struct ast_str *resolved_str = NULL;
485 struct ast_str *usage_rules_str = NULL;
486 struct ast_str *confidence_str = NULL;
500 "profile_precedence: %-s\n"
501 "pidf_element: %-s\n"
502 "location_reference: %-s\n"
503 "location_format: %-s\n"
504 "location_info: %-s\n"
505 "location_method: %-s\n"
506 "location_source: %-s\n"
507 "location_confidence: %-s\n"
508 "location_refinement: %-s\n"
509 "location_variables: %-s\n"
510 "allow_routing_use: %-s\n"
511 "suppress_empty_elements: %-s\n"
512 "effective_location: %-s\n"
516 precedence_names[eprofile->precedence],
517 pidf_element_names[eprofile->pidf_element],
518 S_OR(eprofile->location_reference,
"<none>"),
519 format_names[eprofile->format],
521 S_OR(eprofile->method,
"<none>"),
522 S_OR(eprofile->location_source,
"<none>"),
526 S_COR(eprofile->allow_routing_use,
"yes",
"no"),
527 S_COR(eprofile->suppress_empty_ca_elements,
"yes",
"no"),
530 S_OR(eprofile->notes,
"<none>")
535 ast_free(refinement_str);
536 ast_free(variables_str);
537 ast_free(resolved_str);
538 ast_free(usage_rules_str);
539 ast_free(confidence_str);
544 ast_cli(a->fd,
"\nTotal Profile Objects: %d\n\n", count);
551 char *result = CLI_SUCCESS;
556 e->
usage =
"Usage: geoloc reload\n"
557 " Reload Geolocation Configuration\n";
564 return CLI_SHOWUSAGE;
567 geoloc_config_reload();
568 ast_cli(a->fd,
"Geolocation Configuration reloaded.\n");
573 static struct ast_cli_entry geoloc_location_cli_commands[] = {
574 AST_CLI_DEFINE(geoloc_config_list_locations,
"List Geolocation Location Objects"),
575 AST_CLI_DEFINE(geoloc_config_list_profiles,
"List Geolocation Profile Objects"),
576 AST_CLI_DEFINE(geoloc_config_show_profiles,
"Show Geolocation Profile Objects"),
577 AST_CLI_DEFINE(geoloc_config_cli_reload,
"Reload Geolocation Configuration"),
582 if (ast_strlen_zero(
id)) {
591 if (ast_strlen_zero(
id)) {
598 int geoloc_config_reload(
void)
600 if (geoloc_sorcery) {
606 int geoloc_config_unload(
void)
613 if (geoloc_sorcery) {
616 geoloc_sorcery = NULL;
621 static int default_profile_create(
const char *name)
627 sprintf(
id,
"<%s>", name);
629 ast_assert_return(profile != NULL, 0);
631 profile->precedence = ast_geoloc_precedence_str_to_enum(name);
632 profile->pidf_element = AST_PIDF_ELEMENT_DEVICE;
641 return rc == 0 ? 1 : 0;
644 static int geoloc_load_default_profiles(
void)
651 ast_assert_return(default_profile_create(
"prefer_config"), -1);
652 ast_assert_return(default_profile_create(
"discard_config"), -1);
653 ast_assert_return(default_profile_create(
"prefer_incoming"), -1);
654 ast_assert_return(default_profile_create(
"discard_incoming"), -1);
659 int geoloc_config_load(
void)
665 ast_log(LOG_ERROR,
"Failed to open geolocation sorcery\n");
669 ast_sorcery_apply_config(geoloc_sorcery,
"location");
670 result = ast_sorcery_apply_default(geoloc_sorcery,
"location",
"config",
"geolocation.conf,criteria=type=location");
672 ast_log(LOG_ERROR,
"Failed to apply defaults for geoloc location object with sorcery\n");
678 ast_log(LOG_ERROR,
"Failed to register geoloc location object with sorcery\n");
684 location_format_handler, location_format_to_str, NULL, 0, 0);
686 location_location_info_handler, location_location_info_to_str, location_location_info_dup, 0, 0);
688 location_confidence_handler, location_confidence_to_str, location_confidence_dup, 0, 0);
695 ast_sorcery_apply_config(geoloc_sorcery,
"profile");
701 ast_log(LOG_ERROR,
"Failed to add memory wizard mapping to geoloc profile object\n");
706 "geolocation.conf,criteria=type=profile", 0);
708 ast_log(LOG_ERROR,
"Failed to add memory wizard mapping to geoloc profile object\n");
713 ast_log(LOG_ERROR,
"Failed to register geoloc profile object with sorcery\n");
719 pidf_element_names[AST_PIDF_ELEMENT_DEVICE], profile_pidf_element_handler, profile_pidf_element_to_str, NULL, 0, 0);
723 profile_precedence_handler, profile_precedence_to_str, NULL, 0, 0);
725 profile_usage_rules_handler, profile_usage_rules_to_str, profile_usage_rules_dup, 0, 0);
727 profile_location_refinement_handler, profile_location_refinement_to_str, profile_location_refinement_dup, 0, 0);
729 profile_location_variables_handler, profile_location_variables_to_str, profile_location_variables_dup, 0, 0);
738 profile_format_handler, profile_format_to_str, NULL, 0, 0);
740 profile_location_info_handler, profile_location_info_to_str, profile_location_info_dup, 0, 0);
742 profile_confidence_handler, profile_confidence_to_str, profile_confidence_dup, 0, 0);
751 rc = geoloc_load_default_profiles();
753 ast_log(LOG_ERROR,
"Failed to load default geoloc profiles\n");
Asterisk main include file. File version handling, generic pbx functions.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
#define ast_sorcery_apply_wizard_mapping(sorcery, type, name, data, caching)
Apply additional object wizard mappings.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
descriptor for a cli entry.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Structure for variables, used for configurations and for channel variables.
Perform no matching, return all objects.
Full structure for sorcery.
Type for a default handler that should do nothing.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Return all matching objects.
Socket address structure.
struct ao2_container * ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
Retrieve multiple objects using a regular expression on their id.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
Create and potentially persist an object using an available wizard.
#define ast_sorcery_object_field_register_custom(sorcery, type, name, default_val, config_handler, sorcery_handler, multiple_handler, flags,...)
Register a field within an object with custom handlers.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
int ast_sorcery_object_unregister(struct ast_sorcery *sorcery, const char *type)
Unregister an object type.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
const char * ast_variable_find_in_list(const struct ast_variable *list, const char *variable)
Gets the value of a variable from a variable list by name.
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Support for dynamic strings.
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy all object references in the src container into the dest container.
Type for default option handler for bools (ast_true/ast_false)
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
Module has failed to load, may be in an inconsistent state.
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
void ast_sorcery_load(const struct ast_sorcery *sorcery)
Inform any wizards to load persistent objects.
void ast_sorcery_reload(const struct ast_sorcery *sorcery)
Inform any wizards to reload persistent objects.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Standard Command Line Interface.
struct ast_str * ast_variable_list_join(const struct ast_variable *head, const char *item_separator, const char *name_value_separator, const char *quote_char, struct ast_str **str)
Join an ast_variable list with specified separators and quoted values.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
#define ast_sorcery_open()
Open a new sorcery structure.
Type for default option handler for stringfields.
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a red-black tree container.
#define AST_OPTIONAL_API_NAME(name)
Expands to the name of the implementation function.
void ast_sorcery_ref(struct ast_sorcery *sorcery)
Increase the reference count of a sorcery structure.
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Asterisk module definitions.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.