Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:47 2009

## Asterisk developer's documentation

# dnsmgr.c File Reference

Background DNS update manager. More...

`#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.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

struct 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)
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)
void | 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 = 0
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

## Detailed Description

Background DNS update manager.

Definition in file dnsmgr.c.

## Define Documentation

#define REFRESH_DEFAULT 300

Definition at line 64 of file dnsmgr.c.

Referenced by do_reload().

## Function Documentation

struct ast_dnsmgr_entry* ast_dnsmgr_get | ( | const char * | name,
|  | struct in_addr * | result |
| ) |  |  | `[read]`

Definition at line 81 of file dnsmgr.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_strlen_zero(), calloc, and ast_dnsmgr_entry::result.

Referenced by ast_dnsmgr_lookup().

    00082 {
    00083    struct ast_dnsmgr_entry *entry;
    00084
    00085    if (!result || ast_strlen_zero(name))
    00086       return NULL;
    00087
    00088    entry = calloc(1, sizeof(*entry) + strlen(name));
    00089    if (!entry)
    00090       return NULL;
    00091
    00092    entry->result = result;
    00093    strcpy(entry->name, name);
    00094
    00095    AST_LIST_LOCK(&entry_list);
    00096    AST_LIST_INSERT_HEAD(&entry_list, entry, list);
    00097    AST_LIST_UNLOCK(&entry_list);
    00098
    00099    return entry;
    00100 }

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

Definition at line 113 of file dnsmgr.c.

References ast_dnsmgr_get(), ast_gethostbyname(), ast_strlen_zero(), ast_verbose(), enabled, hp, option_verbose, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

Referenced by build_peer().

    00114 {
    00115    struct ast_hostent ahp;
    00116    struct hostent *hp;
    00117
    00118    if (ast_strlen_zero(name) || !result || !dnsmgr)
    00119       return -1;
    00120
    00121    if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name))
    00122       return 0;
    00123
    00124    if (option_verbose > 3)
    00125       ast_verbose(VERBOSE_PREFIX_3 "doing lookup for '%s'\n", name);
    00126
    00127    /* if it's actually an IP address and not a name,
    00128       there's no need for a managed lookup */
    00129    if (inet_aton(name, result))
    00130       return 0;
    00131
    00132    /* do a lookup now but add a manager so it will automagically get updated in the background */
    00133    if ((hp = ast_gethostbyname(name, &ahp)))
    00134       memcpy(result, hp->h_addr, sizeof(result));
    00135
    00136    /* if dnsmgr is not enable don't bother adding an entry */
    00137    if (!enabled)
    00138       return 0;
    00139
    00140    if (option_verbose > 2)
    00141       ast_verbose(VERBOSE_PREFIX_2 "adding manager for '%s'\n", name);
    00142    *dnsmgr = ast_dnsmgr_get(name, result);
    00143    return !*dnsmgr;
    00144 }

void ast_dnsmgr_release | ( | struct ast_dnsmgr_entry * | entry | ) |

Definition at line 102 of file dnsmgr.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and free.

Referenced by destroy_peer().

    00103 {
    00104    if (!entry)
    00105       return;
    00106
    00107    AST_LIST_LOCK(&entry_list);
    00108    AST_LIST_REMOVE(&entry_list, entry, list);
    00109    AST_LIST_UNLOCK(&entry_list);
    00110    free(entry);
    00111 }

static AST_LIST_HEAD_STATIC | ( | entry_list | ,
|  | ast_dnsmgr_entry |  |
| ) |  |  | `[static]`

AST_MUTEX_DEFINE_STATIC | ( | refresh_lock |  | ) |

int dnsmgr_init | ( | void |  | ) |

Definition at line 285 of file dnsmgr.c.

References ast_cli_register(), ast_log(), cli_reload, cli_status, do_reload(), LOG_ERROR, and sched_context_create().

Referenced by main().

    00286 {
    00287    sched = sched_context_create();
    00288    if (!sched) {
    00289       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
    00290       return -1;
    00291    }
    00292    ast_cli_register(&cli_reload);
    00293    ast_cli_register(&cli_status);
    00294    return do_reload(1);
    00295 }

void dnsmgr_reload | ( | void |  | ) |

Definition at line 297 of file dnsmgr.c.

References do_reload().

Referenced by ast_module_reload().

    00298 {
    00299    do_reload(0);
    00300 }

void dnsmgr_start_refresh | ( | void |  | ) |

Definition at line 194 of file dnsmgr.c.

References ast_sched_add_variable(), ast_sched_del(), master_refresh_info, and refresh_list().

Referenced by main().

    00195 {
    00196    if (refresh_sched > -1) {
    00197       ast_sched_del(sched, refresh_sched);
    00198       refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1);
    00199    }
    00200 }

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

Definition at line 146 of file dnsmgr.c.

References ast_sched_runq(), and ast_sched_wait().

Referenced by do_reload().

    00147 {
    00148    for (;;) {
    00149       pthread_testcancel();
    00150       usleep((ast_sched_wait(sched)*1000));
    00151       pthread_testcancel();
    00152       ast_sched_runq(sched);
    00153    }
    00154    return NULL;
    00155 }

static int do_reload | ( | int | loading | ) | `[static]`

Definition at line 302 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, 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, and refresh_list().

    00303 {
    00304    struct ast_config *config;
    00305    const char *interval_value;
    00306    const char *enabled_value;
    00307    int interval;
    00308    int was_enabled;
    00309    int res = -1;
    00310
    00311    /* ensure that no refresh cycles run while the reload is in progress */
    00312    ast_mutex_lock(&refresh_lock);
    00313
    00314    /* reset defaults in preparation for reading config file */
    00315    refresh_interval = REFRESH_DEFAULT;
    00316    was_enabled = enabled;
    00317    enabled = 0;
    00318
    00319    if (refresh_sched > -1)
    00320       ast_sched_del(sched, refresh_sched);
    00321
    00322    if ((config = ast_config_load("dnsmgr.conf"))) {
    00323       if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
    00324          enabled = ast_true(enabled_value);
    00325       }
    00326       if ((interval_value = ast_variable_retrieve(config, "general", "refreshinterval"))) {
    00327          if (sscanf(interval_value, "%30d", &interval) < 1)
    00328             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", interval_value);
    00329          else if (interval < 0)
    00330             ast_log(LOG_WARNING, "Invalid refresh interval '%d' specified, using default\n", interval);
    00331          else
    00332             refresh_interval = interval;
    00333       }
    00334       ast_config_destroy(config);
    00335    }
    00336
    00337    if (enabled && refresh_interval)
    00338       ast_log(LOG_NOTICE, "Managed DNS entries will be refreshed every %d seconds.\n", refresh_interval);
    00339
    00340    /* if this reload enabled the manager, create the background thread
    00341       if it does not exist */
    00342    if (enabled) {
    00343       if (!was_enabled && (refresh_thread == AST_PTHREADT_NULL)) {
    00344          if (ast_pthread_create(&refresh_thread, NULL, do_refresh, NULL) < 0) {
    00345             ast_log(LOG_ERROR, "Unable to start refresh thread.\n");
    00346          }
    00347          ast_cli_register(&cli_refresh);
    00348       }
    00349       /* make a background refresh happen right away */
    00350       refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1);
    00351       res = 0;
    00352    }
    00353    /* if this reload disabled the manager and there is a background thread,
    00354       kill it */
    00355    else if (!enabled && was_enabled && (refresh_thread != AST_PTHREADT_NULL)) {
    00356       /* wake up the thread so it will exit */
    00357       pthread_cancel(refresh_thread);
    00358       pthread_kill(refresh_thread, SIGURG);
    00359       pthread_join(refresh_thread, NULL);
    00360       refresh_thread = AST_PTHREADT_NULL;
    00361       ast_cli_unregister(&cli_refresh);
    00362       res = 0;
    00363    }
    00364    else
    00365       res = 0;
    00366
    00367    ast_mutex_unlock(&refresh_lock);
    00368
    00369    return res;
    00370 }

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

Definition at line 213 of file dnsmgr.c.

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

    00214 {
    00215    struct refresh_info info = {
    00216       .entries = &entry_list,
    00217       .verbose = 1,
    00218    };
    00219
    00220    if (argc > 3)
    00221       return RESULT_SHOWUSAGE;
    00222
    00223    if (argc == 3) {
    00224       if (regcomp(&info.filter, argv[2], REG_EXTENDED | REG_NOSUB))
    00225          return RESULT_SHOWUSAGE;
    00226       else
    00227          info.regex_present = 1;
    00228    }
    00229
    00230    refresh_list(&info);
    00231
    00232    if (info.regex_present)
    00233       regfree(&info.filter);
    00234
    00235    return 0;
    00236 }

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

Definition at line 204 of file dnsmgr.c.

References do_reload(), and RESULT_SHOWUSAGE.

    00205 {
    00206    if (argc > 2)
    00207       return RESULT_SHOWUSAGE;
    00208
    00209    do_reload(0);
    00210    return 0;
    00211 }

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

Definition at line 238 of file dnsmgr.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, enabled, refresh_interval, and RESULT_SHOWUSAGE.

    00239 {
    00240    int count = 0;
    00241    struct ast_dnsmgr_entry *entry;
    00242
    00243    if (argc > 2)
    00244       return RESULT_SHOWUSAGE;
    00245
    00246    ast_cli(fd, "DNS Manager: %s\n", enabled ? "enabled" : "disabled");
    00247    ast_cli(fd, "Refresh Interval: %d seconds\n", refresh_interval);
    00248    AST_LIST_LOCK(&entry_list);
    00249    AST_LIST_TRAVERSE(&entry_list, entry, list)
    00250       count++;
    00251    AST_LIST_UNLOCK(&entry_list);
    00252    ast_cli(fd, "Number of entries: %d\n", count);
    00253
    00254    return 0;
    00255 }

static int refresh_list | ( | void * | data | ) | `[static]`

Definition at line 157 of file dnsmgr.c.

References ast_gethostbyname(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_verbose(), refresh_info::entries, refresh_info::filter, hp, LOG_WARNING, option_verbose, refresh_interval, refresh_info::regex_present, ast_dnsmgr_entry::result, refresh_info::verbose, and VERBOSE_PREFIX_2.

Referenced by dnsmgr_start_refresh(), do_reload(), and handle_cli_refresh().

    00158 {
    00159    struct refresh_info *info = data;
    00160    struct ast_dnsmgr_entry *entry;
    00161    struct ast_hostent ahp;
    00162    struct hostent *hp;
    00163
    00164    /* if a refresh or reload is already in progress, exit now */
    00165    if (ast_mutex_trylock(&refresh_lock)) {
    00166       if (info->verbose)
    00167          ast_log(LOG_WARNING, "DNS Manager refresh already in progress.\n");
    00168       return -1;
    00169    }
    00170
    00171    if (option_verbose > 2)
    00172       ast_verbose(VERBOSE_PREFIX_2 "Refreshing DNS lookups.\n");
    00173    AST_LIST_LOCK(info->entries);
    00174    AST_LIST_TRAVERSE(info->entries, entry, list) {
    00175       if (info->regex_present && regexec(&info->filter, entry->name, 0, NULL, 0))
    00176           continue;
    00177
    00178       if (info->verbose && (option_verbose > 2))
    00179          ast_verbose(VERBOSE_PREFIX_2 "refreshing '%s'\n", entry->name);
    00180
    00181       if ((hp = ast_gethostbyname(entry->name, &ahp))) {
    00182          /* check to see if it has changed, do callback if requested */
    00183          memcpy(entry->result, hp->h_addr, sizeof(entry->result));
    00184       }
    00185    }
    00186    AST_LIST_UNLOCK(info->entries);
    00187
    00188    ast_mutex_unlock(&refresh_lock);
    00189
    00190    /* automatically reschedule based on the interval */
    00191    return refresh_interval * 1000;
    00192 }

## Variable Documentation

struct ast_cli_entry cli_refresh`[static]`

Definition at line 266 of file dnsmgr.c.

Referenced by do_reload().

struct ast_cli_entry cli_reload`[static]`

Definition at line 257 of file dnsmgr.c.

Referenced by dnsmgr_init().

struct ast_cli_entry cli_status`[static]`

Definition at line 276 of file dnsmgr.c.

int enabled = 0`[static]`

Definition at line 66 of file dnsmgr.c.

struct refresh_info master_refresh_info`[static]`

Initial value:

     {
       .entries = &entry_list,
       .verbose = 0,
    }

Definition at line 76 of file dnsmgr.c.

Referenced by dnsmgr_start_refresh(), and do_reload().

int refresh_interval`[static]`

Definition at line 67 of file dnsmgr.c.

Referenced by do_reload(), handle_cli_status(), and refresh_list().

int refresh_sched = -1`[static]`

Definition at line 51 of file dnsmgr.c.

pthread_t refresh_thread = AST_PTHREADT_NULL`[static]`

Definition at line 52 of file dnsmgr.c.

struct sched_context* sched`[static]`

Definition at line 50 of file dnsmgr.c.