Background DNS update manager. More...
#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 | 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. | |
| struct 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. | |
| AST_MUTEX_DEFINE_STATIC (refresh_lock) | |
| static | AST_RWLIST_HEAD_STATIC (entry_list, ast_dnsmgr_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 = AST_CLI_DEFINE(handle_cli_refresh, "Performs an immediate refresh") |
| static struct ast_cli_entry | cli_reload = AST_CLI_DEFINE(handle_cli_reload, "Reloads the DNS manager configuration") |
| static struct ast_cli_entry | cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the DNS manager status") |
| static int | enabled |
| static struct refresh_info | master_refresh_info |
| static int | refresh_interval |
| static int | refresh_sched = -1 |
| static pthread_t | refresh_thread = AST_PTHREADT_NULL |
| static struct sched_context * | sched |
Background DNS update manager.
Definition in file dnsmgr.c.
| #define REFRESH_DEFAULT 300 |
Definition at line 71 of file dnsmgr.c.
Referenced by do_reload().
| 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 | |||
| ) | [read] |
Allocate a new DNS manager entry.
| name | the hostname | |
| result | where the DNS manager should store the IP address as it refreshes it. it. |
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.
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::lock, 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 |
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 126 of file dnsmgr.c.
References ast_dnsmgr_get(), ast_get_ip_or_srv(), ast_strlen_zero(), ast_verb, and enabled.
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, and ast_dnsmgr_entry::lock.
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 }
| AST_MUTEX_DEFINE_STATIC | ( | refresh_lock | ) |
| static AST_RWLIST_HEAD_STATIC | ( | entry_list | , | |
| ast_dnsmgr_entry | ||||
| ) | [static] |
| 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, 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::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, and refresh_list().
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(), and ast_sched_wait().
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_STATUS_FILEUNCHANGED, do_refresh(), enabled, EVENT_FLAG_SYSTEM, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, master_refresh_info, REFRESH_DEFAULT, refresh_interval, and refresh_list().
Referenced by dnsmgr_init(), dnsmgr_reload(), and handle_cli_reload().
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, "%30d", &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, 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, LOG_WARNING, 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 = AST_CLI_DEFINE(handle_cli_refresh, "Performs an immediate refresh") [static] |
Definition at line 347 of file dnsmgr.c.
Referenced by dnsmgr_init().
struct ast_cli_entry cli_reload = AST_CLI_DEFINE(handle_cli_reload, "Reloads the DNS manager configuration") [static] |
Definition at line 346 of file dnsmgr.c.
Referenced by dnsmgr_init().
struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the DNS manager status") [static] |
Definition at line 348 of file dnsmgr.c.
Referenced by dnsmgr_init().
int enabled [static] |
Definition at line 73 of file dnsmgr.c.
Referenced by ast_dnsmgr_lookup(), do_reload(), handle_cli_refresh(), and handle_cli_status().
struct refresh_info master_refresh_info [static] |
{
.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().
int refresh_sched = -1 [static] |
pthread_t refresh_thread = AST_PTHREADT_NULL [static] |
struct sched_context* sched [static] |
1.6.1