63 static int refresh_sched = -1;
64 static pthread_t refresh_thread = AST_PTHREADT_NULL;
87 AST_MUTEX_DEFINE_STATIC(refresh_lock);
89 #define REFRESH_DEFAULT 300
92 static int refresh_interval;
95 struct entry_list *entries;
97 unsigned int regex_present:1;
102 .entries = &entry_list,
108 struct ast_dnsmgr_entry *
entry;
109 int total_size =
sizeof(*entry) + strlen(name) + (service ? strlen(service) + 1 : 0);
111 if (!result || ast_strlen_zero(name) || !(entry =
ast_calloc(1, total_size))) {
116 ast_mutex_init(&entry->lock);
117 strcpy(entry->name, name);
119 entry->
service = ((
char *) entry) +
sizeof(*entry) + strlen(name);
120 strcpy(entry->
service, service);
125 AST_RWLIST_INSERT_HEAD(&entry_list, entry, list);
143 AST_RWLIST_REMOVE(&entry_list, entry, list);
145 ast_debug(6,
"removing dns manager for '%s'\n", entry->name);
147 ast_mutex_destroy(&entry->lock);
151 static int internal_dnsmgr_lookup(
const char *name,
struct ast_sockaddr *result,
struct ast_dnsmgr_entry **dnsmgr,
const char *service, dns_update_func func,
void *data)
155 if (ast_strlen_zero(name) || !result || !dnsmgr) {
159 if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name)) {
164 family = result->ss.ss_family;
174 ast_debug(6,
"doing dnsmgr_lookup for '%s'\n", name);
184 ast_debug(6,
"adding dns manager for '%s'\n", name);
186 (*dnsmgr)->update_func = func;
187 (*dnsmgr)->data =
data;
193 return internal_dnsmgr_lookup(name, result, dnsmgr, service, NULL, NULL);
198 return internal_dnsmgr_lookup(name, result, dnsmgr, service, func, data);
204 static int dnsmgr_refresh(
struct ast_dnsmgr_entry *
entry,
int verbose)
209 ast_mutex_lock(&entry->lock);
211 ast_debug(6,
"refreshing '%s'\n", entry->name);
213 tmp.ss.ss_family = entry->
family;
225 ast_log(LOG_NOTICE,
"dnssrv: host '%s' changed from %s to %s\n",
226 entry->name, old_addr, new_addr);
234 ast_mutex_unlock(&entry->lock);
241 return dnsmgr_refresh(entry, 0);
251 ast_mutex_lock(&entry->lock);
256 ast_mutex_unlock(&entry->lock);
261 static void *do_refresh(
void *data)
264 pthread_testcancel();
266 pthread_testcancel();
272 static int refresh_list(
const void *data)
275 struct ast_dnsmgr_entry *entry;
278 if (ast_mutex_trylock(&refresh_lock)) {
280 ast_log(LOG_WARNING,
"DNS Manager refresh already in progress.\n");
285 ast_debug(6,
"Refreshing DNS lookups.\n");
287 AST_RWLIST_TRAVERSE(info->entries, entry, list) {
288 if (info->regex_present && regexec(&info->filter, entry->name, 0, NULL, 0)) {
292 dnsmgr_refresh(entry, info->verbose);
296 ast_mutex_unlock(&refresh_lock);
299 return refresh_interval * 1000;
304 if (refresh_sched > -1) {
310 static int do_reload(
int loading);
318 "Usage: dnsmgr reload\n"
319 " Reloads the DNS manager configuration.\n";
325 return CLI_SHOWUSAGE;
335 .entries = &entry_list,
342 "Usage: dnsmgr refresh [pattern]\n"
343 " Performs an immediate refresh of the managed DNS entries.\n"
344 " Optional regular expression pattern is used to filter the entries to refresh.\n";
351 ast_cli(a->fd,
"DNS Manager is disabled.\n");
356 return CLI_SHOWUSAGE;
360 if (regcomp(&info.filter, a->argv[2], REG_EXTENDED | REG_NOSUB)) {
361 return CLI_SHOWUSAGE;
363 info.regex_present = 1;
369 if (info.regex_present) {
370 regfree(&info.filter);
379 struct ast_dnsmgr_entry *entry;
384 "Usage: dnsmgr status\n"
385 " Displays the DNS manager status.\n";
392 return CLI_SHOWUSAGE;
395 ast_cli(a->fd,
"DNS Manager: %s\n", enabled ?
"enabled" :
"disabled");
396 ast_cli(a->fd,
"Refresh Interval: %d seconds\n", refresh_interval);
398 AST_RWLIST_TRAVERSE(&entry_list, entry, list)
401 ast_cli(a->fd, "Number of entries: %d\n", count);
406 static struct
ast_cli_entry cli_reload = AST_CLI_DEFINE(handle_cli_reload, "Reloads the DNS manager configuration");
407 static struct
ast_cli_entry cli_refresh = AST_CLI_DEFINE(handle_cli_refresh, "Performs an immediate
refresh");
408 static struct
ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the DNS manager status");
410 static
int unload_module(
void)
417 ast_mutex_lock(&refresh_lock);
418 if (refresh_thread != AST_PTHREADT_NULL) {
420 pthread_cancel(refresh_thread);
421 pthread_kill(refresh_thread, SIGURG);
422 pthread_join(refresh_thread, NULL);
423 refresh_thread = AST_PTHREADT_NULL;
425 ast_mutex_unlock(&refresh_lock);
432 static int load_module(
void)
435 ast_log(LOG_ERROR,
"Unable to create schedule context.\n");
445 static int reload_module(
void)
450 static int do_reload(
int loading)
458 if ((config =
ast_config_load2(
"dnsmgr.conf",
"dnsmgr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
463 ast_mutex_lock(&refresh_lock);
466 refresh_interval = REFRESH_DEFAULT;
470 if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
471 ast_mutex_unlock(&refresh_lock);
477 for (v = ast_variable_browse(config,
"general"); v; v = v->
next) {
478 if (!strcasecmp(v->
name,
"enable")) {
480 }
else if (!strcasecmp(v->
name,
"refreshinterval")) {
481 if (sscanf(v->
value,
"%30d", &interval) < 1) {
482 ast_log(LOG_WARNING,
"Unable to convert '%s' to a numeric value.\n", v->
value);
483 }
else if (interval < 0) {
484 ast_log(LOG_WARNING,
"Invalid refresh interval '%d' specified, using default\n", interval);
486 refresh_interval = interval;
492 if (enabled && refresh_interval) {
493 ast_log(LOG_NOTICE,
"Managed DNS entries will be refreshed every %d seconds.\n", refresh_interval);
499 if (!was_enabled && (refresh_thread == AST_PTHREADT_NULL)) {
500 if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) {
501 ast_log(LOG_ERROR,
"Unable to start refresh thread.\n");
507 }
else if (!enabled && was_enabled && (refresh_thread != AST_PTHREADT_NULL)) {
509 pthread_cancel(refresh_thread);
510 pthread_kill(refresh_thread, SIGURG);
511 pthread_join(refresh_thread, NULL);
512 refresh_thread = AST_PTHREADT_NULL;
515 ast_mutex_unlock(&refresh_lock);
520 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"DNS Manager",
521 .support_level = AST_MODULE_SUPPORT_CORE,
523 .unload = unload_module,
524 .reload = reload_module,
526 .requires =
"extconfig",
struct ast_variable * next
Asterisk main include file. File version handling, generic pbx functions.
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
descriptor for a cli entry.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Structure for variables, used for configurations and for channel variables.
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
Adds a scheduled event with rescheduling support.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Background DNS update manager.
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Socket address structure.
int ast_dnsmgr_refresh(struct ast_dnsmgr_entry *entry)
Force a refresh of a dnsmgr entry.
#define ast_cli_register(e)
Registers a command or an array of commands.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Configuration File Parser.
dns_update_func update_func
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Access Control of various sorts.
int ast_dnsmgr_lookup_cb(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service, dns_update_func func, void *data)
Allocate and initialize a DNS manager entry, with update callback.
Scheduler Routines (derived from cheops)
struct ast_sockaddr * result
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry)
Free a DNS manager entry.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
#define ast_calloc(num, len)
A wrapper for calloc()
void dnsmgr_start_refresh(void)
Module could not be loaded properly.
Prototypes for public functions only of internal interest,.
Structure used to handle boolean flags.
int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *hostname, const char *service)
Get the IP address given a hostname and optional service.
Standard Command Line Interface.
static int enabled
Whether or not we are storing history.
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
struct ast_dnsmgr_entry * ast_dnsmgr_get_family(const char *name, struct ast_sockaddr *result, const char *service, unsigned int family)
Allocate a new DNS manager entry.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
struct ast_dnsmgr_entry * ast_dnsmgr_get(const char *name, struct ast_sockaddr *result, const char *service)
Allocate a new DNS manager entry.
int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service)
Allocate and initialize a DNS manager entry.
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Structure for mutex and tracking information.
int ast_dnsmgr_changed(struct ast_dnsmgr_entry *entry)
Check is see if a dnsmgr entry has changed.