Asterisk - The Open Source Telephony Project GIT-master-7921072
dnsmgr.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2005-2006, Kevin P. Fleming
5 *
6 * Kevin P. Fleming <kpfleming@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief Background DNS update manager
22 *
23 * \author Kevin P. Fleming <kpfleming@digium.com>
24 *
25 * \bug There is a minor race condition. In the event that an IP address
26 * of a dnsmgr managed host changes, there is the potential for the consumer
27 * of that address to access the in_addr data at the same time that the dnsmgr
28 * thread is in the middle of updating it to the new address.
29 */
30
31
32/*! \li \ref dnsmgr.c uses the configuration file \ref dnsmgr.conf
33 * \addtogroup configuration_file Configuration Files
34 */
35
36/*!
37 * \page dnsmgr.conf dnsmgr.conf
38 * \verbinclude dnsmgr.conf.sample
39 */
40
41
42/*** MODULEINFO
43 <support_level>core</support_level>
44 ***/
45
46#include "asterisk.h"
47
48#include "asterisk/_private.h"
49#include <regex.h>
50#include <signal.h>
51
52#include "asterisk/module.h"
53#include "asterisk/dnsmgr.h"
55#include "asterisk/utils.h"
56#include "asterisk/config.h"
57#include "asterisk/sched.h"
58#include "asterisk/cli.h"
59#include "asterisk/manager.h"
60#include "asterisk/acl.h"
61
62static struct ast_sched_context *sched;
63static int refresh_sched = -1;
65
67 /*! where we will store the resulting IP address and port number */
69 /*! SRV record to lookup, if provided. Composed of service, protocol, and domain name: _Service._Proto.Name */
70 char *service;
71 /*! Address family to filter DNS responses. */
72 unsigned int family;
73 /*! Set to 1 if the entry changes */
74 unsigned int changed:1;
75 /*! Data to pass back to update_func */
76 void *data;
77 /*! The callback function to execute on address update */
81 /*! just 1 here, but we use calloc to allocate the correct size */
82 char name[1];
83};
84
86
88
89#define REFRESH_DEFAULT 300
90
91static int enabled;
93
97 unsigned int regex_present:1;
98 regex_t filter;
99};
100
103 .verbose = 0,
104};
105
106struct ast_dnsmgr_entry *ast_dnsmgr_get_family(const char *name, struct ast_sockaddr *result, const char *service, unsigned int family)
107{
108 struct ast_dnsmgr_entry *entry;
109 int total_size = sizeof(*entry) + strlen(name) + (service ? strlen(service) + 1 : 0);
110
111 if (!result || ast_strlen_zero(name) || !(entry = ast_calloc(1, total_size))) {
112 return NULL;
113 }
114
115 entry->result = result;
116 ast_mutex_init(&entry->lock);
117 strcpy(entry->name, name);
118 if (service) {
119 entry->service = ((char *) entry) + sizeof(*entry) + strlen(name);
120 strcpy(entry->service, service);
121 }
122 entry->family = family;
123
127
128 return entry;
129}
130
131struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct ast_sockaddr *result, const char *service)
132{
134}
135
137{
138 if (!entry) {
139 return;
140 }
141
145 ast_debug(6, "removing dns manager for '%s'\n", entry->name);
146
147 ast_mutex_destroy(&entry->lock);
149}
150
151static int internal_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service, dns_update_func func, void *data)
152{
153 unsigned int family;
154
155 if (ast_strlen_zero(name) || !result || !dnsmgr) {
156 return -1;
157 }
158
159 if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name)) {
160 return 0;
161 }
162
163 /* Lookup address family filter. */
164 family = result->ss.ss_family;
165
166 /*
167 * If it's actually an IP address and not a name, there's no
168 * need for a managed lookup.
169 */
171 return 0;
172 }
173
174 ast_debug(6, "doing dnsmgr_lookup for '%s'\n", name);
175
176 /* do a lookup now but add a manager so it will automagically get updated in the background */
178
179 /* if dnsmgr is not enable don't bother adding an entry */
180 if (!enabled) {
181 return 0;
182 }
183
184 ast_debug(6, "adding dns manager for '%s'\n", name);
186 (*dnsmgr)->update_func = func;
187 (*dnsmgr)->data = data;
188 return !*dnsmgr;
189}
190
191int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service)
192{
194}
195
196int ast_dnsmgr_lookup_cb(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service, dns_update_func func, void *data)
197{
198 return internal_dnsmgr_lookup(name, result, dnsmgr, service, func, data);
199}
200
201/*
202 * Refresh a dnsmgr entry
203 */
204static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose)
205{
206 struct ast_sockaddr tmp = { .len = 0, };
207 int changed = 0;
208
209 ast_mutex_lock(&entry->lock);
210
211 ast_debug(6, "refreshing '%s'\n", entry->name);
212
213 tmp.ss.ss_family = entry->family;
214 if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service)) {
215 if (!ast_sockaddr_port(&tmp)) {
217 }
218 if (ast_sockaddr_cmp(&tmp, entry->result)) {
219 const char *old_addr = ast_strdupa(ast_sockaddr_stringify(entry->result));
220 const char *new_addr = ast_strdupa(ast_sockaddr_stringify(&tmp));
221
222 if (entry->update_func) {
223 entry->update_func(entry->result, &tmp, entry->data);
224 } else {
225 ast_log(LOG_NOTICE, "dnssrv: host '%s' changed from %s to %s\n",
226 entry->name, old_addr, new_addr);
227
228 ast_sockaddr_copy(entry->result, &tmp);
229 changed = entry->changed = 1;
230 }
231 }
232 }
233
234 ast_mutex_unlock(&entry->lock);
235
236 return changed;
237}
238
240{
241 return dnsmgr_refresh(entry, 0);
242}
243
244/*
245 * Check if dnsmgr entry has changed from since last call to this function
246 */
248{
249 int changed;
250
251 ast_mutex_lock(&entry->lock);
252
253 changed = entry->changed;
254 entry->changed = 0;
255
256 ast_mutex_unlock(&entry->lock);
257
258 return changed;
259}
260
261static void *do_refresh(void *data)
262{
263 for (;;) {
264 pthread_testcancel();
265 usleep((ast_sched_wait(sched)*1000));
266 pthread_testcancel();
268 }
269 return NULL;
270}
271
272static int refresh_list(const void *data)
273{
274 struct refresh_info *info = (struct refresh_info *)data;
275 struct ast_dnsmgr_entry *entry;
276
277 /* if a refresh or reload is already in progress, exit now */
279 if (info->verbose) {
280 ast_log(LOG_WARNING, "DNS Manager refresh already in progress.\n");
281 }
282 return -1;
283 }
284
285 ast_debug(6, "Refreshing DNS lookups.\n");
286 AST_RWLIST_RDLOCK(info->entries);
287 AST_RWLIST_TRAVERSE(info->entries, entry, list) {
288 if (info->regex_present && regexec(&info->filter, entry->name, 0, NULL, 0)) {
289 continue;
290 }
291
292 dnsmgr_refresh(entry, info->verbose);
293 }
294 AST_RWLIST_UNLOCK(info->entries);
295
297
298 /* automatically reschedule based on the interval */
299 return refresh_interval * 1000;
300}
301
303{
304 if (refresh_sched > -1) {
307 }
308}
309
310static int do_reload(int loading);
311
312static char *handle_cli_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
313{
314 switch (cmd) {
315 case CLI_INIT:
316 e->command = "dnsmgr reload";
317 e->usage =
318 "Usage: dnsmgr reload\n"
319 " Reloads the DNS manager configuration.\n";
320 return NULL;
321 case CLI_GENERATE:
322 return NULL;
323 }
324 if (a->argc > 2) {
325 return CLI_SHOWUSAGE;
326 }
327
328 do_reload(0);
329 return CLI_SUCCESS;
330}
331
332static char *handle_cli_refresh(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
333{
334 struct refresh_info info = {
335 .entries = &entry_list,
336 .verbose = 1,
337 };
338 switch (cmd) {
339 case CLI_INIT:
340 e->command = "dnsmgr refresh";
341 e->usage =
342 "Usage: dnsmgr refresh [pattern]\n"
343 " Performs an immediate refresh of the managed DNS entries.\n"
344 " Optional regular expression pattern is used to filter the entries to refresh.\n";
345 return NULL;
346 case CLI_GENERATE:
347 return NULL;
348 }
349
350 if (!enabled) {
351 ast_cli(a->fd, "DNS Manager is disabled.\n");
352 return 0;
353 }
354
355 if (a->argc > 3) {
356 return CLI_SHOWUSAGE;
357 }
358
359 if (a->argc == 3) {
360 if (regcomp(&info.filter, a->argv[2], REG_EXTENDED | REG_NOSUB)) {
361 return CLI_SHOWUSAGE;
362 } else {
363 info.regex_present = 1;
364 }
365 }
366
368
369 if (info.regex_present) {
370 regfree(&info.filter);
371 }
372
373 return CLI_SUCCESS;
374}
375
376static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
377{
378 int count = 0;
379 struct ast_dnsmgr_entry *entry;
380 switch (cmd) {
381 case CLI_INIT:
382 e->command = "dnsmgr status";
383 e->usage =
384 "Usage: dnsmgr status\n"
385 " Displays the DNS manager status.\n";
386 return NULL;
387 case CLI_GENERATE:
388 return NULL;
389 }
390
391 if (a->argc > 2) {
392 return CLI_SHOWUSAGE;
393 }
394
395 ast_cli(a->fd, "DNS Manager: %s\n", enabled ? "enabled" : "disabled");
396 ast_cli(a->fd, "Refresh Interval: %d seconds\n", refresh_interval);
399 count++;
401 ast_cli(a->fd, "Number of entries: %d\n", count);
402
403 return CLI_SUCCESS;
404}
405
406static struct ast_cli_entry cli_reload = AST_CLI_DEFINE(handle_cli_reload, "Reloads the DNS manager configuration");
407static struct ast_cli_entry cli_refresh = AST_CLI_DEFINE(handle_cli_refresh, "Performs an immediate refresh");
408static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the DNS manager status");
409
410static int unload_module(void)
411{
415
416 /* Destroy refresh thread. */
419 /* wake up the thread so it will exit */
420 pthread_cancel(refresh_thread);
421 pthread_kill(refresh_thread, SIGURG);
422 pthread_join(refresh_thread, NULL);
424 }
426
428
429 return 0;
430}
431
432static int load_module(void)
433{
434 if (!(sched = ast_sched_context_create())) {
435 ast_log(LOG_ERROR, "Unable to create schedule context.\n");
437 }
441
443}
444
445static int reload_module(void)
446{
447 return do_reload(0);
448}
449
450static int do_reload(int loading)
451{
452 struct ast_config *config;
453 struct ast_variable *v;
454 struct ast_flags config_flags = { loading ? 0 : CONFIG_FLAG_FILEUNCHANGED };
455 int interval;
456 int was_enabled;
457
458 if ((config = ast_config_load2("dnsmgr.conf", "dnsmgr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
459 return 0;
460 }
461
462 /* ensure that no refresh cycles run while the reload is in progress */
464
465 /* reset defaults in preparation for reading config file */
467 was_enabled = enabled;
468 enabled = 0;
469
472 return 0;
473 }
474
476
477 for (v = ast_variable_browse(config, "general"); v; v = v->next) {
478 if (!strcasecmp(v->name, "enable")) {
479 enabled = ast_true(v->value);
480 } else if (!strcasecmp(v->name, "refreshinterval")) {
481 if (sscanf(v->value, "%30d", &interval) < 1) {
482 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
483 } else if (interval < 0) {
484 ast_log(LOG_WARNING, "Invalid refresh interval '%d' specified, using default\n", interval);
485 } else {
486 refresh_interval = interval;
487 }
488 }
489 }
491
492 if (enabled && refresh_interval) {
493 ast_log(LOG_NOTICE, "Managed DNS entries will be refreshed every %d seconds.\n", refresh_interval);
494 }
495
496 /* if this reload enabled the manager, create the background thread
497 if it does not exist */
498 if (enabled) {
499 if (!was_enabled && (refresh_thread == AST_PTHREADT_NULL)) {
501 ast_log(LOG_ERROR, "Unable to start refresh thread.\n");
502 }
503 }
504 /* make a background refresh happen right away */
506 /* if this reload disabled the manager and there is a background thread, kill it */
507 } else if (!enabled && was_enabled && (refresh_thread != AST_PTHREADT_NULL)) {
508 /* wake up the thread so it will exit */
509 pthread_cancel(refresh_thread);
510 pthread_kill(refresh_thread, SIGURG);
511 pthread_join(refresh_thread, NULL);
513 }
514
516
517 return 0;
518}
519
521 .support_level = AST_MODULE_SUPPORT_CORE,
522 .load = load_module,
523 .unload = unload_module,
525 .load_pri = AST_MODPRI_CORE,
526 .requires = "extconfig",
Prototypes for public functions only of internal interest,.
Access Control of various sorts.
int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *hostname, const char *service)
Get the IP address given a hostname and optional service.
Definition: acl.c:896
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
static int tmp()
Definition: bt_open.c:389
enum ast_cc_service_type service
Definition: ccss.c:383
static PGresult * result
Definition: cel_pgsql.c:84
static const char config[]
Definition: chan_ooh323.c:111
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
Definition: main/cli.c:2427
#define ast_cli_register(e)
Registers a command or an array of commands.
Definition: cli.h:256
#define CLI_SUCCESS
Definition: cli.h:44
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry)
Free a DNS manager entry.
Definition: dnsmgr.c:136
static int enabled
Definition: dnsmgr.c:91
static int refresh_interval
Definition: dnsmgr.c:92
void dnsmgr_start_refresh(void)
Definition: dnsmgr.c:302
struct ast_dnsmgr_entry * ast_dnsmgr_get_family(const char *name, struct ast_sockaddr *result, const char *service, unsigned int family)
Allocate a new DNS manager entry.
Definition: dnsmgr.c:106
struct ast_dnsmgr_entry * ast_dnsmgr_get(const char *name, struct ast_sockaddr *result, const char *service)
Allocate a new DNS manager entry.
Definition: dnsmgr.c:131
static struct ast_cli_entry cli_status
Definition: dnsmgr.c:408
static void * do_refresh(void *data)
Definition: dnsmgr.c:261
static struct ast_sched_context * sched
Definition: dnsmgr.c:62
static ast_mutex_t refresh_lock
Definition: dnsmgr.c:87
static int internal_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service, dns_update_func func, void *data)
Definition: dnsmgr.c:151
#define REFRESH_DEFAULT
Definition: dnsmgr.c:89
int ast_dnsmgr_lookup_cb(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service, dns_update_func func, void *data)
Allocate and initialize a DNS manager entry, with update callback.
Definition: dnsmgr.c:196
static char * handle_cli_refresh(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: dnsmgr.c:332
int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service)
Allocate and initialize a DNS manager entry.
Definition: dnsmgr.c:191
static int reload_module(void)
Definition: dnsmgr.c:445
static int refresh_list(const void *data)
Definition: dnsmgr.c:272
static struct refresh_info master_refresh_info
Definition: dnsmgr.c:101
static pthread_t refresh_thread
Definition: dnsmgr.c:64
static int refresh_sched
Definition: dnsmgr.c:63
static struct ast_cli_entry cli_refresh
Definition: dnsmgr.c:407
static char * handle_cli_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: dnsmgr.c:312
static struct ast_cli_entry cli_reload
Definition: dnsmgr.c:406
static char * handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: dnsmgr.c:376
static int load_module(void)
Definition: dnsmgr.c:432
static int unload_module(void)
Definition: dnsmgr.c:410
int ast_dnsmgr_changed(struct ast_dnsmgr_entry *entry)
Check is see if a dnsmgr entry has changed.
Definition: dnsmgr.c:247
int ast_dnsmgr_refresh(struct ast_dnsmgr_entry *entry)
Force a refresh of a dnsmgr entry.
Definition: dnsmgr.c:239
static int do_reload(int loading)
Definition: dnsmgr.c:450
static struct entry_list entry_list
static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose)
Definition: dnsmgr.c:204
Background DNS update manager.
void(* dns_update_func)(struct ast_sockaddr *old_addr, struct ast_sockaddr *new_addr, void *data)
Definition: dnsmgr.h:40
static const char name[]
Definition: format_mp3.c:68
Configuration File Parser.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3321
#define CONFIG_STATUS_FILEMISSING
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
A set of macros to manage forward-linked lists.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
Definition: linkedlists.h:333
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:885
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:718
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:415
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_trylock(a)
Definition: lock.h:191
#define ast_mutex_destroy(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:189
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:520
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:317
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition: module.h:316
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODPRI_CORE
Definition: module.h:324
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition: module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:517
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
Definition: netsock2.h:167
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
static int reload(void)
#define NULL
Definition: resample.c:96
Scheduler Routines (derived from cheops)
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:786
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
Adds a scheduled event with rescheduling support.
Definition: sched.c:526
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:238
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:433
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Definition: dnsmgr.c:66
unsigned int family
Definition: dnsmgr.c:72
void * data
Definition: dnsmgr.c:76
char * service
Definition: dnsmgr.c:70
struct ast_sockaddr * result
Definition: dnsmgr.c:68
ast_mutex_t lock
Definition: dnsmgr.c:79
dns_update_func update_func
Definition: dnsmgr.c:78
unsigned int changed
Definition: dnsmgr.c:74
Structure used to handle boolean flags.
Definition: utils.h:199
Structure for mutex and tracking information.
Definition: lock.h:135
Socket address structure.
Definition: netsock2.h:97
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
Definition: search.h:40
char * data
Definition: search.h:42
int verbose
Definition: dnsmgr.c:96
regex_t filter
Definition: dnsmgr.c:98
struct entry_list * entries
Definition: dnsmgr.c:95
unsigned int regex_present
Definition: dnsmgr.c:97
Definition: sched.c:76
static struct test_val a
Utility functions.
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592