Sat Aug 6 00:39:55 2011

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 70 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 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.

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


Variable Documentation

struct ast_cli_entry cli_refresh [static]

Definition at line 323 of file dnsmgr.c.

Referenced by dnsmgr_init().

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]

Definition at line 331 of file dnsmgr.c.

int enabled [static]

Definition at line 72 of file dnsmgr.c.

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]

Definition at line 68 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 Sat Aug 6 00:39:55 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7