22#include <pjlib-util/errno.h> 
   24#include <arpa/nameser.h> 
   36#ifdef HAVE_PJSIP_EXTERNAL_RESOLVER 
   41    pjsip_transport_type_e transport;
 
   52    struct targets resolving;
 
   56    pjsip_server_addresses addresses;
 
   66enum sip_resolver_transport {
 
   67    SIP_RESOLVER_TRANSPORT_UDP,
 
   68    SIP_RESOLVER_TRANSPORT_TCP,
 
   69    SIP_RESOLVER_TRANSPORT_TLS,
 
   70    SIP_RESOLVER_TRANSPORT_UDP6,
 
   71    SIP_RESOLVER_TRANSPORT_TCP6,
 
   72    SIP_RESOLVER_TRANSPORT_TLS6,
 
   76static int sip_available_transports[] = {
 
   82    [SIP_RESOLVER_TRANSPORT_UDP] = 0,
 
   83    [SIP_RESOLVER_TRANSPORT_TCP] = 0,
 
   84    [SIP_RESOLVER_TRANSPORT_TLS] = 0,
 
   85    [SIP_RESOLVER_TRANSPORT_UDP6] = 0,
 
   86    [SIP_RESOLVER_TRANSPORT_TCP6] = 0,
 
   87    [SIP_RESOLVER_TRANSPORT_TLS6] = 0,
 
   96static void sip_resolve_destroy(
void *data)
 
   98    struct sip_resolve *resolve = data;
 
  114static int sip_transport_is_available(
enum pjsip_transport_type_e transport)
 
  116    enum sip_resolver_transport resolver_transport;
 
  118    if (transport == PJSIP_TRANSPORT_UDP) {
 
  119        resolver_transport = SIP_RESOLVER_TRANSPORT_UDP;
 
  120    } 
else if (transport == PJSIP_TRANSPORT_TCP) {
 
  121        resolver_transport = SIP_RESOLVER_TRANSPORT_TCP;
 
  122    } 
else if (transport == PJSIP_TRANSPORT_TLS) {
 
  123        resolver_transport = SIP_RESOLVER_TRANSPORT_TLS;
 
  124    } 
else if (transport == PJSIP_TRANSPORT_UDP6) {
 
  125        resolver_transport = SIP_RESOLVER_TRANSPORT_UDP6;
 
  126    } 
else if (transport == PJSIP_TRANSPORT_TCP6) {
 
  127        resolver_transport = SIP_RESOLVER_TRANSPORT_TCP6;
 
  128    } 
else if (transport == PJSIP_TRANSPORT_TLS6) {
 
  129        resolver_transport = SIP_RESOLVER_TRANSPORT_TLS6;
 
  134    return sip_available_transports[resolver_transport];
 
  152static int sip_resolve_add(
struct sip_resolve *resolve, 
const char *
name, 
int rr_type, 
int rr_class, pjsip_transport_type_e transport, 
int port)
 
  154    struct sip_target target = {
 
  155        .transport = transport,
 
  159    if (!resolve->queries) {
 
  161        if (!resolve->queries) {
 
  167        target.port = pjsip_transport_get_default_port_for_type(transport);
 
  174    ast_debug(2, 
"[%p] Added target '%s' with record type '%d', transport '%s', and port '%d'\n",
 
  175        resolve, 
name, rr_type, pjsip_transport_get_type_desc(transport), target.port);
 
  188static int sip_resolve_invoke_user_callback(
void *data)
 
  190    struct sip_resolve *resolve = data;
 
  194        char addr[PJ_INET6_ADDRSTRLEN + 10];
 
  197        for (idx = 0; idx < resolve->addresses.count; ++idx) {
 
  198            pj_sockaddr_print(&resolve->addresses.entry[idx].addr, addr, 
sizeof(addr), 3);
 
  201                pjsip_transport_get_type_desc(resolve->addresses.entry[idx].type));
 
  205    ast_debug(2, 
"[%p] Invoking user callback with '%d' addresses\n", resolve, resolve->addresses.count);
 
  206    resolve->callback(resolve->addresses.count ? PJ_SUCCESS : PJLIB_UTIL_EDNSNOANSWERREC, resolve->token, &resolve->addresses);
 
  225static int sip_resolve_handle_naptr(
struct sip_resolve *resolve, 
const struct ast_dns_record *record,
 
  226    const char *
service, pjsip_transport_type_e transport)
 
  237    if (!sip_transport_is_available(transport) &&
 
  238        (!(transport & PJSIP_TRANSPORT_IPV6) && !sip_transport_is_available(transport | PJSIP_TRANSPORT_IPV6))) {
 
  239        ast_debug(2, 
"[%p] NAPTR service %s skipped as transport is unavailable\n",
 
  245        ast_debug(2, 
"[%p] NAPTR service %s received with unsupported flags '%s'\n",
 
  268    struct targets resolving;
 
  269    int idx, address_count = 0, have_naptr = 0, have_srv = 0;
 
  270    unsigned short order = 0;
 
  271    int strict_order = 0;
 
  273    ast_debug(2, 
"[%p] All parallel queries completed\n", resolve);
 
  275    resolve->queries = 
NULL;
 
  280    resolving = resolve->resolving;
 
  291        struct sip_target *target;
 
  295            ast_debug(2, 
"[%p] No result information for target '%s' of type '%d'\n", resolve,
 
  306                if (have_naptr || have_srv) {
 
  307                    ast_debug(2, 
"[%p] %s record being skipped on target '%s' because NAPTR or SRV record exists\n",
 
  314                if (address_count == PJSIP_MAX_RESOLVED_ADDRESSES) {
 
  318                resolve->addresses.entry[address_count].type = target->transport;
 
  323                    resolve->addresses.entry[address_count].addr_len = 
sizeof(pj_sockaddr_in);
 
  324                    pj_sockaddr_init(pj_AF_INET(), &resolve->addresses.entry[address_count].addr, 
NULL,
 
  329                    resolve->addresses.entry[address_count].addr_len = 
sizeof(pj_sockaddr_in6);
 
  330                    pj_sockaddr_init(pj_AF_INET6(), &resolve->addresses.entry[address_count].addr, 
NULL,
 
  339                    ast_debug(2, 
"[%p] SRV record being skipped on target '%s' because NAPTR record exists\n",
 
  348                if ((target->transport & PJSIP_TRANSPORT_IPV6) &&
 
  349                    sip_transport_is_available(target->transport)) {
 
  353                } 
else if (!(target->transport & PJSIP_TRANSPORT_IPV6) &&
 
  354                    sip_transport_is_available(target->transport | PJSIP_TRANSPORT_IPV6)) {
 
  355                    sip_resolve_add(resolve, 
ast_dns_srv_get_host(record), T_AAAA, C_IN, target->transport | PJSIP_TRANSPORT_IPV6,
 
  360                if (!(target->transport & PJSIP_TRANSPORT_IPV6) &&
 
  361                    sip_transport_is_available(target->transport)) {
 
  372                    ast_debug(2, 
"[%p] NAPTR record skipped because order '%hu' does not match strict order '%hu'\n",
 
  377                if (target->transport == PJSIP_TRANSPORT_UNSPECIFIED || target->transport == PJSIP_TRANSPORT_UDP ||
 
  378                    target->transport == PJSIP_TRANSPORT_UDP6) {
 
  379                    added = sip_resolve_handle_naptr(resolve, record, 
"sip+d2u",
 
  380                        target->transport == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : target->transport);
 
  382                if (target->transport == PJSIP_TRANSPORT_UNSPECIFIED || target->transport == PJSIP_TRANSPORT_TCP ||
 
  383                    target->transport == PJSIP_TRANSPORT_TCP6) {
 
  384                    added = sip_resolve_handle_naptr(resolve, record, 
"sip+d2t",
 
  385                        target->transport == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_TCP : target->transport);
 
  387                if (target->transport == PJSIP_TRANSPORT_UNSPECIFIED || target->transport == PJSIP_TRANSPORT_TLS ||
 
  388                    target->transport == PJSIP_TRANSPORT_TLS6) {
 
  389                    added = sip_resolve_handle_naptr(resolve, record, 
"sips+d2t",
 
  390                        target->transport == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_TLS : target->transport);
 
  404    resolve->addresses.count = address_count;
 
  410    if (resolve->queries) {
 
  411        ast_debug(2, 
"[%p] New queries added, performing parallel resolution again\n", resolve);
 
  417    ast_debug(2, 
"[%p] Resolution completed - %d viable targets\n", resolve, resolve->addresses.count);
 
  421    if (
ast_sip_push_task(resolve->serializer, sip_resolve_invoke_user_callback, resolve)) {
 
  438static int sip_resolve_get_ip_addr_ver(
const pj_str_t *host)
 
  443    if (pj_inet_aton(host, &
dummy) > 0) {
 
  447    if (pj_inet_pton(pj_AF_INET6(), host, &dummy6) == PJ_SUCCESS) {
 
  464static void sip_resolve(pjsip_resolver_t *resolver, pj_pool_t *pool, 
const pjsip_host_info *target,
 
  465    void *token, pjsip_resolver_callback *cb)
 
  468    pjsip_transport_type_e 
type = target->type;
 
  469    struct sip_resolve *resolve;
 
  470    char host[NI_MAXHOST];
 
  475    ast_debug(2, 
"Performing SIP DNS resolution of target '%s'\n", host);
 
  478    ip_addr_ver = sip_resolve_get_ip_addr_ver(&target->addr.host);
 
  481    if (
type == PJSIP_TRANSPORT_UNSPECIFIED) {
 
  484        if (target->flag & PJSIP_TRANSPORT_SECURE) {
 
  485            type = PJSIP_TRANSPORT_TLS;
 
  486        } 
else if (target->flag & PJSIP_TRANSPORT_RELIABLE) {
 
  487            type = PJSIP_TRANSPORT_TCP;
 
  493        if (ip_addr_ver || target->addr.port) {
 
  494            type = PJSIP_TRANSPORT_UDP;
 
  497        if (ip_addr_ver == 6) {
 
  498            type = (pjsip_transport_type_e)((
int) 
type | PJSIP_TRANSPORT_IPV6);
 
  502    ast_debug(2, 
"Transport type for target '%s' is '%s'\n", host, pjsip_transport_get_type_desc(
type));
 
  506        pjsip_server_addresses addresses = {
 
  507            .entry[0].type = 
type,
 
  511        if (ip_addr_ver == 4) {
 
  512            addresses.entry[0].addr_len = 
sizeof(pj_sockaddr_in);
 
  513            pj_sockaddr_init(pj_AF_INET(), &addresses.entry[0].addr, 
NULL, 0);
 
  514            pj_inet_aton(&target->addr.host, &addresses.entry[0].addr.ipv4.sin_addr);
 
  516            addresses.entry[0].addr_len = 
sizeof(pj_sockaddr_in6);
 
  517            pj_sockaddr_init(pj_AF_INET6(), &addresses.entry[0].addr, 
NULL, 0);
 
  518            pj_inet_pton(pj_AF_INET6(), &target->addr.host, &addresses.entry[0].addr.ipv6.sin6_addr);
 
  521        pj_sockaddr_set_port(&addresses.entry[0].addr, !target->addr.port ? pjsip_transport_get_default_port_for_type(
type) : target->addr.port);
 
  523        ast_debug(2, 
"Target '%s' is an IP address, skipping resolution\n", host);
 
  525        cb(PJ_SUCCESS, token, &addresses);
 
  532        cb(PJ_ENOMEM, token, 
NULL);
 
  536    resolve->callback = cb;
 
  537    resolve->token = token;
 
  541        cb(PJ_ENOMEM, token, 
NULL);
 
  545    ast_debug(2, 
"[%p] Created resolution tracking for target '%s'\n", resolve, host);
 
  548    if (!target->addr.port) {
 
  549        char srv[NI_MAXHOST];
 
  562        res |= sip_resolve_add(resolve, host, T_NAPTR, C_IN, 
type, 0);
 
  564        if (
type == PJSIP_TRANSPORT_UNSPECIFIED ||
 
  565            (
type == PJSIP_TRANSPORT_TLS && sip_transport_is_available(PJSIP_TRANSPORT_TLS)) ||
 
  566            (
type == PJSIP_TRANSPORT_TLS6 && sip_transport_is_available(PJSIP_TRANSPORT_TLS6))) {
 
  567            if (snprintf(srv, 
sizeof(srv), 
"_sips._tcp.%s", host) < NI_MAXHOST) {
 
  568                res |= sip_resolve_add(resolve, srv, T_SRV, C_IN,
 
  569                    type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_TLS : 
type, 0);
 
  572        if (
type == PJSIP_TRANSPORT_UNSPECIFIED ||
 
  573            (
type == PJSIP_TRANSPORT_TCP && sip_transport_is_available(PJSIP_TRANSPORT_TCP)) ||
 
  574            (
type == PJSIP_TRANSPORT_TCP6 && sip_transport_is_available(PJSIP_TRANSPORT_TCP6))) {
 
  575            if (snprintf(srv, 
sizeof(srv), 
"_sip._tcp.%s", host) < NI_MAXHOST) {
 
  576                res |= sip_resolve_add(resolve, srv, T_SRV, C_IN,
 
  577                    type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_TCP : 
type, 0);
 
  580        if (
type == PJSIP_TRANSPORT_UNSPECIFIED ||
 
  581            (
type == PJSIP_TRANSPORT_UDP && sip_transport_is_available(PJSIP_TRANSPORT_UDP)) ||
 
  582            (
type == PJSIP_TRANSPORT_UDP6 && sip_transport_is_available(PJSIP_TRANSPORT_UDP6))) {
 
  583            if (snprintf(srv, 
sizeof(srv), 
"_sip._udp.%s", host) < NI_MAXHOST) {
 
  584                res |= sip_resolve_add(resolve, srv, T_SRV, C_IN,
 
  585                    type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : 
type, 0);
 
  590    if ((
type == PJSIP_TRANSPORT_UNSPECIFIED && sip_transport_is_available(PJSIP_TRANSPORT_UDP6)) ||
 
  591        ((
type & PJSIP_TRANSPORT_IPV6) && sip_transport_is_available(
type))) {
 
  592        res |= sip_resolve_add(resolve, host, T_AAAA, C_IN, (
type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP6 : 
type), target->addr.port);
 
  593    } 
else if (!(
type & PJSIP_TRANSPORT_IPV6) && sip_transport_is_available(
type | PJSIP_TRANSPORT_IPV6)) {
 
  594        res |= sip_resolve_add(resolve, host, T_AAAA, C_IN, 
type | PJSIP_TRANSPORT_IPV6, target->addr.port);
 
  597    if ((
type == PJSIP_TRANSPORT_UNSPECIFIED && sip_transport_is_available(PJSIP_TRANSPORT_UDP)) ||
 
  598        (!(
type & PJSIP_TRANSPORT_IPV6) && sip_transport_is_available(
type))) {
 
  599        res |= sip_resolve_add(resolve, host, T_A, C_IN, (
type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : 
type), target->addr.port);
 
  604        cb(PJ_ENOMEM, token, 
NULL);
 
  607    if (!resolve->queries) {
 
  608        ast_debug(2, 
"[%p] No resolution queries for target '%s'\n", resolve, host);
 
  610        cb(PJLIB_UTIL_EDNSNOANSWERREC, token, 
NULL);
 
  616    ast_debug(2, 
"[%p] Starting initial resolution using parallel queries for target '%s'\n", resolve, host);
 
  630static void sip_check_transport(pj_pool_t *pool, pjsip_transport_type_e transport, 
const char *
name)
 
  632    pjsip_tpmgr_fla2_param prm;
 
  633    enum sip_resolver_transport resolver_transport;
 
  635    pjsip_tpmgr_fla2_param_default(&prm);
 
  636    prm.tp_type = transport;
 
  638    if (transport == PJSIP_TRANSPORT_UDP) {
 
  639        resolver_transport = SIP_RESOLVER_TRANSPORT_UDP;
 
  640    } 
else if (transport == PJSIP_TRANSPORT_TCP) {
 
  641        resolver_transport = SIP_RESOLVER_TRANSPORT_TCP;
 
  642    } 
else if (transport == PJSIP_TRANSPORT_TLS) {
 
  643        resolver_transport = SIP_RESOLVER_TRANSPORT_TLS;
 
  644    } 
else if (transport == PJSIP_TRANSPORT_UDP6) {
 
  645        resolver_transport = SIP_RESOLVER_TRANSPORT_UDP6;
 
  646    } 
else if (transport == PJSIP_TRANSPORT_TCP6) {
 
  647        resolver_transport = SIP_RESOLVER_TRANSPORT_TCP6;
 
  648    } 
else if (transport == PJSIP_TRANSPORT_TLS6) {
 
  649        resolver_transport = SIP_RESOLVER_TRANSPORT_TLS6;
 
  651        ast_verb(2, 
"'%s' is an unsupported SIP transport\n", 
name);
 
  656        pool, &prm) == PJ_SUCCESS) {
 
  657        ast_verb(2, 
"'%s' is an available SIP transport\n", 
name);
 
  658        sip_available_transports[resolver_transport] = 1;
 
  660        ast_verb(2, 
"'%s' is not an available SIP transport, disabling resolver support for it\n",
 
  666static pjsip_ext_resolver ext_resolver = {
 
  667    .resolve = sip_resolve,
 
  677static int sip_replace_resolver(
void *data)
 
  688    sip_check_transport(pool, PJSIP_TRANSPORT_UDP, 
"UDP+IPv4");
 
  689    sip_check_transport(pool, PJSIP_TRANSPORT_TCP, 
"TCP+IPv4");
 
  690    sip_check_transport(pool, PJSIP_TRANSPORT_TLS, 
"TLS+IPv4");
 
  691    sip_check_transport(pool, PJSIP_TRANSPORT_UDP6, 
"UDP+IPv6");
 
  692    sip_check_transport(pool, PJSIP_TRANSPORT_TCP6, 
"TCP+IPv6");
 
  693    sip_check_transport(pool, PJSIP_TRANSPORT_TLS6, 
"TLS+IPv6");
 
  713    ast_log(
LOG_NOTICE, 
"The version of PJSIP in use does not support external resolvers, using PJSIP provided resolver\n");
 
 
Asterisk main include file. File version handling, generic pbx functions.
@ AO2_ALLOC_OPT_LOCK_NOLOCK
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc_options(data_size, destructor_fn, options)
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
enum ast_cc_service_type service
static void dummy(char *unused,...)
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
int ast_dns_query_get_rr_type(const struct ast_dns_query *query)
Get the record resource type of a DNS query.
const struct ast_dns_record * ast_dns_record_get_next(const struct ast_dns_record *record)
Get the next DNS record.
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw DNS record.
const struct ast_dns_record * ast_dns_result_get_records(const struct ast_dns_result *result)
Get the first record of a DNS Result.
struct ast_dns_result * ast_dns_query_get_result(const struct ast_dns_query *query)
Get the result information for a DNS query.
int ast_dns_record_get_rr_type(const struct ast_dns_record *record)
Get the resource record type of a DNS record.
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
size_t ast_dns_record_get_data_size(const struct ast_dns_record *record)
Retrieve the size of the raw DNS record.
DNS NAPTR Record Parsing API.
const char * ast_dns_naptr_get_replacement(const struct ast_dns_record *record)
Get the replacement value from a NAPTR record.
const char * ast_dns_naptr_get_flags(const struct ast_dns_record *record)
Get the flags from a NAPTR record.
const char * ast_dns_naptr_get_service(const struct ast_dns_record *record)
Get the service from a NAPTR record.
unsigned short ast_dns_naptr_get_order(const struct ast_dns_record *record)
Get the order from a NAPTR record.
struct ast_dns_query * ast_dns_query_set_get(const struct ast_dns_query_set *query_set, unsigned int index)
Retrieve a query from a query set.
struct ast_dns_query_set * ast_dns_query_set_create(void)
Create a query set to hold queries.
size_t ast_dns_query_set_num_queries(const struct ast_dns_query_set *query_set)
Retrieve the number of queries in a query set.
int ast_dns_query_set_add(struct ast_dns_query_set *query_set, const char *name, int rr_type, int rr_class)
Add a query to a query set.
void ast_dns_query_set_resolve_async(struct ast_dns_query_set *query_set, ast_dns_query_set_callback callback, void *data)
Asynchronously resolve queries in a query set.
void * ast_dns_query_set_get_data(const struct ast_dns_query_set *query_set)
Retrieve user specific data from a query set.
DNS SRV Record Parsing API.
const char * ast_dns_srv_get_host(const struct ast_dns_record *record)
Get the hostname from an SRV record.
unsigned short ast_dns_srv_get_port(const struct ast_dns_record *record)
Get the port from an SRV record.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
#define DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
void ast_sip_initialize_resolver(void)
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
The result of a DNS query.
A ast_taskprocessor structure is a singleton by name.
An API for managing task processing threads that can be shared across modules.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
struct ast_taskprocessor * ast_threadpool_serializer_get_current(void)
Get the threadpool serializer currently associated with this thread.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
#define AST_VECTOR(name, type)
Define a vector structure.
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.