diff --git a/CHANGES b/CHANGES index 64e1d19a3d4ae75bd87911c6b9e2fa6bace274d7..8ddbf564f313ef62f442c00aa5d6d216272207e5 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 64cf68c10a75c1349857c443db7e4222ea53b27a..4899fa8b4fd64f9288dd3676bd872ef3793ca642 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 d5682758e30fbdfaaeefb5c3fbf9bf38f92abe19..fb0e2acb7fef7404f2fcf283e6d1817df6383067 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 650c68884c5ba4231bed81ac5bc04ed8e3944753..69e6b668d86ba288ca1a47afd4f2d8372c1b62db 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 bdf53149f43c427af164cd7926001abb4e6a6f81..8c4c548fa5e14edbb0002abdb80a8374c6269a0d 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 00aeea49fb3dd72bf854dd794784041896f73c69..fa37c8c4beb7b7024b15428e86bf4cd768bd53df 100644 --- a/res/res_pjsip/include/res_pjsip_private.h +++ b/res/res_pjsip/include/res_pjsip_private.h @@ -72,6 +72,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 *