Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 <[email protected]>
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"
54 #include "asterisk/linkedlists.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 
62 static struct ast_sched_context *sched;
63 static int refresh_sched = -1;
64 static pthread_t refresh_thread = AST_PTHREADT_NULL;
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 
91 static int enabled;
92 static int refresh_interval;
93 
94 struct refresh_info {
96  int verbose;
97  unsigned int regex_present:1;
98  regex_t filter;
99 };
100 
102  .entries = &entry_list,
103  .verbose = 0,
104 };
105 
106 struct 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 
125  AST_RWLIST_INSERT_HEAD(&entry_list, entry, list);
127 
128  return entry;
129 }
130 
131 struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct ast_sockaddr *result, const char *service)
132 {
133  return ast_dnsmgr_get_family(name, result, service, 0);
134 }
135 
137 {
138  if (!entry) {
139  return;
140  }
141 
143  AST_RWLIST_REMOVE(&entry_list, entry, list);
145  ast_debug(6, "removing dns manager for '%s'\n", entry->name);
146 
147  ast_mutex_destroy(&entry->lock);
148  ast_free(entry);
149 }
150 
151 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)
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  */
170  if (ast_sockaddr_parse(result, name, PARSE_PORT_FORBID)) {
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 */
177  ast_get_ip_or_srv(result, name, service);
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);
185  *dnsmgr = ast_dnsmgr_get_family(name, result, service, family);
186  (*dnsmgr)->update_func = func;
187  (*dnsmgr)->data = data;
188  return !*dnsmgr;
189 }
190 
191 int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service)
192 {
193  return internal_dnsmgr_lookup(name, result, dnsmgr, service, NULL, NULL);
194 }
195 
196 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)
197 {
198  return internal_dnsmgr_lookup(name, result, dnsmgr, service, func, data);
199 }
200 
201 /*
202  * Refresh a dnsmgr entry
203  */
204 static 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 
261 static void *do_refresh(void *data)
262 {
263  for (;;) {
264  pthread_testcancel();
265  usleep((ast_sched_wait(sched)*1000));
266  pthread_testcancel();
267  ast_sched_runq(sched);
268  }
269  return NULL;
270 }
271 
272 static 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) {
306  refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1);
307  }
308 }
309 
310 static int do_reload(int loading);
311 
312 static 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 
332 static 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  " Peforms 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 
367  refresh_list(&info);
368 
369  if (info.regex_present) {
370  regfree(&info.filter);
371  }
372 
373  return CLI_SUCCESS;
374 }
375 
376 static 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);
398  AST_RWLIST_TRAVERSE(&entry_list, entry, list)
399  count++;
401  ast_cli(a->fd, "Number of entries: %d\n", count);
402 
403  return CLI_SUCCESS;
404 }
405 
406 static struct ast_cli_entry cli_reload = AST_CLI_DEFINE(handle_cli_reload, "Reloads the DNS manager configuration");
407 static struct ast_cli_entry cli_refresh = AST_CLI_DEFINE(handle_cli_refresh, "Performs an immediate refresh");
408 static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the DNS manager status");
409 
410 static int unload_module(void)
411 {
412  ast_cli_unregister(&cli_reload);
413  ast_cli_unregister(&cli_status);
414  ast_cli_unregister(&cli_refresh);
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 
432 static int load_module(void)
433 {
434  if (!(sched = ast_sched_context_create())) {
435  ast_log(LOG_ERROR, "Unable to create schedule context.\n");
437  }
438  ast_cli_register(&cli_reload);
439  ast_cli_register(&cli_status);
440  ast_cli_register(&cli_refresh);
441 
443 }
444 
445 static int reload_module(void)
446 {
447  return do_reload(0);
448 }
449 
450 static 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 
470  if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
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  }
490  ast_config_destroy(config);
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 */
505  refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1);
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",
527 );
struct ast_variable * next
struct sockaddr_storage ss
Definition: netsock2.h:98
regex_t filter
Definition: dnsmgr.c:98
ast_mutex_t lock
Definition: dnsmgr.c:79
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
static struct refresh_info master_refresh_info
Definition: dnsmgr.c:101
Asterisk main include file. File version handling, generic pbx functions.
#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:332
char * config
Definition: conf2ael.c:66
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:755
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
static int refresh_interval
Definition: dnsmgr.c:92
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
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:171
struct entry_list * entries
Definition: dnsmgr.c:95
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
Definition: main/cli.c:2397
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
#define LOG_WARNING
Definition: logger.h:274
#define CONFIG_STATUS_FILEINVALID
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
void(* dns_update_func)(struct ast_sockaddr *old_addr, struct ast_sockaddr *new_addr, void *data)
Definition: dnsmgr.h:40
socklen_t len
Definition: netsock2.h:99
static struct ast_sched_context * sched
Definition: dnsmgr.c:62
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:3154
static struct ast_cli_entry cli_reload
Definition: dnsmgr.c:406
Structure for variables, used for configurations and for channel variables.
static char * handle_cli_refresh(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: dnsmgr.c:332
Definition: cli.h:152
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:524
#define REFRESH_DEFAULT
Definition: dnsmgr.c:89
static pthread_t refresh_thread
Definition: dnsmgr.c:64
Background DNS update manager.
static int refresh_sched
Definition: dnsmgr.c:63
#define ast_mutex_lock(a)
Definition: lock.h:187
static struct ast_cli_entry cli_refresh
Definition: dnsmgr.c:407
Definition: dnsmgr.c:66
#define NULL
Definition: resample.c:96
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
unsigned int family
Definition: dnsmgr.c:72
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
Socket address structure.
Definition: netsock2.h:97
int ast_dnsmgr_refresh(struct ast_dnsmgr_entry *entry)
Force a refresh of a dnsmgr entry.
Definition: dnsmgr.c:239
Utility functions.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_cli_register(e)
Registers a command or an array of commands.
Definition: cli.h:256
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
Configuration File Parser.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:717
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
dns_update_func update_func
Definition: dnsmgr.c:78
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
#define ast_mutex_trylock(a)
Definition: lock.h:189
const int fd
Definition: cli.h:159
#define AST_PTHREADT_NULL
Definition: lock.h:66
Access Control of various sorts.
static int do_reload(int loading)
Definition: dnsmgr.c:450
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
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
Scheduler Routines (derived from cheops)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct ast_sockaddr * result
Definition: dnsmgr.c:68
A set of macros to manage forward-linked lists.
static int load_module(void)
Definition: dnsmgr.c:432
#define CONFIG_STATUS_FILEUNCHANGED
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:236
const char *const * argv
Definition: cli.h:161
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
static struct ast_cli_entry cli_status
Definition: dnsmgr.c:408
static ast_mutex_t refresh_lock
Definition: dnsmgr.c:87
void * data
Definition: dnsmgr.c:76
#define LOG_ERROR
Definition: logger.h:285
void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry)
Free a DNS manager entry.
Definition: dnsmgr.c:136
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
unsigned int regex_present
Definition: dnsmgr.c:97
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
def info(msg)
static int refresh_list(const void *data)
Definition: dnsmgr.c:272
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose)
Definition: dnsmgr.c:204
static int unload_module(void)
Definition: dnsmgr.c:410
#define LOG_NOTICE
Definition: logger.h:263
static int reload_module(void)
Definition: dnsmgr.c:445
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static int reload(void)
Definition: cdr_mysql.c:741
void dnsmgr_start_refresh(void)
Definition: dnsmgr.c:302
Module could not be loaded properly.
Definition: module.h:102
Prototypes for public functions only of internal interest,.
static char * handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: dnsmgr.c:376
Structure used to handle boolean flags.
Definition: utils.h:199
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:414
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
const char * usage
Definition: cli.h:177
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:897
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 CONFIG_STATUS_FILEMISSING
#define CLI_SUCCESS
Definition: cli.h:44
Standard Command Line Interface.
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:431
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
static char * handle_cli_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: dnsmgr.c:312
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:884
int verbose
Definition: dnsmgr.c:96
Definition: search.h:40
unsigned int changed
Definition: dnsmgr.c:74
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#define ast_mutex_destroy(a)
Definition: lock.h:186
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
static struct entry_list entry_list
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
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 void * do_refresh(void *data)
Definition: dnsmgr.c:261
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:269
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
Structure for mutex and tracking information.
Definition: lock.h:135
#define ast_mutex_unlock(a)
Definition: lock.h:188
char * service
Definition: dnsmgr.c:70
static int enabled
Definition: dnsmgr.c:91
int ast_dnsmgr_changed(struct ast_dnsmgr_entry *entry)
Check is see if a dnsmgr entry has changed.
Definition: dnsmgr.c:247
static struct test_val a