Mon May 14 04:48:23 2007

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"

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

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 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 }


Variable Documentation

struct ast_cli_entry cli_refresh [static]

Definition at line 321 of file dnsmgr.c.

Referenced by do_reload().

struct ast_cli_entry cli_reload [static]

Definition at line 314 of file dnsmgr.c.

Referenced by dnsmgr_init().

struct ast_cli_entry cli_status [static]

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

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 Mon May 14 04:48:24 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1