#include "asterisk.h"
#include "asterisk/_private.h"
#include <regex.h>
#include <signal.h>
#include "asterisk/dnsmgr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/config.h"
#include "asterisk/sched.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/acl.h"
Go to the source code of this file.
Data Structures | |
struct | ast_dnsmgr_entry |
struct | entry_list |
struct | refresh_info |
Defines | |
#define | REFRESH_DEFAULT 300 |
Functions | |
int | ast_dnsmgr_changed (struct ast_dnsmgr_entry *entry) |
Check is see if a dnsmgr entry has changed. | |
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. | |
int | ast_dnsmgr_refresh (struct ast_dnsmgr_entry *entry) |
Force a refresh of a dnsmgr entry. | |
void | ast_dnsmgr_release (struct ast_dnsmgr_entry *entry) |
Free a DNS manager entry. | |
int | dnsmgr_init (void) |
static int | dnsmgr_refresh (struct ast_dnsmgr_entry *entry, int verbose) |
int | dnsmgr_reload (void) |
void | dnsmgr_start_refresh (void) |
static void * | do_refresh (void *data) |
static int | do_reload (int loading) |
static char * | handle_cli_refresh (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | refresh_list (const void *data) |
Variables | |
static struct ast_cli_entry | cli_refresh = { .handler = handle_cli_refresh , .summary = "Performs an immediate refresh" ,__VA_ARGS__ } |
static struct ast_cli_entry | cli_reload = { .handler = handle_cli_reload , .summary = "Reloads the DNS manager configuration" ,__VA_ARGS__ } |
static struct ast_cli_entry | cli_status = { .handler = handle_cli_status , .summary = "Display the DNS manager status" ,__VA_ARGS__ } |
static int | enabled |
static struct refresh_info | master_refresh_info |
static int | refresh_interval |
static ast_mutex_t | refresh_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } |
static int | refresh_sched = -1 |
static pthread_t | refresh_thread = AST_PTHREADT_NULL |
static struct sched_context * | sched |
Definition in file dnsmgr.c.
#define REFRESH_DEFAULT 300 |
int ast_dnsmgr_changed | ( | struct ast_dnsmgr_entry * | entry | ) |
Check is see if a dnsmgr entry has changed.
non-zero | if the dnsmgr entry has changed since the last call to this function | |
zero | if the dnsmgr entry has not changed since the last call to this function |
Definition at line 193 of file dnsmgr.c.
References ast_mutex_lock, ast_mutex_unlock, ast_dnsmgr_entry::changed, and ast_dnsmgr_entry::lock.
Referenced by iax2_do_register().
00194 { 00195 int changed; 00196 00197 ast_mutex_lock(&entry->lock); 00198 00199 changed = entry->changed; 00200 entry->changed = 0; 00201 00202 ast_mutex_unlock(&entry->lock); 00203 00204 return changed; 00205 }
struct ast_dnsmgr_entry* ast_dnsmgr_get | ( | const char * | name, | |
struct ast_sockaddr * | result, | |||
const char * | service | |||
) |
Allocate a new DNS manager entry.
name | the hostname | |
result | where the DNS manager should store the IP address as it refreshes it. | |
service | This function allocates a new DNS manager entry object, and fills it with the provided hostname and IP address. This function does not force an initial lookup of the IP address. So, generally, this should be used when the initial address is already known. |
1.8.0 result changed from struct ast_sockaddr_in to ast_sockaddr for IPv6 support
Definition at line 86 of file dnsmgr.c.
References ast_calloc, ast_mutex_init, AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero(), ast_dnsmgr_entry::list, ast_dnsmgr_entry::lock, ast_dnsmgr_entry::name, ast_dnsmgr_entry::result, and ast_dnsmgr_entry::service.
Referenced by ast_dnsmgr_lookup().
00087 { 00088 struct ast_dnsmgr_entry *entry; 00089 int total_size = sizeof(*entry) + strlen(name) + (service ? strlen(service) + 1 : 0); 00090 00091 if (!result || ast_strlen_zero(name) || !(entry = ast_calloc(1, total_size))) { 00092 return NULL; 00093 } 00094 00095 entry->result = result; 00096 ast_mutex_init(&entry->lock); 00097 strcpy(entry->name, name); 00098 if (service) { 00099 entry->service = ((char *) entry) + sizeof(*entry) + strlen(name); 00100 strcpy(entry->service, service); 00101 } 00102 00103 AST_RWLIST_WRLOCK(&entry_list); 00104 AST_RWLIST_INSERT_HEAD(&entry_list, entry, list); 00105 AST_RWLIST_UNLOCK(&entry_list); 00106 00107 return entry; 00108 }
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.
name | the hostname | |
result | where to store the IP address as the DNS manager refreshes it. The address family is used as an input parameter to filter the returned adresses. if it is 0, both IPv4 * and IPv6 addresses can be returned. | |
dnsmgr | Where to store the allocate DNS manager entry | |
service | This function allocates a new DNS manager entry object, and fills it with the provided hostname and IP address. This function _does_ force an initial lookup, so it may block for some period of time. |
0 | success | |
non-zero | failure |
Definition at line 124 of file dnsmgr.c.
References ast_dnsmgr_get(), ast_get_ip_or_srv(), ast_strlen_zero(), ast_verb, enabled, and ast_dnsmgr_entry::result.
Referenced by __sip_subscribe_mwi_do(), build_peer(), iax2_append_register(), and transmit_register().
00125 { 00126 if (ast_strlen_zero(name) || !result || !dnsmgr) { 00127 return -1; 00128 } 00129 00130 if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name)) { 00131 return 0; 00132 } 00133 00134 ast_verb(4, "doing dnsmgr_lookup for '%s'\n", name); 00135 00136 /* do a lookup now but add a manager so it will automagically get updated in the background */ 00137 ast_get_ip_or_srv(result, name, service); 00138 00139 /* if dnsmgr is not enable don't bother adding an entry */ 00140 if (!enabled) { 00141 return 0; 00142 } 00143 00144 ast_verb(3, "adding dns manager for '%s'\n", name); 00145 *dnsmgr = ast_dnsmgr_get(name, result, service); 00146 return !*dnsmgr; 00147 }
int ast_dnsmgr_refresh | ( | struct ast_dnsmgr_entry * | entry | ) |
Force a refresh of a dnsmgr entry.
non-zero | if the result is different than the previous result | |
zero | if the result is the same as the previous result |
Definition at line 185 of file dnsmgr.c.
References dnsmgr_refresh().
Referenced by build_peer(), iax2_do_register(), and sip_reg_timeout().
00186 { 00187 return dnsmgr_refresh(entry, 0); 00188 }
void ast_dnsmgr_release | ( | struct ast_dnsmgr_entry * | entry | ) |
Free a DNS manager entry.
entry | the DNS manager entry to free |
Definition at line 110 of file dnsmgr.c.
References ast_free, ast_mutex_destroy, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_dnsmgr_entry::list, ast_dnsmgr_entry::lock, and ast_dnsmgr_entry::name.
Referenced by delete_users(), peer_destructor(), sip_destroy_peer(), sip_registry_destroy(), and sip_subscribe_mwi_destroy().
00111 { 00112 if (!entry) 00113 return; 00114 00115 AST_RWLIST_WRLOCK(&entry_list); 00116 AST_RWLIST_REMOVE(&entry_list, entry, list); 00117 AST_RWLIST_UNLOCK(&entry_list); 00118 ast_verb(4, "removing dns manager for '%s'\n", entry->name); 00119 00120 ast_mutex_destroy(&entry->lock); 00121 ast_free(entry); 00122 }
int dnsmgr_init | ( | void | ) |
Provided by dnsmgr.c
Definition at line 352 of file dnsmgr.c.
References ast_cli_register(), ast_log(), cli_refresh, cli_reload, cli_status, do_reload(), LOG_ERROR, sched, and sched_context_create().
Referenced by main().
00353 { 00354 if (!(sched = sched_context_create())) { 00355 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 00356 return -1; 00357 } 00358 ast_cli_register(&cli_reload); 00359 ast_cli_register(&cli_status); 00360 ast_cli_register(&cli_refresh); 00361 return do_reload(1); 00362 }
static int dnsmgr_refresh | ( | struct ast_dnsmgr_entry * | entry, | |
int | verbose | |||
) | [static] |
Definition at line 152 of file dnsmgr.c.
References ast_get_ip_or_srv(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdupa, ast_verb, ast_dnsmgr_entry::changed, ast_sockaddr::len, ast_dnsmgr_entry::lock, LOG_NOTICE, ast_dnsmgr_entry::name, ast_dnsmgr_entry::result, and ast_dnsmgr_entry::service.
Referenced by ast_dnsmgr_refresh(), and refresh_list().
00153 { 00154 struct ast_sockaddr tmp = { .len = 0, }; 00155 int changed = 0; 00156 00157 ast_mutex_lock(&entry->lock); 00158 00159 if (verbose) { 00160 ast_verb(3, "refreshing '%s'\n", entry->name); 00161 } 00162 00163 if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service)) { 00164 if (!ast_sockaddr_port(&tmp)) { 00165 ast_sockaddr_set_port(&tmp, ast_sockaddr_port(entry->result)); 00166 } 00167 00168 if (ast_sockaddr_cmp(&tmp, entry->result)) { 00169 const char *old_addr = ast_strdupa(ast_sockaddr_stringify(entry->result)); 00170 const char *new_addr = ast_strdupa(ast_sockaddr_stringify(&tmp)); 00171 00172 ast_log(LOG_NOTICE, "dnssrv: host '%s' changed from %s to %s\n", 00173 entry->name, old_addr, new_addr); 00174 00175 ast_sockaddr_copy(entry->result, &tmp); 00176 changed = entry->changed = 1; 00177 } 00178 } 00179 00180 ast_mutex_unlock(&entry->lock); 00181 00182 return changed; 00183 }
int dnsmgr_reload | ( | void | ) |
Provided by dnsmgr.c
Definition at line 364 of file dnsmgr.c.
References do_reload().
00365 { 00366 return do_reload(0); 00367 }
void dnsmgr_start_refresh | ( | void | ) |
Provided by dnsmgr.c
Definition at line 246 of file dnsmgr.c.
References ast_sched_add_variable(), AST_SCHED_DEL, master_refresh_info, refresh_list(), and sched.
Referenced by main().
00247 { 00248 if (refresh_sched > -1) { 00249 AST_SCHED_DEL(sched, refresh_sched); 00250 refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1); 00251 } 00252 }
static void* do_refresh | ( | void * | data | ) | [static] |
Definition at line 207 of file dnsmgr.c.
References ast_sched_runq(), ast_sched_wait(), and sched.
Referenced by do_reload(), and load_module().
00208 { 00209 for (;;) { 00210 pthread_testcancel(); 00211 usleep((ast_sched_wait(sched)*1000)); 00212 pthread_testcancel(); 00213 ast_sched_runq(sched); 00214 } 00215 return NULL; 00216 }
static int do_reload | ( | int | loading | ) | [static] |
Definition at line 369 of file dnsmgr.c.
References ast_config_destroy(), ast_config_load2(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, ast_sched_add_variable(), AST_SCHED_DEL, ast_true(), ast_variable_retrieve(), config, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, do_refresh(), enabled, EVENT_FLAG_SYSTEM, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, master_refresh_info, REFRESH_DEFAULT, refresh_interval, refresh_list(), and sched.
00370 { 00371 struct ast_config *config; 00372 struct ast_flags config_flags = { loading ? 0 : CONFIG_FLAG_FILEUNCHANGED }; 00373 const char *interval_value; 00374 const char *enabled_value; 00375 int interval; 00376 int was_enabled; 00377 int res = -1; 00378 00379 config = ast_config_load2("dnsmgr.conf", "dnsmgr", config_flags); 00380 if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEUNCHANGED || config == CONFIG_STATUS_FILEINVALID) { 00381 return 0; 00382 } 00383 00384 /* ensure that no refresh cycles run while the reload is in progress */ 00385 ast_mutex_lock(&refresh_lock); 00386 00387 /* reset defaults in preparation for reading config file */ 00388 refresh_interval = REFRESH_DEFAULT; 00389 was_enabled = enabled; 00390 enabled = 0; 00391 00392 AST_SCHED_DEL(sched, refresh_sched); 00393 00394 if (config) { 00395 if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) { 00396 enabled = ast_true(enabled_value); 00397 } 00398 if ((interval_value = ast_variable_retrieve(config, "general", "refreshinterval"))) { 00399 if (sscanf(interval_value, "%30d", &interval) < 1) 00400 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", interval_value); 00401 else if (interval < 0) 00402 ast_log(LOG_WARNING, "Invalid refresh interval '%d' specified, using default\n", interval); 00403 else 00404 refresh_interval = interval; 00405 } 00406 ast_config_destroy(config); 00407 } 00408 00409 if (enabled && refresh_interval) 00410 ast_log(LOG_NOTICE, "Managed DNS entries will be refreshed every %d seconds.\n", refresh_interval); 00411 00412 /* if this reload enabled the manager, create the background thread 00413 if it does not exist */ 00414 if (enabled) { 00415 if (!was_enabled && (refresh_thread == AST_PTHREADT_NULL)) { 00416 if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) { 00417 ast_log(LOG_ERROR, "Unable to start refresh thread.\n"); 00418 } 00419 } 00420 /* make a background refresh happen right away */ 00421 refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1); 00422 res = 0; 00423 } 00424 /* if this reload disabled the manager and there is a background thread, 00425 kill it */ 00426 else if (!enabled && was_enabled && (refresh_thread != AST_PTHREADT_NULL)) { 00427 /* wake up the thread so it will exit */ 00428 pthread_cancel(refresh_thread); 00429 pthread_kill(refresh_thread, SIGURG); 00430 pthread_join(refresh_thread, NULL); 00431 refresh_thread = AST_PTHREADT_NULL; 00432 res = 0; 00433 } 00434 else 00435 res = 0; 00436 00437 ast_mutex_unlock(&refresh_lock); 00438 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: DNSmgr\r\nStatus: %s\r/nMessage: DNSmgr reload Requested\r\n", enabled ? "Enabled" : "Disabled"); 00439 00440 return res; 00441 }
static char* handle_cli_refresh | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 275 of file dnsmgr.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, enabled, refresh_info::entries, ast_cli_args::fd, refresh_info::filter, refresh_list(), refresh_info::regex_present, and ast_cli_entry::usage.
00276 { 00277 struct refresh_info info = { 00278 .entries = &entry_list, 00279 .verbose = 1, 00280 }; 00281 switch (cmd) { 00282 case CLI_INIT: 00283 e->command = "dnsmgr refresh"; 00284 e->usage = 00285 "Usage: dnsmgr refresh [pattern]\n" 00286 " Peforms an immediate refresh of the managed DNS entries.\n" 00287 " Optional regular expression pattern is used to filter the entries to refresh.\n"; 00288 return NULL; 00289 case CLI_GENERATE: 00290 return NULL; 00291 } 00292 00293 if (!enabled) { 00294 ast_cli(a->fd, "DNS Manager is disabled.\n"); 00295 return 0; 00296 } 00297 00298 if (a->argc > 3) { 00299 return CLI_SHOWUSAGE; 00300 } 00301 00302 if (a->argc == 3) { 00303 if (regcomp(&info.filter, a->argv[2], REG_EXTENDED | REG_NOSUB)) { 00304 return CLI_SHOWUSAGE; 00305 } else { 00306 info.regex_present = 1; 00307 } 00308 } 00309 00310 refresh_list(&info); 00311 00312 if (info.regex_present) { 00313 regfree(&info.filter); 00314 } 00315 00316 return CLI_SUCCESS; 00317 }
static char* handle_cli_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 256 of file dnsmgr.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, do_reload(), and ast_cli_entry::usage.
00257 { 00258 switch (cmd) { 00259 case CLI_INIT: 00260 e->command = "dnsmgr reload"; 00261 e->usage = 00262 "Usage: dnsmgr reload\n" 00263 " Reloads the DNS manager configuration.\n"; 00264 return NULL; 00265 case CLI_GENERATE: 00266 return NULL; 00267 } 00268 if (a->argc > 2) 00269 return CLI_SHOWUSAGE; 00270 00271 do_reload(0); 00272 return CLI_SUCCESS; 00273 }
static char* handle_cli_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 319 of file dnsmgr.c.
References ast_cli_args::argc, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, enabled, ast_cli_args::fd, ast_dnsmgr_entry::list, refresh_interval, and ast_cli_entry::usage.
00320 { 00321 int count = 0; 00322 struct ast_dnsmgr_entry *entry; 00323 switch (cmd) { 00324 case CLI_INIT: 00325 e->command = "dnsmgr status"; 00326 e->usage = 00327 "Usage: dnsmgr status\n" 00328 " Displays the DNS manager status.\n"; 00329 return NULL; 00330 case CLI_GENERATE: 00331 return NULL; 00332 } 00333 00334 if (a->argc > 2) 00335 return CLI_SHOWUSAGE; 00336 00337 ast_cli(a->fd, "DNS Manager: %s\n", enabled ? "enabled" : "disabled"); 00338 ast_cli(a->fd, "Refresh Interval: %d seconds\n", refresh_interval); 00339 AST_RWLIST_RDLOCK(&entry_list); 00340 AST_RWLIST_TRAVERSE(&entry_list, entry, list) 00341 count++; 00342 AST_RWLIST_UNLOCK(&entry_list); 00343 ast_cli(a->fd, "Number of entries: %d\n", count); 00344 00345 return CLI_SUCCESS; 00346 }
static int refresh_list | ( | const void * | data | ) | [static] |
Definition at line 218 of file dnsmgr.c.
References ast_log(), ast_mutex_trylock, ast_mutex_unlock, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_verb, dnsmgr_refresh(), refresh_info::entries, refresh_info::filter, ast_dnsmgr_entry::list, LOG_WARNING, ast_dnsmgr_entry::name, refresh_interval, refresh_info::regex_present, and refresh_info::verbose.
Referenced by dnsmgr_start_refresh(), do_reload(), and handle_cli_refresh().
00219 { 00220 struct refresh_info *info = (struct refresh_info *)data; 00221 struct ast_dnsmgr_entry *entry; 00222 00223 /* if a refresh or reload is already in progress, exit now */ 00224 if (ast_mutex_trylock(&refresh_lock)) { 00225 if (info->verbose) 00226 ast_log(LOG_WARNING, "DNS Manager refresh already in progress.\n"); 00227 return -1; 00228 } 00229 00230 ast_verb(3, "Refreshing DNS lookups.\n"); 00231 AST_RWLIST_RDLOCK(info->entries); 00232 AST_RWLIST_TRAVERSE(info->entries, entry, list) { 00233 if (info->regex_present && regexec(&info->filter, entry->name, 0, NULL, 0)) 00234 continue; 00235 00236 dnsmgr_refresh(entry, info->verbose); 00237 } 00238 AST_RWLIST_UNLOCK(info->entries); 00239 00240 ast_mutex_unlock(&refresh_lock); 00241 00242 /* automatically reschedule based on the interval */ 00243 return refresh_interval * 1000; 00244 }
struct ast_cli_entry cli_refresh = { .handler = handle_cli_refresh , .summary = "Performs an immediate refresh" ,__VA_ARGS__ } [static] |
struct ast_cli_entry cli_reload = { .handler = handle_cli_reload , .summary = "Reloads the DNS manager configuration" ,__VA_ARGS__ } [static] |
Definition at line 348 of file dnsmgr.c.
Referenced by dnsmgr_init(), load_module(), and unload_module().
struct ast_cli_entry cli_status = { .handler = handle_cli_status , .summary = "Display the DNS manager status" ,__VA_ARGS__ } [static] |
struct refresh_info master_refresh_info [static] |
Initial value:
{ .entries = &entry_list, .verbose = 0, }
Definition at line 81 of file dnsmgr.c.
Referenced by dnsmgr_start_refresh(), and do_reload().
int refresh_interval [static] |
Definition at line 72 of file dnsmgr.c.
Referenced by do_reload(), handle_cli_status(), and refresh_list().
ast_mutex_t refresh_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static] |
int refresh_sched = -1 [static] |
pthread_t refresh_thread = AST_PTHREADT_NULL [static] |
struct sched_context* sched [static] |