#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 sockaddr_in *result, const char *service) |
Allocate a new DNS manager entry. | |
int | ast_dnsmgr_lookup (const char *name, struct sockaddr_in *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 = ((ast_mutex_t) 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 191 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().
00192 { 00193 int changed; 00194 00195 ast_mutex_lock(&entry->lock); 00196 00197 changed = entry->changed; 00198 entry->changed = 0; 00199 00200 ast_mutex_unlock(&entry->lock); 00201 00202 return changed; 00203 }
struct ast_dnsmgr_entry* ast_dnsmgr_get | ( | const char * | name, | |
struct sockaddr_in * | 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. it. |
Definition at line 88 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::last, 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().
00089 { 00090 struct ast_dnsmgr_entry *entry; 00091 int total_size = sizeof(*entry) + strlen(name) + (service ? strlen(service) + 1 : 0); 00092 00093 if (!result || ast_strlen_zero(name) || !(entry = ast_calloc(1, total_size))) 00094 return NULL; 00095 00096 entry->result = result; 00097 ast_mutex_init(&entry->lock); 00098 strcpy(entry->name, name); 00099 memcpy(&entry->last, result, sizeof(entry->last)); 00100 if (service) { 00101 entry->service = ((char *) entry) + sizeof(*entry) + strlen(name); 00102 strcpy(entry->service, service); 00103 } 00104 00105 AST_RWLIST_WRLOCK(&entry_list); 00106 AST_RWLIST_INSERT_HEAD(&entry_list, entry, list); 00107 AST_RWLIST_UNLOCK(&entry_list); 00108 00109 return entry; 00110 }
int ast_dnsmgr_lookup | ( | const char * | name, | |
struct sockaddr_in * | 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 | |
dnsmgr | Where to store the allocate DNS manager entry |
0 | success | |
non-zero | failure |
Definition at line 126 of file dnsmgr.c.
References ast_dnsmgr_get(), ast_get_ip_or_srv(), ast_strlen_zero(), ast_verb, enabled, and inet_aton().
Referenced by build_peer(), iax2_append_register(), and transmit_register().
00127 { 00128 if (ast_strlen_zero(name) || !result || !dnsmgr) 00129 return -1; 00130 00131 if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name)) 00132 return 0; 00133 00134 /* if it's actually an IP address and not a name, 00135 there's no need for a managed lookup */ 00136 if (inet_aton(name, &result->sin_addr)) 00137 return 0; 00138 00139 ast_verb(4, "doing dnsmgr_lookup for '%s'\n", name); 00140 00141 /* do a lookup now but add a manager so it will automagically get updated in the background */ 00142 ast_get_ip_or_srv(result, name, service); 00143 00144 /* if dnsmgr is not enable don't bother adding an entry */ 00145 if (!enabled) 00146 return 0; 00147 00148 ast_verb(3, "adding dns manager for '%s'\n", name); 00149 *dnsmgr = ast_dnsmgr_get(name, result, service); 00150 return !*dnsmgr; 00151 }
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 183 of file dnsmgr.c.
References dnsmgr_refresh().
Referenced by iax2_do_register(), and sip_reg_timeout().
00184 { 00185 return dnsmgr_refresh(entry, 0); 00186 }
void ast_dnsmgr_release | ( | struct ast_dnsmgr_entry * | entry | ) |
Free a DNS manager entry.
entry | the DNS manager entry to free |
Definition at line 112 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(), and sip_registry_destroy().
00113 { 00114 if (!entry) 00115 return; 00116 00117 AST_RWLIST_WRLOCK(&entry_list); 00118 AST_RWLIST_REMOVE(&entry_list, entry, list); 00119 AST_RWLIST_UNLOCK(&entry_list); 00120 ast_verb(4, "removing dns manager for '%s'\n", entry->name); 00121 00122 ast_mutex_destroy(&entry->lock); 00123 ast_free(entry); 00124 }
int dnsmgr_init | ( | void | ) |
Provided by dnsmgr.c
Definition at line 350 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().
00351 { 00352 if (!(sched = sched_context_create())) { 00353 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 00354 return -1; 00355 } 00356 ast_cli_register(&cli_reload); 00357 ast_cli_register(&cli_status); 00358 ast_cli_register(&cli_refresh); 00359 return do_reload(1); 00360 }
static int dnsmgr_refresh | ( | struct ast_dnsmgr_entry * | entry, | |
int | verbose | |||
) | [static] |
Definition at line 156 of file dnsmgr.c.
References ast_copy_string(), ast_get_ip_or_srv(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, ast_dnsmgr_entry::changed, inaddrcmp(), ast_dnsmgr_entry::last, 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().
00157 { 00158 char iabuf[INET_ADDRSTRLEN]; 00159 char iabuf2[INET_ADDRSTRLEN]; 00160 struct sockaddr_in tmp; 00161 int changed = 0; 00162 00163 ast_mutex_lock(&entry->lock); 00164 if (verbose) 00165 ast_verb(3, "refreshing '%s'\n", entry->name); 00166 00167 tmp.sin_port = entry->last.sin_port; 00168 00169 if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service) && inaddrcmp(&tmp, &entry->last)) { 00170 ast_copy_string(iabuf, ast_inet_ntoa(entry->last.sin_addr), sizeof(iabuf)); 00171 ast_copy_string(iabuf2, ast_inet_ntoa(tmp.sin_addr), sizeof(iabuf2)); 00172 ast_log(LOG_NOTICE, "dnssrv: host '%s' changed from %s:%d to %s:%d\n", 00173 entry->name, iabuf, ntohs(entry->last.sin_port), iabuf2, ntohs(tmp.sin_port)); 00174 *entry->result = tmp; 00175 entry->last = tmp; 00176 changed = entry->changed = 1; 00177 } 00178 00179 ast_mutex_unlock(&entry->lock); 00180 return changed; 00181 }
int dnsmgr_reload | ( | void | ) |
Provided by dnsmgr.c
Definition at line 362 of file dnsmgr.c.
References do_reload().
00363 { 00364 return do_reload(0); 00365 }
void dnsmgr_start_refresh | ( | void | ) |
Provided by dnsmgr.c
Definition at line 244 of file dnsmgr.c.
References ast_sched_add_variable(), AST_SCHED_DEL, master_refresh_info, refresh_list(), and sched.
Referenced by main().
00245 { 00246 if (refresh_sched > -1) { 00247 AST_SCHED_DEL(sched, refresh_sched); 00248 refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1); 00249 } 00250 }
static void* do_refresh | ( | void * | data | ) | [static] |
Definition at line 205 of file dnsmgr.c.
References ast_sched_runq(), ast_sched_wait(), and sched.
Referenced by do_reload().
00206 { 00207 for (;;) { 00208 pthread_testcancel(); 00209 usleep((ast_sched_wait(sched)*1000)); 00210 pthread_testcancel(); 00211 ast_sched_runq(sched); 00212 } 00213 return NULL; 00214 }
static int do_reload | ( | int | loading | ) | [static] |
Definition at line 367 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_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.
00368 { 00369 struct ast_config *config; 00370 struct ast_flags config_flags = { loading ? 0 : CONFIG_FLAG_FILEUNCHANGED }; 00371 const char *interval_value; 00372 const char *enabled_value; 00373 int interval; 00374 int was_enabled; 00375 int res = -1; 00376 00377 if ((config = ast_config_load2("dnsmgr.conf", "dnsmgr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 00378 return 0; 00379 00380 /* ensure that no refresh cycles run while the reload is in progress */ 00381 ast_mutex_lock(&refresh_lock); 00382 00383 /* reset defaults in preparation for reading config file */ 00384 refresh_interval = REFRESH_DEFAULT; 00385 was_enabled = enabled; 00386 enabled = 0; 00387 00388 AST_SCHED_DEL(sched, refresh_sched); 00389 00390 if (config) { 00391 if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) { 00392 enabled = ast_true(enabled_value); 00393 } 00394 if ((interval_value = ast_variable_retrieve(config, "general", "refreshinterval"))) { 00395 if (sscanf(interval_value, "%d", &interval) < 1) 00396 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", interval_value); 00397 else if (interval < 0) 00398 ast_log(LOG_WARNING, "Invalid refresh interval '%d' specified, using default\n", interval); 00399 else 00400 refresh_interval = interval; 00401 } 00402 ast_config_destroy(config); 00403 } 00404 00405 if (enabled && refresh_interval) 00406 ast_log(LOG_NOTICE, "Managed DNS entries will be refreshed every %d seconds.\n", refresh_interval); 00407 00408 /* if this reload enabled the manager, create the background thread 00409 if it does not exist */ 00410 if (enabled) { 00411 if (!was_enabled && (refresh_thread == AST_PTHREADT_NULL)) { 00412 if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) { 00413 ast_log(LOG_ERROR, "Unable to start refresh thread.\n"); 00414 } 00415 } 00416 /* make a background refresh happen right away */ 00417 refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1); 00418 res = 0; 00419 } 00420 /* if this reload disabled the manager and there is a background thread, 00421 kill it */ 00422 else if (!enabled && was_enabled && (refresh_thread != AST_PTHREADT_NULL)) { 00423 /* wake up the thread so it will exit */ 00424 pthread_cancel(refresh_thread); 00425 pthread_kill(refresh_thread, SIGURG); 00426 pthread_join(refresh_thread, NULL); 00427 refresh_thread = AST_PTHREADT_NULL; 00428 res = 0; 00429 } 00430 else 00431 res = 0; 00432 00433 ast_mutex_unlock(&refresh_lock); 00434 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: DNSmgr\r\nStatus: %s\r/nMessage: DNSmgr reload Requested\r\n", enabled ? "Enabled" : "Disabled"); 00435 00436 return res; 00437 }
static char* handle_cli_refresh | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 273 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.
00274 { 00275 struct refresh_info info = { 00276 .entries = &entry_list, 00277 .verbose = 1, 00278 }; 00279 switch (cmd) { 00280 case CLI_INIT: 00281 e->command = "dnsmgr refresh"; 00282 e->usage = 00283 "Usage: dnsmgr refresh [pattern]\n" 00284 " Peforms an immediate refresh of the managed DNS entries.\n" 00285 " Optional regular expression pattern is used to filter the entries to refresh.\n"; 00286 return NULL; 00287 case CLI_GENERATE: 00288 return NULL; 00289 } 00290 00291 if (!enabled) { 00292 ast_cli(a->fd, "DNS Manager is disabled.\n"); 00293 return 0; 00294 } 00295 00296 if (a->argc > 3) { 00297 return CLI_SHOWUSAGE; 00298 } 00299 00300 if (a->argc == 3) { 00301 if (regcomp(&info.filter, a->argv[2], REG_EXTENDED | REG_NOSUB)) { 00302 return CLI_SHOWUSAGE; 00303 } else { 00304 info.regex_present = 1; 00305 } 00306 } 00307 00308 refresh_list(&info); 00309 00310 if (info.regex_present) { 00311 regfree(&info.filter); 00312 } 00313 00314 return CLI_SUCCESS; 00315 }
static char* handle_cli_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 254 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.
00255 { 00256 switch (cmd) { 00257 case CLI_INIT: 00258 e->command = "dnsmgr reload"; 00259 e->usage = 00260 "Usage: dnsmgr reload\n" 00261 " Reloads the DNS manager configuration.\n"; 00262 return NULL; 00263 case CLI_GENERATE: 00264 return NULL; 00265 } 00266 if (a->argc > 2) 00267 return CLI_SHOWUSAGE; 00268 00269 do_reload(0); 00270 return CLI_SUCCESS; 00271 }
static char* handle_cli_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 317 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.
00318 { 00319 int count = 0; 00320 struct ast_dnsmgr_entry *entry; 00321 switch (cmd) { 00322 case CLI_INIT: 00323 e->command = "dnsmgr status"; 00324 e->usage = 00325 "Usage: dnsmgr status\n" 00326 " Displays the DNS manager status.\n"; 00327 return NULL; 00328 case CLI_GENERATE: 00329 return NULL; 00330 } 00331 00332 if (a->argc > 2) 00333 return CLI_SHOWUSAGE; 00334 00335 ast_cli(a->fd, "DNS Manager: %s\n", enabled ? "enabled" : "disabled"); 00336 ast_cli(a->fd, "Refresh Interval: %d seconds\n", refresh_interval); 00337 AST_RWLIST_RDLOCK(&entry_list); 00338 AST_RWLIST_TRAVERSE(&entry_list, entry, list) 00339 count++; 00340 AST_RWLIST_UNLOCK(&entry_list); 00341 ast_cli(a->fd, "Number of entries: %d\n", count); 00342 00343 return CLI_SUCCESS; 00344 }
static int refresh_list | ( | const void * | data | ) | [static] |
Definition at line 216 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().
00217 { 00218 struct refresh_info *info = (struct refresh_info *)data; 00219 struct ast_dnsmgr_entry *entry; 00220 00221 /* if a refresh or reload is already in progress, exit now */ 00222 if (ast_mutex_trylock(&refresh_lock)) { 00223 if (info->verbose) 00224 ast_log(LOG_WARNING, "DNS Manager refresh already in progress.\n"); 00225 return -1; 00226 } 00227 00228 ast_verb(3, "Refreshing DNS lookups.\n"); 00229 AST_RWLIST_RDLOCK(info->entries); 00230 AST_RWLIST_TRAVERSE(info->entries, entry, list) { 00231 if (info->regex_present && regexec(&info->filter, entry->name, 0, NULL, 0)) 00232 continue; 00233 00234 dnsmgr_refresh(entry, info->verbose); 00235 } 00236 AST_RWLIST_UNLOCK(info->entries); 00237 00238 ast_mutex_unlock(&refresh_lock); 00239 00240 /* automatically reschedule based on the interval */ 00241 return refresh_interval * 1000; 00242 }
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 346 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 83 of file dnsmgr.c.
Referenced by dnsmgr_start_refresh(), and do_reload().
int refresh_interval [static] |
Definition at line 74 of file dnsmgr.c.
Referenced by do_reload(), handle_cli_status(), and refresh_list().
ast_mutex_t refresh_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
int refresh_sched = -1 [static] |
pthread_t refresh_thread = AST_PTHREADT_NULL [static] |
struct sched_context* sched [static] |