Fri Feb 19 17:13:07 2010

Asterisk developer's documentation


dnsmgr.c File Reference

Background DNS update manager. More...

#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_entryast_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_contextsched


Detailed Description

Background DNS update manager.

Author:
Kevin P. Fleming <kpfleming@digium.com>

Definition in file dnsmgr.c.


Define Documentation

#define REFRESH_DEFAULT   300

Definition at line 72 of file dnsmgr.c.

Referenced by do_reload().


Function Documentation

int ast_dnsmgr_changed ( struct ast_dnsmgr_entry entry  ) 

Check is see if a dnsmgr entry has changed.

Return values:
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 198 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().

00199 {
00200    int changed;
00201 
00202    ast_mutex_lock(&entry->lock);
00203 
00204    changed = entry->changed;
00205    entry->changed = 0;
00206 
00207    ast_mutex_unlock(&entry->lock);
00208    
00209    return changed;
00210 }

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(), ast_dnsmgr_entry::list, 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    memcpy(&entry->last, result, sizeof(entry->last));
00100 
00101    AST_LIST_LOCK(&entry_list);
00102    AST_LIST_INSERT_HEAD(&entry_list, entry, list);
00103    AST_LIST_UNLOCK(&entry_list);
00104 
00105    return entry;
00106 }

int ast_dnsmgr_lookup ( const char *  name,
struct in_addr *  result,
struct ast_dnsmgr_entry **  dnsmgr 
)

Definition at line 123 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().

00124 {
00125    struct ast_hostent ahp;
00126    struct hostent *hp;
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 (option_verbose > 3)
00135       ast_verbose(VERBOSE_PREFIX_4 "doing dnsmgr_lookup for '%s'\n", name);
00136 
00137    /* if it's actually an IP address and not a name,
00138       there's no need for a managed lookup */
00139    if (inet_aton(name, result))
00140       return 0;
00141 
00142    /* do a lookup now but add a manager so it will automagically get updated in the background */
00143    if ((hp = ast_gethostbyname(name, &ahp)))
00144       memcpy(result, hp->h_addr, sizeof(result));
00145    
00146    /* if dnsmgr is not enable don't bother adding an entry */
00147    if (!enabled)
00148       return 0;
00149    
00150    if (option_verbose > 2)
00151       ast_verbose(VERBOSE_PREFIX_2 "adding dns manager for '%s'\n", name);
00152    *dnsmgr = ast_dnsmgr_get(name, result);
00153    return !*dnsmgr;
00154 }

int ast_dnsmgr_refresh ( struct ast_dnsmgr_entry entry  ) 

Force a refresh of a dnsmgr entry.

Return values:
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 190 of file dnsmgr.c.

References dnsmgr_refresh().

Referenced by iax2_do_register().

00191 {
00192    return dnsmgr_refresh(entry, 0);
00193 }

void ast_dnsmgr_release ( struct ast_dnsmgr_entry entry  ) 

Definition at line 108 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().

00109 {
00110    if (!entry)
00111       return;
00112 
00113    AST_LIST_LOCK(&entry_list);
00114    AST_LIST_REMOVE(&entry_list, entry, list);
00115    AST_LIST_UNLOCK(&entry_list);
00116    if (option_verbose > 3)
00117       ast_verbose(VERBOSE_PREFIX_4 "removing dns manager for '%s'\n", entry->name);
00118 
00119    ast_mutex_destroy(&entry->lock);
00120    free(entry);
00121 }

int dnsmgr_init ( void   ) 

Provided by dnsmgr.c

Definition at line 342 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().

00343 {
00344    if (!(sched = sched_context_create())) {
00345       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
00346       return -1;
00347    }
00348    ast_cli_register(&cli_reload);
00349    ast_cli_register(&cli_status);
00350    ast_cli_register(&cli_refresh);
00351    return do_reload(1);
00352 }

static int dnsmgr_refresh ( struct ast_dnsmgr_entry entry,
int  verbose 
) [static]

Definition at line 159 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::last, 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().

00160 {
00161    struct ast_hostent ahp;
00162    struct hostent *hp;
00163    char iabuf[INET_ADDRSTRLEN];
00164    char iabuf2[INET_ADDRSTRLEN];
00165    struct in_addr tmp;
00166    int changed = 0;
00167         
00168    ast_mutex_lock(&entry->lock);
00169    if (verbose && (option_verbose > 2))
00170       ast_verbose(VERBOSE_PREFIX_2 "refreshing '%s'\n", entry->name);
00171 
00172    if ((hp = ast_gethostbyname(entry->name, &ahp))) {
00173       /* check to see if it has changed, do callback if requested (where de callback is defined ????) */
00174       memcpy(&tmp, hp->h_addr, sizeof(tmp));
00175       if (tmp.s_addr != entry->last.s_addr) {
00176          ast_copy_string(iabuf, ast_inet_ntoa(entry->last), sizeof(iabuf));
00177          ast_copy_string(iabuf2, ast_inet_ntoa(tmp), sizeof(iabuf2));
00178          ast_log(LOG_NOTICE, "host '%s' changed from %s to %s\n", 
00179             entry->name, iabuf, iabuf2);
00180          memcpy(entry->result, hp->h_addr, sizeof(entry->result));
00181          memcpy(&entry->last, hp->h_addr, sizeof(entry->last));
00182          changed = entry->changed = 1;
00183       } 
00184       
00185    }
00186    ast_mutex_unlock(&entry->lock);
00187    return changed;
00188 }

int dnsmgr_reload ( void   ) 

Provided by dnsmgr.c

Definition at line 354 of file dnsmgr.c.

References do_reload().

00355 {
00356    return do_reload(0);
00357 }

void dnsmgr_start_refresh ( void   ) 

Provided by dnsmgr.c

Definition at line 252 of file dnsmgr.c.

References ast_sched_add_variable(), AST_SCHED_DEL, master_refresh_info, refresh_list(), and sched.

Referenced by main().

00253 {
00254    if (refresh_sched > -1) {
00255       AST_SCHED_DEL(sched, refresh_sched);
00256       refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1);
00257    }
00258 }

static void* do_refresh ( void *  data  )  [static]

Definition at line 212 of file dnsmgr.c.

References ast_sched_runq(), ast_sched_wait(), and sched.

Referenced by do_reload().

00213 {
00214    for (;;) {
00215       pthread_testcancel();
00216       usleep((ast_sched_wait(sched)*1000));
00217       pthread_testcancel();
00218       ast_sched_runq(sched);
00219    }
00220    return NULL;
00221 }

static int do_reload ( int  loading  )  [static]

Definition at line 359 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.

00360 {
00361    struct ast_config *config;
00362    const char *interval_value;
00363    const char *enabled_value;
00364    int interval;
00365    int was_enabled;
00366    int res = -1;
00367 
00368    /* ensure that no refresh cycles run while the reload is in progress */
00369    ast_mutex_lock(&refresh_lock);
00370 
00371    /* reset defaults in preparation for reading config file */
00372    refresh_interval = REFRESH_DEFAULT;
00373    was_enabled = enabled;
00374    enabled = 0;
00375 
00376    AST_SCHED_DEL(sched, refresh_sched);
00377 
00378    if ((config = ast_config_load("dnsmgr.conf"))) {
00379       if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
00380          enabled = ast_true(enabled_value);
00381       }
00382       if ((interval_value = ast_variable_retrieve(config, "general", "refreshinterval"))) {
00383          if (sscanf(interval_value, "%30d", &interval) < 1)
00384             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", interval_value);
00385          else if (interval < 0)
00386             ast_log(LOG_WARNING, "Invalid refresh interval '%d' specified, using default\n", interval);
00387          else
00388             refresh_interval = interval;
00389       }
00390       ast_config_destroy(config);
00391    }
00392 
00393    if (enabled && refresh_interval)
00394       ast_log(LOG_NOTICE, "Managed DNS entries will be refreshed every %d seconds.\n", refresh_interval);
00395 
00396    /* if this reload enabled the manager, create the background thread
00397       if it does not exist */
00398    if (enabled) {
00399       if (!was_enabled && (refresh_thread == AST_PTHREADT_NULL)) {
00400          if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) {
00401             ast_log(LOG_ERROR, "Unable to start refresh thread.\n");
00402          }
00403       }
00404       /* make a background refresh happen right away */
00405       refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1);
00406       res = 0;
00407    }
00408    /* if this reload disabled the manager and there is a background thread,
00409       kill it */
00410    else if (!enabled && was_enabled && (refresh_thread != AST_PTHREADT_NULL)) {
00411       /* wake up the thread so it will exit */
00412       pthread_cancel(refresh_thread);
00413       pthread_kill(refresh_thread, SIGURG);
00414       pthread_join(refresh_thread, NULL);
00415       refresh_thread = AST_PTHREADT_NULL;
00416       res = 0;
00417    }
00418    else
00419       res = 0;
00420 
00421    ast_mutex_unlock(&refresh_lock);
00422 
00423    return res;
00424 }

static int handle_cli_refresh ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 271 of file dnsmgr.c.

References ast_cli(), enabled, refresh_info::entries, refresh_info::filter, refresh_list(), refresh_info::regex_present, and RESULT_SHOWUSAGE.

00272 {
00273    struct refresh_info info = {
00274       .entries = &entry_list,
00275       .verbose = 1,
00276    };
00277 
00278    if(!enabled) {
00279       ast_cli(fd, "DNS Manager is disabled.\n");
00280       return 0;
00281    }
00282 
00283    if (argc > 3)
00284       return RESULT_SHOWUSAGE;
00285 
00286    if (argc == 3) {
00287       if (regcomp(&info.filter, argv[2], REG_EXTENDED | REG_NOSUB))
00288          return RESULT_SHOWUSAGE;
00289       else
00290          info.regex_present = 1;
00291    }
00292 
00293    refresh_list(&info);
00294 
00295    if (info.regex_present)
00296       regfree(&info.filter);
00297 
00298    return 0;
00299 }

static int handle_cli_reload ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 262 of file dnsmgr.c.

References do_reload(), and RESULT_SHOWUSAGE.

00263 {
00264    if (argc > 2)
00265       return RESULT_SHOWUSAGE;
00266 
00267    do_reload(0);
00268    return 0;
00269 }

static int handle_cli_status ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 301 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.

00302 {
00303    int count = 0;
00304    struct ast_dnsmgr_entry *entry;
00305 
00306    if (argc > 2)
00307       return RESULT_SHOWUSAGE;
00308 
00309    ast_cli(fd, "DNS Manager: %s\n", enabled ? "enabled" : "disabled");
00310    ast_cli(fd, "Refresh Interval: %d seconds\n", refresh_interval);
00311    AST_LIST_LOCK(&entry_list);
00312    AST_LIST_TRAVERSE(&entry_list, entry, list)
00313       count++;
00314    AST_LIST_UNLOCK(&entry_list);
00315    ast_cli(fd, "Number of entries: %d\n", count);
00316 
00317    return 0;
00318 }

static int refresh_list ( const void *  data  )  [static]

Definition at line 223 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().

00224 {
00225    struct refresh_info *info = (struct refresh_info *)data;
00226    struct ast_dnsmgr_entry *entry;
00227 
00228    /* if a refresh or reload is already in progress, exit now */
00229    if (ast_mutex_trylock(&refresh_lock)) {
00230       if (info->verbose)
00231          ast_log(LOG_WARNING, "DNS Manager refresh already in progress.\n");
00232       return -1;
00233    }
00234 
00235    if (option_verbose > 2)
00236       ast_verbose(VERBOSE_PREFIX_2 "Refreshing DNS lookups.\n");
00237    AST_LIST_LOCK(info->entries);
00238    AST_LIST_TRAVERSE(info->entries, entry, list) {
00239       if (info->regex_present && regexec(&info->filter, entry->name, 0, NULL, 0))
00240           continue;
00241 
00242       dnsmgr_refresh(entry, info->verbose);
00243    }
00244    AST_LIST_UNLOCK(info->entries);
00245 
00246    ast_mutex_unlock(&refresh_lock);
00247 
00248    /* automatically reschedule based on the interval */
00249    return refresh_interval * 1000;
00250 }


Variable Documentation

struct ast_cli_entry cli_refresh [static]

Definition at line 327 of file dnsmgr.c.

Referenced by dnsmgr_init().

struct ast_cli_entry cli_reload [static]

Definition at line 320 of file dnsmgr.c.

Referenced by dnsmgr_init(), load_module(), and unload_module().

struct ast_cli_entry cli_status [static]

Definition at line 335 of file dnsmgr.c.

int enabled [static]

Definition at line 74 of file dnsmgr.c.

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().

ast_mutex_t refresh_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 70 of file dnsmgr.c.

int refresh_sched = -1 [static]

Definition at line 52 of file dnsmgr.c.

pthread_t refresh_thread = AST_PTHREADT_NULL [static]

Definition at line 53 of file dnsmgr.c.

struct sched_context* sched [static]

Definition at line 51 of file dnsmgr.c.


Generated on Fri Feb 19 17:13:07 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7