#include "asterisk.h"
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <resolv.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.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/logger.h"
#include "asterisk/sched.h"
#include "asterisk/options.h"
#include "asterisk/cli.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 in_addr *result) |
int | ast_dnsmgr_lookup (const char *name, struct in_addr *result, struct ast_dnsmgr_entry **dnsmgr) |
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) |
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 int | handle_cli_refresh (int fd, int argc, char *argv[]) |
static int | handle_cli_reload (int fd, int argc, char *argv[]) |
static int | handle_cli_status (int fd, int argc, char *argv[]) |
static int | refresh_list (const void *data) |
Variables | |
static struct ast_cli_entry | cli_refresh |
static struct ast_cli_entry | cli_reload |
static struct ast_cli_entry | cli_status |
static int | enabled |
static struct refresh_info | master_refresh_info |
static int | refresh_interval |
static ast_mutex_t | refresh_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
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 194 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().
00195 { 00196 int changed; 00197 00198 ast_mutex_lock(&entry->lock); 00199 00200 changed = entry->changed; 00201 entry->changed = 0; 00202 00203 ast_mutex_unlock(&entry->lock); 00204 00205 return changed; 00206 }
struct ast_dnsmgr_entry* ast_dnsmgr_get | ( | const char * | name, | |
struct in_addr * | result | |||
) |
Definition at line 87 of file dnsmgr.c.
References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_mutex_init(), ast_strlen_zero(), ast_dnsmgr_entry::list, and ast_dnsmgr_entry::result.
Referenced by ast_dnsmgr_lookup().
00088 { 00089 struct ast_dnsmgr_entry *entry; 00090 00091 if (!result || ast_strlen_zero(name) || !(entry = ast_calloc(1, sizeof(*entry) + strlen(name)))) 00092 return NULL; 00093 00094 entry->result = result; 00095 ast_mutex_init(&entry->lock); 00096 strcpy(entry->name, name); 00097 00098 AST_LIST_LOCK(&entry_list); 00099 AST_LIST_INSERT_HEAD(&entry_list, entry, list); 00100 AST_LIST_UNLOCK(&entry_list); 00101 00102 return entry; 00103 }
int ast_dnsmgr_lookup | ( | const char * | name, | |
struct in_addr * | result, | |||
struct ast_dnsmgr_entry ** | dnsmgr | |||
) |
Definition at line 120 of file dnsmgr.c.
References ahp, ast_dnsmgr_get(), ast_gethostbyname(), ast_strlen_zero(), ast_verbose(), enabled, hp, option_verbose, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_4.
Referenced by build_peer(), and iax2_register().
00121 { 00122 struct ast_hostent ahp; 00123 struct hostent *hp; 00124 00125 if (ast_strlen_zero(name) || !result || !dnsmgr) 00126 return -1; 00127 00128 if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name)) 00129 return 0; 00130 00131 if (option_verbose > 3) 00132 ast_verbose(VERBOSE_PREFIX_4 "doing dnsmgr_lookup for '%s'\n", name); 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)) 00137 return 0; 00138 00139 /* do a lookup now but add a manager so it will automagically get updated in the background */ 00140 if ((hp = ast_gethostbyname(name, &ahp))) 00141 memcpy(result, hp->h_addr, sizeof(result)); 00142 00143 /* if dnsmgr is not enable don't bother adding an entry */ 00144 if (!enabled) 00145 return 0; 00146 00147 if (option_verbose > 2) 00148 ast_verbose(VERBOSE_PREFIX_2 "adding dns manager for '%s'\n", name); 00149 *dnsmgr = ast_dnsmgr_get(name, result); 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 186 of file dnsmgr.c.
References dnsmgr_refresh().
Referenced by iax2_do_register().
00187 { 00188 return dnsmgr_refresh(entry, 0); 00189 }
void ast_dnsmgr_release | ( | struct ast_dnsmgr_entry * | entry | ) |
Definition at line 105 of file dnsmgr.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_verbose(), free, ast_dnsmgr_entry::list, ast_dnsmgr_entry::lock, ast_dnsmgr_entry::name, option_verbose, and VERBOSE_PREFIX_4.
Referenced by delete_users(), and peer_destructor().
00106 { 00107 if (!entry) 00108 return; 00109 00110 AST_LIST_LOCK(&entry_list); 00111 AST_LIST_REMOVE(&entry_list, entry, list); 00112 AST_LIST_UNLOCK(&entry_list); 00113 if (option_verbose > 3) 00114 ast_verbose(VERBOSE_PREFIX_4 "removing dns manager for '%s'\n", entry->name); 00115 00116 ast_mutex_destroy(&entry->lock); 00117 free(entry); 00118 }
int dnsmgr_init | ( | void | ) |
Provided by dnsmgr.c
Definition at line 338 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().
00339 { 00340 if (!(sched = sched_context_create())) { 00341 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 00342 return -1; 00343 } 00344 ast_cli_register(&cli_reload); 00345 ast_cli_register(&cli_status); 00346 ast_cli_register(&cli_refresh); 00347 return do_reload(1); 00348 }
static int dnsmgr_refresh | ( | struct ast_dnsmgr_entry * | entry, | |
int | verbose | |||
) | [static] |
Definition at line 156 of file dnsmgr.c.
References ahp, ast_copy_string(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_dnsmgr_entry::changed, hp, ast_dnsmgr_entry::lock, LOG_NOTICE, ast_dnsmgr_entry::name, option_verbose, ast_dnsmgr_entry::result, and VERBOSE_PREFIX_2.
Referenced by ast_dnsmgr_refresh(), and refresh_list().
00157 { 00158 struct ast_hostent ahp; 00159 struct hostent *hp; 00160 char iabuf[INET_ADDRSTRLEN]; 00161 char iabuf2[INET_ADDRSTRLEN]; 00162 struct in_addr tmp; 00163 int changed = 0; 00164 00165 ast_mutex_lock(&entry->lock); 00166 if (verbose && (option_verbose > 2)) 00167 ast_verbose(VERBOSE_PREFIX_2 "refreshing '%s'\n", entry->name); 00168 00169 if ((hp = ast_gethostbyname(entry->name, &ahp))) { 00170 /* check to see if it has changed, do callback if requested (where de callback is defined ????) */ 00171 memcpy(&tmp, hp->h_addr, sizeof(tmp)); 00172 if (tmp.s_addr != entry->result->s_addr) { 00173 ast_copy_string(iabuf, ast_inet_ntoa(*entry->result), sizeof(iabuf)); 00174 ast_copy_string(iabuf2, ast_inet_ntoa(tmp), sizeof(iabuf2)); 00175 ast_log(LOG_NOTICE, "host '%s' changed from %s to %s\n", 00176 entry->name, iabuf, iabuf2); 00177 memcpy(entry->result, hp->h_addr, sizeof(entry->result)); 00178 changed = entry->changed = 1; 00179 } 00180 00181 } 00182 ast_mutex_unlock(&entry->lock); 00183 return changed; 00184 }
int dnsmgr_reload | ( | void | ) |
Provided by dnsmgr.c
Definition at line 350 of file dnsmgr.c.
References do_reload().
00351 { 00352 return do_reload(0); 00353 }
void dnsmgr_start_refresh | ( | void | ) |
Provided by dnsmgr.c
Definition at line 248 of file dnsmgr.c.
References ast_sched_add_variable(), AST_SCHED_DEL, master_refresh_info, refresh_list(), and sched.
Referenced by main().
00249 { 00250 if (refresh_sched > -1) { 00251 AST_SCHED_DEL(sched, refresh_sched); 00252 refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1); 00253 } 00254 }
static void* do_refresh | ( | void * | data | ) | [static] |
Definition at line 208 of file dnsmgr.c.
References ast_sched_runq(), ast_sched_wait(), and sched.
Referenced by do_reload().
00209 { 00210 for (;;) { 00211 pthread_testcancel(); 00212 usleep((ast_sched_wait(sched)*1000)); 00213 pthread_testcancel(); 00214 ast_sched_runq(sched); 00215 } 00216 return NULL; 00217 }
static int do_reload | ( | int | loading | ) | [static] |
Definition at line 355 of file dnsmgr.c.
References ast_config_destroy(), ast_config_load(), 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, do_refresh(), enabled, LOG_ERROR, LOG_NOTICE, LOG_WARNING, master_refresh_info, REFRESH_DEFAULT, refresh_interval, refresh_list(), and sched.
00356 { 00357 struct ast_config *config; 00358 const char *interval_value; 00359 const char *enabled_value; 00360 int interval; 00361 int was_enabled; 00362 int res = -1; 00363 00364 /* ensure that no refresh cycles run while the reload is in progress */ 00365 ast_mutex_lock(&refresh_lock); 00366 00367 /* reset defaults in preparation for reading config file */ 00368 refresh_interval = REFRESH_DEFAULT; 00369 was_enabled = enabled; 00370 enabled = 0; 00371 00372 AST_SCHED_DEL(sched, refresh_sched); 00373 00374 if ((config = ast_config_load("dnsmgr.conf"))) { 00375 if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) { 00376 enabled = ast_true(enabled_value); 00377 } 00378 if ((interval_value = ast_variable_retrieve(config, "general", "refreshinterval"))) { 00379 if (sscanf(interval_value, "%30d", &interval) < 1) 00380 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", interval_value); 00381 else if (interval < 0) 00382 ast_log(LOG_WARNING, "Invalid refresh interval '%d' specified, using default\n", interval); 00383 else 00384 refresh_interval = interval; 00385 } 00386 ast_config_destroy(config); 00387 } 00388 00389 if (enabled && refresh_interval) 00390 ast_log(LOG_NOTICE, "Managed DNS entries will be refreshed every %d seconds.\n", refresh_interval); 00391 00392 /* if this reload enabled the manager, create the background thread 00393 if it does not exist */ 00394 if (enabled) { 00395 if (!was_enabled && (refresh_thread == AST_PTHREADT_NULL)) { 00396 if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) { 00397 ast_log(LOG_ERROR, "Unable to start refresh thread.\n"); 00398 } 00399 } 00400 /* make a background refresh happen right away */ 00401 refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1); 00402 res = 0; 00403 } 00404 /* if this reload disabled the manager and there is a background thread, 00405 kill it */ 00406 else if (!enabled && was_enabled && (refresh_thread != AST_PTHREADT_NULL)) { 00407 /* wake up the thread so it will exit */ 00408 pthread_cancel(refresh_thread); 00409 pthread_kill(refresh_thread, SIGURG); 00410 pthread_join(refresh_thread, NULL); 00411 refresh_thread = AST_PTHREADT_NULL; 00412 res = 0; 00413 } 00414 else 00415 res = 0; 00416 00417 ast_mutex_unlock(&refresh_lock); 00418 00419 return res; 00420 }
static int handle_cli_refresh | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 267 of file dnsmgr.c.
References ast_cli(), enabled, refresh_info::entries, refresh_info::filter, refresh_list(), refresh_info::regex_present, and RESULT_SHOWUSAGE.
00268 { 00269 struct refresh_info info = { 00270 .entries = &entry_list, 00271 .verbose = 1, 00272 }; 00273 00274 if(!enabled) { 00275 ast_cli(fd, "DNS Manager is disabled.\n"); 00276 return 0; 00277 } 00278 00279 if (argc > 3) 00280 return RESULT_SHOWUSAGE; 00281 00282 if (argc == 3) { 00283 if (regcomp(&info.filter, argv[2], REG_EXTENDED | REG_NOSUB)) 00284 return RESULT_SHOWUSAGE; 00285 else 00286 info.regex_present = 1; 00287 } 00288 00289 refresh_list(&info); 00290 00291 if (info.regex_present) 00292 regfree(&info.filter); 00293 00294 return 0; 00295 }
static int handle_cli_reload | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 258 of file dnsmgr.c.
References do_reload(), and RESULT_SHOWUSAGE.
00259 { 00260 if (argc > 2) 00261 return RESULT_SHOWUSAGE; 00262 00263 do_reload(0); 00264 return 0; 00265 }
static int handle_cli_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 297 of file dnsmgr.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, enabled, ast_dnsmgr_entry::list, refresh_interval, and RESULT_SHOWUSAGE.
00298 { 00299 int count = 0; 00300 struct ast_dnsmgr_entry *entry; 00301 00302 if (argc > 2) 00303 return RESULT_SHOWUSAGE; 00304 00305 ast_cli(fd, "DNS Manager: %s\n", enabled ? "enabled" : "disabled"); 00306 ast_cli(fd, "Refresh Interval: %d seconds\n", refresh_interval); 00307 AST_LIST_LOCK(&entry_list); 00308 AST_LIST_TRAVERSE(&entry_list, entry, list) 00309 count++; 00310 AST_LIST_UNLOCK(&entry_list); 00311 ast_cli(fd, "Number of entries: %d\n", count); 00312 00313 return 0; 00314 }
static int refresh_list | ( | const void * | data | ) | [static] |
Definition at line 219 of file dnsmgr.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_verbose(), dnsmgr_refresh(), refresh_info::entries, refresh_info::filter, ast_dnsmgr_entry::list, LOG_WARNING, ast_dnsmgr_entry::name, option_verbose, refresh_interval, refresh_info::regex_present, refresh_info::verbose, and VERBOSE_PREFIX_2.
Referenced by dnsmgr_start_refresh(), do_reload(), and handle_cli_refresh().
00220 { 00221 struct refresh_info *info = (struct refresh_info *)data; 00222 struct ast_dnsmgr_entry *entry; 00223 00224 /* if a refresh or reload is already in progress, exit now */ 00225 if (ast_mutex_trylock(&refresh_lock)) { 00226 if (info->verbose) 00227 ast_log(LOG_WARNING, "DNS Manager refresh already in progress.\n"); 00228 return -1; 00229 } 00230 00231 if (option_verbose > 2) 00232 ast_verbose(VERBOSE_PREFIX_2 "Refreshing DNS lookups.\n"); 00233 AST_LIST_LOCK(info->entries); 00234 AST_LIST_TRAVERSE(info->entries, entry, list) { 00235 if (info->regex_present && regexec(&info->filter, entry->name, 0, NULL, 0)) 00236 continue; 00237 00238 dnsmgr_refresh(entry, info->verbose); 00239 } 00240 AST_LIST_UNLOCK(info->entries); 00241 00242 ast_mutex_unlock(&refresh_lock); 00243 00244 /* automatically reschedule based on the interval */ 00245 return refresh_interval * 1000; 00246 }
struct ast_cli_entry cli_refresh [static] |
struct ast_cli_entry cli_reload [static] |
Definition at line 316 of file dnsmgr.c.
Referenced by dnsmgr_init(), load_module(), and unload_module().
struct ast_cli_entry cli_status [static] |
struct refresh_info master_refresh_info [static] |
Initial value:
{ .entries = &entry_list, .verbose = 0, }
Definition at line 82 of file dnsmgr.c.
Referenced by dnsmgr_start_refresh(), and do_reload().
int refresh_interval [static] |
Definition at line 73 of file dnsmgr.c.
Referenced by do_reload(), handle_cli_status(), and refresh_list().
ast_mutex_t refresh_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
int refresh_sched = -1 [static] |
pthread_t refresh_thread = AST_PTHREADT_NULL [static] |
struct sched_context* sched [static] |