#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"
Include dependency graph for dnsmgr.c:
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. | |
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) |
static | AST_LIST_HEAD_STATIC (entry_list, ast_dnsmgr_entry) |
AST_MUTEX_DEFINE_STATIC (refresh_lock) | |
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 (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 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 197 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().
00198 { 00199 int changed; 00200 00201 ast_mutex_lock(&entry->lock); 00202 00203 changed = entry->changed; 00204 entry->changed = 0; 00205 00206 ast_mutex_unlock(&entry->lock); 00207 00208 return changed; 00209 }
struct ast_dnsmgr_entry* ast_dnsmgr_get | ( | const char * | name, | |
struct in_addr * | result | |||
) |
Definition at line 89 of file dnsmgr.c.
References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_mutex_init(), ast_strlen_zero(), and ast_dnsmgr_entry::result.
Referenced by ast_dnsmgr_lookup().
00090 { 00091 struct ast_dnsmgr_entry *entry; 00092 00093 if (!result || ast_strlen_zero(name) || !(entry = ast_calloc(1, sizeof(*entry) + strlen(name)))) 00094 return NULL; 00095 00096 entry->result = result; 00097 ast_mutex_init(&entry->lock); 00098 strcpy(entry->name, name); 00099 00100 AST_LIST_LOCK(&entry_list); 00101 AST_LIST_INSERT_HEAD(&entry_list, entry, list); 00102 AST_LIST_UNLOCK(&entry_list); 00103 00104 return entry; 00105 }
int ast_dnsmgr_lookup | ( | const char * | name, | |
struct in_addr * | result, | |||
struct ast_dnsmgr_entry ** | dnsmgr | |||
) |
Definition at line 122 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().
00123 { 00124 if (ast_strlen_zero(name) || !result || !dnsmgr) 00125 return -1; 00126 00127 if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name)) 00128 return 0; 00129 00130 if (option_verbose > 3) 00131 ast_verbose(VERBOSE_PREFIX_4 "doing dnsmgr_lookup for '%s'\n", name); 00132 00133 /* if it's actually an IP address and not a name, 00134 there's no need for a managed lookup */ 00135 if (inet_aton(name, result)) 00136 return 0; 00137 00138 /* if the manager is disabled, do a direct lookup and return the result, 00139 otherwise register a managed lookup for the name */ 00140 if (!enabled) { 00141 struct ast_hostent ahp; 00142 struct hostent *hp; 00143 00144 if ((hp = ast_gethostbyname(name, &ahp))) 00145 memcpy(result, hp->h_addr, sizeof(result)); 00146 return 0; 00147 } else { 00148 if (option_verbose > 2) 00149 ast_verbose(VERBOSE_PREFIX_2 "adding dns manager for '%s'\n", name); 00150 *dnsmgr = ast_dnsmgr_get(name, result); 00151 return !*dnsmgr; 00152 } 00153 }
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 189 of file dnsmgr.c.
References dnsmgr_refresh().
Referenced by iax2_do_register().
00190 { 00191 return dnsmgr_refresh(entry, 0); 00192 }
void ast_dnsmgr_release | ( | struct ast_dnsmgr_entry * | entry | ) |
Definition at line 107 of file dnsmgr.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_verbose(), free, ast_dnsmgr_entry::lock, option_verbose, and VERBOSE_PREFIX_4.
Referenced by delete_users(), and destroy_peer().
00108 { 00109 if (!entry) 00110 return; 00111 00112 AST_LIST_LOCK(&entry_list); 00113 AST_LIST_REMOVE(&entry_list, entry, list); 00114 AST_LIST_UNLOCK(&entry_list); 00115 if (option_verbose > 3) 00116 ast_verbose(VERBOSE_PREFIX_4 "removing dns manager for '%s'\n", entry->name); 00117 00118 ast_mutex_destroy(&entry->lock); 00119 free(entry); 00120 }
static AST_LIST_HEAD_STATIC | ( | entry_list | , | |
ast_dnsmgr_entry | ||||
) | [static] |
AST_MUTEX_DEFINE_STATIC | ( | refresh_lock | ) |
int dnsmgr_init | ( | void | ) |
Provided by dnsmgr.c
Definition at line 336 of file dnsmgr.c.
References ast_cli_register(), ast_log(), cli_reload, cli_status, do_reload(), LOG_ERROR, sched, and sched_context_create().
Referenced by main().
00337 { 00338 if (!(sched = sched_context_create())) { 00339 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 00340 return -1; 00341 } 00342 ast_cli_register(&cli_reload); 00343 ast_cli_register(&cli_status); 00344 return do_reload(1); 00345 }
static int dnsmgr_refresh | ( | struct ast_dnsmgr_entry * | entry, | |
int | verbose | |||
) | [static] |
Definition at line 158 of file dnsmgr.c.
References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_dnsmgr_entry::changed, hp, ast_dnsmgr_entry::last, ast_dnsmgr_entry::lock, LOG_NOTICE, option_verbose, ast_dnsmgr_entry::result, and VERBOSE_PREFIX_2.
Referenced by ast_dnsmgr_refresh(), and refresh_list().
00159 { 00160 struct ast_hostent ahp; 00161 struct hostent *hp; 00162 char iabuf[INET_ADDRSTRLEN]; 00163 char iabuf2[INET_ADDRSTRLEN]; 00164 struct in_addr tmp; 00165 int changed = 0; 00166 00167 ast_mutex_lock(&entry->lock); 00168 if (verbose && (option_verbose > 2)) 00169 ast_verbose(VERBOSE_PREFIX_2 "refreshing '%s'\n", entry->name); 00170 00171 if ((hp = ast_gethostbyname(entry->name, &ahp))) { 00172 /* check to see if it has changed, do callback if requested (where de callback is defined ????) */ 00173 memcpy(&tmp, hp->h_addr, sizeof(tmp)); 00174 if (tmp.s_addr != entry->last.s_addr) { 00175 ast_copy_string(iabuf, ast_inet_ntoa(entry->last), sizeof(iabuf)); 00176 ast_copy_string(iabuf2, ast_inet_ntoa(tmp), sizeof(iabuf2)); 00177 ast_log(LOG_NOTICE, "host '%s' changed from %s to %s\n", 00178 entry->name, iabuf, iabuf2); 00179 memcpy(entry->result, hp->h_addr, sizeof(entry->result)); 00180 memcpy(&entry->last, hp->h_addr, sizeof(entry->last)); 00181 changed = entry->changed = 1; 00182 } 00183 00184 } 00185 ast_mutex_unlock(&entry->lock); 00186 return changed; 00187 }
int dnsmgr_reload | ( | void | ) |
Provided by dnsmgr.c
Definition at line 347 of file dnsmgr.c.
References do_reload().
00348 { 00349 return do_reload(0); 00350 }
void dnsmgr_start_refresh | ( | void | ) |
Provided by dnsmgr.c
Definition at line 251 of file dnsmgr.c.
References ast_sched_add_variable(), ast_sched_del(), master_refresh_info, refresh_list(), and sched.
Referenced by main().
00252 { 00253 if (refresh_sched > -1) { 00254 ast_sched_del(sched, refresh_sched); 00255 refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1); 00256 } 00257 }
static void* do_refresh | ( | void * | data | ) | [static] |
Definition at line 211 of file dnsmgr.c.
References ast_sched_runq(), ast_sched_wait(), and sched.
Referenced by do_reload().
00212 { 00213 for (;;) { 00214 pthread_testcancel(); 00215 usleep((ast_sched_wait(sched)*1000)); 00216 pthread_testcancel(); 00217 ast_sched_runq(sched); 00218 } 00219 return NULL; 00220 }
static int do_reload | ( | int | loading | ) | [static] |
Definition at line 352 of file dnsmgr.c.
References ast_cli_register(), ast_cli_unregister(), 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(), cli_refresh, config, do_refresh(), enabled, LOG_ERROR, LOG_NOTICE, LOG_WARNING, master_refresh_info, REFRESH_DEFAULT, refresh_interval, refresh_list(), and sched.
00353 { 00354 struct ast_config *config; 00355 const char *interval_value; 00356 const char *enabled_value; 00357 int interval; 00358 int was_enabled; 00359 int res = -1; 00360 00361 /* ensure that no refresh cycles run while the reload is in progress */ 00362 ast_mutex_lock(&refresh_lock); 00363 00364 /* reset defaults in preparation for reading config file */ 00365 refresh_interval = REFRESH_DEFAULT; 00366 was_enabled = enabled; 00367 enabled = 0; 00368 00369 if (refresh_sched > -1) 00370 ast_sched_del(sched, refresh_sched); 00371 00372 if ((config = ast_config_load("dnsmgr.conf"))) { 00373 if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) { 00374 enabled = ast_true(enabled_value); 00375 } 00376 if ((interval_value = ast_variable_retrieve(config, "general", "refreshinterval"))) { 00377 if (sscanf(interval_value, "%d", &interval) < 1) 00378 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", interval_value); 00379 else if (interval < 0) 00380 ast_log(LOG_WARNING, "Invalid refresh interval '%d' specified, using default\n", interval); 00381 else 00382 refresh_interval = interval; 00383 } 00384 ast_config_destroy(config); 00385 } 00386 00387 if (enabled && refresh_interval) 00388 ast_log(LOG_NOTICE, "Managed DNS entries will be refreshed every %d seconds.\n", refresh_interval); 00389 00390 /* if this reload enabled the manager, create the background thread 00391 if it does not exist */ 00392 if (enabled) { 00393 if (!was_enabled && (refresh_thread == AST_PTHREADT_NULL)) { 00394 if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) { 00395 ast_log(LOG_ERROR, "Unable to start refresh thread.\n"); 00396 } 00397 ast_cli_register(&cli_refresh); 00398 } 00399 /* make a background refresh happen right away */ 00400 refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1); 00401 res = 0; 00402 } 00403 /* if this reload disabled the manager and there is a background thread, 00404 kill it */ 00405 else if (!enabled && was_enabled && (refresh_thread != AST_PTHREADT_NULL)) { 00406 /* wake up the thread so it will exit */ 00407 pthread_cancel(refresh_thread); 00408 pthread_kill(refresh_thread, SIGURG); 00409 pthread_join(refresh_thread, NULL); 00410 refresh_thread = AST_PTHREADT_NULL; 00411 ast_cli_unregister(&cli_refresh); 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 270 of file dnsmgr.c.
References refresh_info::entries, refresh_info::filter, refresh_list(), refresh_info::regex_present, and RESULT_SHOWUSAGE.
00271 { 00272 struct refresh_info info = { 00273 .entries = &entry_list, 00274 .verbose = 1, 00275 }; 00276 00277 if (argc > 3) 00278 return RESULT_SHOWUSAGE; 00279 00280 if (argc == 3) { 00281 if (regcomp(&info.filter, argv[2], REG_EXTENDED | REG_NOSUB)) 00282 return RESULT_SHOWUSAGE; 00283 else 00284 info.regex_present = 1; 00285 } 00286 00287 refresh_list(&info); 00288 00289 if (info.regex_present) 00290 regfree(&info.filter); 00291 00292 return 0; 00293 }
static int handle_cli_reload | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 261 of file dnsmgr.c.
References do_reload(), and RESULT_SHOWUSAGE.
00262 { 00263 if (argc > 2) 00264 return RESULT_SHOWUSAGE; 00265 00266 do_reload(0); 00267 return 0; 00268 }
static int handle_cli_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 295 of file dnsmgr.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, enabled, refresh_interval, and RESULT_SHOWUSAGE.
00296 { 00297 int count = 0; 00298 struct ast_dnsmgr_entry *entry; 00299 00300 if (argc > 2) 00301 return RESULT_SHOWUSAGE; 00302 00303 ast_cli(fd, "DNS Manager: %s\n", enabled ? "enabled" : "disabled"); 00304 ast_cli(fd, "Refresh Interval: %d seconds\n", refresh_interval); 00305 AST_LIST_LOCK(&entry_list); 00306 AST_LIST_TRAVERSE(&entry_list, entry, list) 00307 count++; 00308 AST_LIST_UNLOCK(&entry_list); 00309 ast_cli(fd, "Number of entries: %d\n", count); 00310 00311 return 0; 00312 }
static int refresh_list | ( | void * | data | ) | [static] |
Definition at line 222 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, LOG_WARNING, 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().
00223 { 00224 struct refresh_info *info = data; 00225 struct ast_dnsmgr_entry *entry; 00226 00227 /* if a refresh or reload is already in progress, exit now */ 00228 if (ast_mutex_trylock(&refresh_lock)) { 00229 if (info->verbose) 00230 ast_log(LOG_WARNING, "DNS Manager refresh already in progress.\n"); 00231 return -1; 00232 } 00233 00234 if (option_verbose > 2) 00235 ast_verbose(VERBOSE_PREFIX_2 "Refreshing DNS lookups.\n"); 00236 AST_LIST_LOCK(info->entries); 00237 AST_LIST_TRAVERSE(info->entries, entry, list) { 00238 if (info->regex_present && regexec(&info->filter, entry->name, 0, NULL, 0)) 00239 continue; 00240 00241 dnsmgr_refresh(entry, info->verbose); 00242 } 00243 AST_LIST_UNLOCK(info->entries); 00244 00245 ast_mutex_unlock(&refresh_lock); 00246 00247 /* automatically reschedule based on the interval */ 00248 return refresh_interval * 1000; 00249 }
struct ast_cli_entry cli_refresh [static] |
struct ast_cli_entry cli_reload [static] |
struct ast_cli_entry cli_status [static] |
struct refresh_info master_refresh_info [static] |
Initial value:
{ .entries = &entry_list, .verbose = 0, }
Definition at line 84 of file dnsmgr.c.
Referenced by dnsmgr_start_refresh(), and do_reload().
int refresh_interval [static] |
Definition at line 75 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] |