summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2014-03-17 22:54:32 +0000
committerJoshua Colp <jcolp@digium.com>2014-03-17 22:54:32 +0000
commitcc40bf53173ec40a26d4eb35184dd7d39f208efc (patch)
tree9f38be9c86724ea595541fff54c7e041061f1301
parent932fb5a6e231c511a74e7a78693cdac1abad7690 (diff)
res_pjsip: Enable PJSIP DNS client support.
This change enables DNS client support within PJSIP. System nameservers are automatically discovered using res_init or res_ninit. If this fails then PJSIP will resort to using gethostbyname for resolution. By enabling this support we gain SRV support, failover, and weight support. (closes issue ASTERISK-23435) Reported by: Matt Jordan Review: https://reviewboard.asterisk.org/r/3343/ ........ Merged revisions 410795 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410796 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--CHANGES7
-rw-r--r--include/asterisk/dns.h3
-rw-r--r--main/dns.c44
-rw-r--r--res/res_pjsip.c3
-rw-r--r--res/res_pjsip/config_system.c68
-rw-r--r--res/res_pjsip/include/res_pjsip_private.h5
6 files changed, 130 insertions, 0 deletions
diff --git a/CHANGES b/CHANGES
index 64e1d19a3..8ddbf564f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -241,6 +241,13 @@ res_mwi_external
and other modules that depend on it cannot be built or loaded with
app_voicemail present.
+res_pjsip
+------------------
+ * DNS functionality will now automatically be enabled if the system configured
+ nameservers can be retrieved. If the system configured nameservers can not be
+ retrieved the functionality will resort to using system resolution. Functionalty
+ such as SRV records and failover will not be available if system resolution
+ is in use.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 11 to Asterisk 12 --------------------
diff --git a/include/asterisk/dns.h b/include/asterisk/dns.h
index 64cf68c10..4899fa8b4 100644
--- a/include/asterisk/dns.h
+++ b/include/asterisk/dns.h
@@ -36,4 +36,7 @@
int ast_search_dns(void *context, const char *dname, int class, int type,
int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer));
+/*! \brief Retrieve the configured nameservers of the system */
+struct ao2_container *ast_dns_get_nameservers(void);
+
#endif /* _ASTERISK_DNS_H */
diff --git a/main/dns.c b/main/dns.c
index d5682758e..fb0e2acb7 100644
--- a/main/dns.c
+++ b/main/dns.c
@@ -296,3 +296,47 @@ int ast_search_dns(void *context,
return ret;
}
+
+struct ao2_container *ast_dns_get_nameservers(void)
+{
+#ifdef HAVE_RES_NINIT
+ struct __res_state dnsstate;
+#endif
+ struct __res_state *state;
+ struct ao2_container *nameservers;
+ int i;
+
+ nameservers = ast_str_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 3);
+ if (!nameservers) {
+ return NULL;
+ }
+
+#ifdef HAVE_RES_NINIT
+ memset(&dnsstate, 0, sizeof(dnsstate));
+ res_ninit(&dnsstate);
+ state = &dnsstate;
+#else
+ ast_mutex_lock(&res_lock);
+ res_init();
+ state = &_res;
+#endif
+
+ for (i = 0; i < state->nscount; i++) {
+ ast_str_container_add(nameservers, ast_inet_ntoa(state->nsaddr_list[i].sin_addr));
+ }
+
+#ifdef HAVE_RES_NINIT
+#ifdef HAVE_RES_NDESTROY
+ res_ndestroy(&dnsstate);
+#else
+ res_nclose(&dnsstate);
+#endif
+#else
+#ifdef HAVE_RES_CLOSE
+ res_close();
+#endif
+ ast_mutex_unlock(&res_lock);
+#endif
+
+ return nameservers;
+} \ No newline at end of file
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 650c68884..69e6b668d 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -2305,6 +2305,8 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
+ ast_sip_initialize_dns();
+
pjsip_tsx_layer_init_module(ast_pjsip_endpoint);
pjsip_ua_init_module(ast_pjsip_endpoint, NULL);
@@ -2395,6 +2397,7 @@ static int reload_module(void)
return AST_MODULE_LOAD_DECLINE;
}
ast_res_pjsip_init_options_handling(1);
+ ast_sip_initialize_dns();
return 0;
}
diff --git a/res/res_pjsip/config_system.c b/res/res_pjsip/config_system.c
index bdf53149f..8c4c548fa 100644
--- a/res/res_pjsip/config_system.c
+++ b/res/res_pjsip/config_system.c
@@ -25,6 +25,7 @@
#include "asterisk/sorcery.h"
#include "include/res_pjsip_private.h"
#include "asterisk/threadpool.h"
+#include "asterisk/dns.h"
#define TIMER_T1_MIN 100
#define DEFAULT_TIMER_T1 500
@@ -174,3 +175,70 @@ void ast_sip_destroy_system(void)
ast_sorcery_unref(system_sorcery);
}
+static int system_create_resolver_and_set_nameservers(void *data)
+{
+ struct ao2_container *discovered_nameservers;
+ struct ao2_iterator it_nameservers;
+ char *nameserver;
+ pj_status_t status;
+ pj_dns_resolver *resolver;
+ pj_str_t nameservers[PJ_DNS_RESOLVER_MAX_NS];
+ unsigned int count = 0;
+
+ discovered_nameservers = ast_dns_get_nameservers();
+ if (!discovered_nameservers) {
+ ast_log(LOG_ERROR, "Could not retrieve local system nameservers, resorting to system resolution\n");
+ return 0;
+ }
+
+ if (!ao2_container_count(discovered_nameservers)) {
+ ast_log(LOG_ERROR, "There are no local system nameservers configured, resorting to system resolution\n");
+ ao2_ref(discovered_nameservers, -1);
+ return -1;
+ }
+
+ if (!(resolver = pjsip_endpt_get_resolver(ast_sip_get_pjsip_endpoint()))) {
+ status = pjsip_endpt_create_resolver(ast_sip_get_pjsip_endpoint(), &resolver);
+ if (status != PJ_SUCCESS) {
+ ast_log(LOG_ERROR, "Could not create DNS resolver(%d), resorting to system resolution\n", status);
+ return 0;
+ }
+ }
+
+ it_nameservers = ao2_iterator_init(discovered_nameservers, 0);
+ while ((nameserver = ao2_iterator_next(&it_nameservers))) {
+ pj_strset2(&nameservers[count++], nameserver);
+ ao2_ref(nameserver, -1);
+
+ if (count == (PJ_DNS_RESOLVER_MAX_NS - 1)) {
+ break;
+ }
+ }
+ ao2_iterator_destroy(&it_nameservers);
+
+ status = pj_dns_resolver_set_ns(resolver, count, nameservers, NULL);
+
+ /* Since we no longer need the nameservers we can drop the list of them */
+ ao2_ref(discovered_nameservers, -1);
+
+ if (status != PJ_SUCCESS) {
+ ast_log(LOG_ERROR, "Could not set nameservers on DNS resolver in PJSIP(%d), resorting to system resolution\n",
+ status);
+ return 0;
+ }
+
+ if (!pjsip_endpt_get_resolver(ast_sip_get_pjsip_endpoint())) {
+ status = pjsip_endpt_set_resolver(ast_sip_get_pjsip_endpoint(), resolver);
+ if (status != PJ_SUCCESS) {
+ ast_log(LOG_ERROR, "Could not set DNS resolver in PJSIP(%d), resorting to system resolution\n", status);
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+void ast_sip_initialize_dns(void)
+{
+ ast_sip_push_task_synchronous(NULL, system_create_resolver_and_set_nameservers, NULL);
+} \ No newline at end of file
diff --git a/res/res_pjsip/include/res_pjsip_private.h b/res/res_pjsip/include/res_pjsip_private.h
index 00aeea49f..fa37c8c4b 100644
--- a/res/res_pjsip/include/res_pjsip_private.h
+++ b/res/res_pjsip/include/res_pjsip_private.h
@@ -73,6 +73,11 @@ int ast_sip_initialize_system(void);
void ast_sip_destroy_system(void);
/*!
+ * \brief Initialize nameserver configuration
+ */
+void ast_sip_initialize_dns(void);
+
+/*!
* \brief Initialize global configuration
*
* \retval 0 Success