00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "asterisk.h"
00036
00037 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 377706 $")
00038
00039 #include "asterisk/_private.h"
00040 #include <regex.h>
00041 #include <signal.h>
00042
00043 #include "asterisk/dnsmgr.h"
00044 #include "asterisk/linkedlists.h"
00045 #include "asterisk/utils.h"
00046 #include "asterisk/config.h"
00047 #include "asterisk/sched.h"
00048 #include "asterisk/cli.h"
00049 #include "asterisk/manager.h"
00050 #include "asterisk/acl.h"
00051
00052 static struct ast_sched_context *sched;
00053 static int refresh_sched = -1;
00054 static pthread_t refresh_thread = AST_PTHREADT_NULL;
00055
00056 struct ast_dnsmgr_entry {
00057
00058 struct ast_sockaddr *result;
00059
00060 char *service;
00061
00062 unsigned int family;
00063
00064 unsigned int changed:1;
00065
00066 void *data;
00067
00068 dns_update_func update_func;
00069 ast_mutex_t lock;
00070 AST_RWLIST_ENTRY(ast_dnsmgr_entry) list;
00071
00072 char name[1];
00073 };
00074
00075 static AST_RWLIST_HEAD_STATIC(entry_list, ast_dnsmgr_entry);
00076
00077 AST_MUTEX_DEFINE_STATIC(refresh_lock);
00078
00079 #define REFRESH_DEFAULT 300
00080
00081 static int enabled;
00082 static int refresh_interval;
00083
00084 struct refresh_info {
00085 struct entry_list *entries;
00086 int verbose;
00087 unsigned int regex_present:1;
00088 regex_t filter;
00089 };
00090
00091 static struct refresh_info master_refresh_info = {
00092 .entries = &entry_list,
00093 .verbose = 0,
00094 };
00095
00096 struct ast_dnsmgr_entry *ast_dnsmgr_get_family(const char *name, struct ast_sockaddr *result, const char *service, unsigned int family)
00097 {
00098 struct ast_dnsmgr_entry *entry;
00099 int total_size = sizeof(*entry) + strlen(name) + (service ? strlen(service) + 1 : 0);
00100
00101 if (!result || ast_strlen_zero(name) || !(entry = ast_calloc(1, total_size))) {
00102 return NULL;
00103 }
00104
00105 entry->result = result;
00106 ast_mutex_init(&entry->lock);
00107 strcpy(entry->name, name);
00108 if (service) {
00109 entry->service = ((char *) entry) + sizeof(*entry) + strlen(name);
00110 strcpy(entry->service, service);
00111 }
00112 entry->family = family;
00113
00114 AST_RWLIST_WRLOCK(&entry_list);
00115 AST_RWLIST_INSERT_HEAD(&entry_list, entry, list);
00116 AST_RWLIST_UNLOCK(&entry_list);
00117
00118 return entry;
00119 }
00120
00121 struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct ast_sockaddr *result, const char *service)
00122 {
00123 return ast_dnsmgr_get_family(name, result, service, 0);
00124 }
00125
00126 void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry)
00127 {
00128 if (!entry) {
00129 return;
00130 }
00131
00132 AST_RWLIST_WRLOCK(&entry_list);
00133 AST_RWLIST_REMOVE(&entry_list, entry, list);
00134 AST_RWLIST_UNLOCK(&entry_list);
00135 ast_debug(6, "removing dns manager for '%s'\n", entry->name);
00136
00137 ast_mutex_destroy(&entry->lock);
00138 ast_free(entry);
00139 }
00140
00141 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)
00142 {
00143 unsigned int family;
00144
00145 if (ast_strlen_zero(name) || !result || !dnsmgr) {
00146 return -1;
00147 }
00148
00149 if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name)) {
00150 return 0;
00151 }
00152
00153
00154 family = result->ss.ss_family;
00155
00156
00157
00158
00159
00160 if (ast_sockaddr_parse(result, name, PARSE_PORT_FORBID)) {
00161 return 0;
00162 }
00163
00164 ast_debug(6, "doing dnsmgr_lookup for '%s'\n", name);
00165
00166
00167 ast_get_ip_or_srv(result, name, service);
00168
00169
00170 if (!enabled) {
00171 return 0;
00172 }
00173
00174 ast_debug(6, "adding dns manager for '%s'\n", name);
00175 *dnsmgr = ast_dnsmgr_get_family(name, result, service, family);
00176 (*dnsmgr)->update_func = func;
00177 (*dnsmgr)->data = data;
00178 return !*dnsmgr;
00179 }
00180
00181 int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service)
00182 {
00183 return internal_dnsmgr_lookup(name, result, dnsmgr, service, NULL, NULL);
00184 }
00185
00186 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)
00187 {
00188 return internal_dnsmgr_lookup(name, result, dnsmgr, service, func, data);
00189 }
00190
00191
00192
00193
00194 static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose)
00195 {
00196 struct ast_sockaddr tmp = { .len = 0, };
00197 int changed = 0;
00198
00199 ast_mutex_lock(&entry->lock);
00200
00201 ast_debug(6, "refreshing '%s'\n", entry->name);
00202
00203 tmp.ss.ss_family = entry->family;
00204 if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service)) {
00205 if (!ast_sockaddr_port(&tmp)) {
00206 ast_sockaddr_set_port(&tmp, ast_sockaddr_port(entry->result));
00207 }
00208 if (ast_sockaddr_cmp(&tmp, entry->result)) {
00209 const char *old_addr = ast_strdupa(ast_sockaddr_stringify(entry->result));
00210 const char *new_addr = ast_strdupa(ast_sockaddr_stringify(&tmp));
00211
00212 if (entry->update_func) {
00213 entry->update_func(entry->result, &tmp, entry->data);
00214 } else {
00215 ast_log(LOG_NOTICE, "dnssrv: host '%s' changed from %s to %s\n",
00216 entry->name, old_addr, new_addr);
00217
00218 ast_sockaddr_copy(entry->result, &tmp);
00219 changed = entry->changed = 1;
00220 }
00221 }
00222 }
00223
00224 ast_mutex_unlock(&entry->lock);
00225
00226 return changed;
00227 }
00228
00229 int ast_dnsmgr_refresh(struct ast_dnsmgr_entry *entry)
00230 {
00231 return dnsmgr_refresh(entry, 0);
00232 }
00233
00234
00235
00236
00237 int ast_dnsmgr_changed(struct ast_dnsmgr_entry *entry)
00238 {
00239 int changed;
00240
00241 ast_mutex_lock(&entry->lock);
00242
00243 changed = entry->changed;
00244 entry->changed = 0;
00245
00246 ast_mutex_unlock(&entry->lock);
00247
00248 return changed;
00249 }
00250
00251 static void *do_refresh(void *data)
00252 {
00253 for (;;) {
00254 pthread_testcancel();
00255 usleep((ast_sched_wait(sched)*1000));
00256 pthread_testcancel();
00257 ast_sched_runq(sched);
00258 }
00259 return NULL;
00260 }
00261
00262 static int refresh_list(const void *data)
00263 {
00264 struct refresh_info *info = (struct refresh_info *)data;
00265 struct ast_dnsmgr_entry *entry;
00266
00267
00268 if (ast_mutex_trylock(&refresh_lock)) {
00269 if (info->verbose) {
00270 ast_log(LOG_WARNING, "DNS Manager refresh already in progress.\n");
00271 }
00272 return -1;
00273 }
00274
00275 ast_debug(6, "Refreshing DNS lookups.\n");
00276 AST_RWLIST_RDLOCK(info->entries);
00277 AST_RWLIST_TRAVERSE(info->entries, entry, list) {
00278 if (info->regex_present && regexec(&info->filter, entry->name, 0, NULL, 0)) {
00279 continue;
00280 }
00281
00282 dnsmgr_refresh(entry, info->verbose);
00283 }
00284 AST_RWLIST_UNLOCK(info->entries);
00285
00286 ast_mutex_unlock(&refresh_lock);
00287
00288
00289 return refresh_interval * 1000;
00290 }
00291
00292 void dnsmgr_start_refresh(void)
00293 {
00294 if (refresh_sched > -1) {
00295 AST_SCHED_DEL(sched, refresh_sched);
00296 refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1);
00297 }
00298 }
00299
00300 static int do_reload(int loading);
00301
00302 static char *handle_cli_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00303 {
00304 switch (cmd) {
00305 case CLI_INIT:
00306 e->command = "dnsmgr reload";
00307 e->usage =
00308 "Usage: dnsmgr reload\n"
00309 " Reloads the DNS manager configuration.\n";
00310 return NULL;
00311 case CLI_GENERATE:
00312 return NULL;
00313 }
00314 if (a->argc > 2) {
00315 return CLI_SHOWUSAGE;
00316 }
00317
00318 do_reload(0);
00319 return CLI_SUCCESS;
00320 }
00321
00322 static char *handle_cli_refresh(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00323 {
00324 struct refresh_info info = {
00325 .entries = &entry_list,
00326 .verbose = 1,
00327 };
00328 switch (cmd) {
00329 case CLI_INIT:
00330 e->command = "dnsmgr refresh";
00331 e->usage =
00332 "Usage: dnsmgr refresh [pattern]\n"
00333 " Peforms an immediate refresh of the managed DNS entries.\n"
00334 " Optional regular expression pattern is used to filter the entries to refresh.\n";
00335 return NULL;
00336 case CLI_GENERATE:
00337 return NULL;
00338 }
00339
00340 if (!enabled) {
00341 ast_cli(a->fd, "DNS Manager is disabled.\n");
00342 return 0;
00343 }
00344
00345 if (a->argc > 3) {
00346 return CLI_SHOWUSAGE;
00347 }
00348
00349 if (a->argc == 3) {
00350 if (regcomp(&info.filter, a->argv[2], REG_EXTENDED | REG_NOSUB)) {
00351 return CLI_SHOWUSAGE;
00352 } else {
00353 info.regex_present = 1;
00354 }
00355 }
00356
00357 refresh_list(&info);
00358
00359 if (info.regex_present) {
00360 regfree(&info.filter);
00361 }
00362
00363 return CLI_SUCCESS;
00364 }
00365
00366 static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00367 {
00368 int count = 0;
00369 struct ast_dnsmgr_entry *entry;
00370 switch (cmd) {
00371 case CLI_INIT:
00372 e->command = "dnsmgr status";
00373 e->usage =
00374 "Usage: dnsmgr status\n"
00375 " Displays the DNS manager status.\n";
00376 return NULL;
00377 case CLI_GENERATE:
00378 return NULL;
00379 }
00380
00381 if (a->argc > 2) {
00382 return CLI_SHOWUSAGE;
00383 }
00384
00385 ast_cli(a->fd, "DNS Manager: %s\n", enabled ? "enabled" : "disabled");
00386 ast_cli(a->fd, "Refresh Interval: %d seconds\n", refresh_interval);
00387 AST_RWLIST_RDLOCK(&entry_list);
00388 AST_RWLIST_TRAVERSE(&entry_list, entry, list)
00389 count++;
00390 AST_RWLIST_UNLOCK(&entry_list);
00391 ast_cli(a->fd, "Number of entries: %d\n", count);
00392
00393 return CLI_SUCCESS;
00394 }
00395
00396 static struct ast_cli_entry cli_reload = AST_CLI_DEFINE(handle_cli_reload, "Reloads the DNS manager configuration");
00397 static struct ast_cli_entry cli_refresh = AST_CLI_DEFINE(handle_cli_refresh, "Performs an immediate refresh");
00398 static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the DNS manager status");
00399
00400 static void dnsmgr_shutdown(void)
00401 {
00402 ast_cli_unregister(&cli_reload);
00403 ast_cli_unregister(&cli_status);
00404 ast_cli_unregister(&cli_refresh);
00405
00406
00407 ast_mutex_lock(&refresh_lock);
00408 if (refresh_thread != AST_PTHREADT_NULL) {
00409
00410 pthread_cancel(refresh_thread);
00411 pthread_kill(refresh_thread, SIGURG);
00412 pthread_join(refresh_thread, NULL);
00413 refresh_thread = AST_PTHREADT_NULL;
00414 }
00415 ast_mutex_unlock(&refresh_lock);
00416
00417 ast_sched_context_destroy(sched);
00418 }
00419
00420 int dnsmgr_init(void)
00421 {
00422 if (!(sched = ast_sched_context_create())) {
00423 ast_log(LOG_ERROR, "Unable to create schedule context.\n");
00424 return -1;
00425 }
00426 ast_cli_register(&cli_reload);
00427 ast_cli_register(&cli_status);
00428 ast_cli_register(&cli_refresh);
00429
00430 ast_register_atexit(dnsmgr_shutdown);
00431
00432 return do_reload(1);
00433 }
00434
00435 int dnsmgr_reload(void)
00436 {
00437 return do_reload(0);
00438 }
00439
00440 static int do_reload(int loading)
00441 {
00442 struct ast_config *config;
00443 struct ast_variable *v;
00444 struct ast_flags config_flags = { loading ? 0 : CONFIG_FLAG_FILEUNCHANGED };
00445 int interval;
00446 int was_enabled;
00447
00448 if ((config = ast_config_load2("dnsmgr.conf", "dnsmgr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
00449 return 0;
00450 }
00451
00452
00453 ast_mutex_lock(&refresh_lock);
00454
00455
00456 refresh_interval = REFRESH_DEFAULT;
00457 was_enabled = enabled;
00458 enabled = 0;
00459
00460 if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
00461 ast_mutex_unlock(&refresh_lock);
00462 return 0;
00463 }
00464
00465 AST_SCHED_DEL(sched, refresh_sched);
00466
00467 for (v = ast_variable_browse(config, "general"); v; v = v->next) {
00468 if (!strcasecmp(v->name, "enable")) {
00469 enabled = ast_true(v->value);
00470 } else if (!strcasecmp(v->name, "refreshinterval")) {
00471 if (sscanf(v->value, "%30d", &interval) < 1) {
00472 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
00473 } else if (interval < 0) {
00474 ast_log(LOG_WARNING, "Invalid refresh interval '%d' specified, using default\n", interval);
00475 } else {
00476 refresh_interval = interval;
00477 }
00478 }
00479 }
00480 ast_config_destroy(config);
00481
00482 if (enabled && refresh_interval) {
00483 ast_log(LOG_NOTICE, "Managed DNS entries will be refreshed every %d seconds.\n", refresh_interval);
00484 }
00485
00486
00487
00488 if (enabled) {
00489 if (!was_enabled && (refresh_thread == AST_PTHREADT_NULL)) {
00490 if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) {
00491 ast_log(LOG_ERROR, "Unable to start refresh thread.\n");
00492 }
00493 }
00494
00495 refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1);
00496
00497 } else if (!enabled && was_enabled && (refresh_thread != AST_PTHREADT_NULL)) {
00498
00499 pthread_cancel(refresh_thread);
00500 pthread_kill(refresh_thread, SIGURG);
00501 pthread_join(refresh_thread, NULL);
00502 refresh_thread = AST_PTHREADT_NULL;
00503 }
00504
00505 ast_mutex_unlock(&refresh_lock);
00506 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: DNSmgr\r\nStatus: %s\r/nMessage: DNSmgr reload Requested\r\n", enabled ? "Enabled" : "Disabled");
00507
00508 return 0;
00509 }