22 #include <pjlib-util/errno.h> 24 #include <arpa/nameser.h> 36 #ifdef HAVE_PJSIP_EXTERNAL_RESOLVER 52 struct targets resolving;
120 if (transport == PJSIP_TRANSPORT_UDP) {
122 }
else if (transport == PJSIP_TRANSPORT_TCP) {
124 }
else if (transport == PJSIP_TRANSPORT_TLS) {
126 }
else if (transport == PJSIP_TRANSPORT_UDP6) {
128 }
else if (transport == PJSIP_TRANSPORT_TCP6) {
130 }
else if (transport == PJSIP_TRANSPORT_TLS6) {
169 target.
port = pjsip_transport_get_default_port_for_type(transport);
176 ast_debug(2,
"[%p] Added target '%s' with record type '%d', transport '%s', and port '%d'\n",
177 resolve, name, rr_type, pjsip_transport_get_type_desc(transport), target.
port);
196 char addr[PJ_INET6_ADDRSTRLEN + 10];
199 for (idx = 0; idx < resolve->
addresses.count; ++idx) {
200 pj_sockaddr_print(&resolve->
addresses.entry[idx].addr, addr,
sizeof(addr), 3);
203 pjsip_transport_get_type_desc(resolve->
addresses.entry[idx].type));
207 ast_debug(2,
"[%p] Invoking user callback with '%d' addresses\n", resolve, resolve->
addresses.count);
241 ast_debug(2,
"[%p] NAPTR service %s skipped as transport is unavailable\n",
247 ast_debug(2,
"[%p] NAPTR service %s received with unsupported flags '%s'\n",
272 struct targets resolving;
273 int idx, address_count = 0, have_naptr = 0, have_srv = 0;
274 unsigned short order = 0;
275 int strict_order = 0;
277 ast_debug(2,
"[%p] All parallel queries completed\n", resolve);
299 ast_debug(2,
"[%p] No result information for target '%s' of type '%d'\n", resolve,
310 if (have_naptr || have_srv) {
311 ast_debug(2,
"[%p] %s record being skipped on target '%s' because NAPTR or SRV record exists\n",
318 if (address_count == PJSIP_MAX_RESOLVED_ADDRESSES) {
327 resolve->
addresses.entry[address_count].addr_len =
sizeof(pj_sockaddr_in);
328 pj_sockaddr_init(pj_AF_INET(), &resolve->
addresses.entry[address_count].addr,
NULL,
333 resolve->
addresses.entry[address_count].addr_len =
sizeof(pj_sockaddr_in6);
334 pj_sockaddr_init(pj_AF_INET6(), &resolve->
addresses.entry[address_count].addr,
NULL,
343 ast_debug(2,
"[%p] SRV record being skipped on target '%s' because NAPTR record exists\n",
352 if ((target->
transport & PJSIP_TRANSPORT_IPV6) &&
357 }
else if (!(target->
transport & PJSIP_TRANSPORT_IPV6) &&
364 if (!(target->
transport & PJSIP_TRANSPORT_IPV6) &&
376 ast_debug(2,
"[%p] NAPTR record skipped because order '%hu' does not match strict order '%hu'\n",
381 if (target->
transport == PJSIP_TRANSPORT_UNSPECIFIED || target->
transport == PJSIP_TRANSPORT_UDP ||
382 target->
transport == PJSIP_TRANSPORT_UDP6) {
384 target->
transport == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : target->
transport);
386 if (target->
transport == PJSIP_TRANSPORT_UNSPECIFIED || target->
transport == PJSIP_TRANSPORT_TCP ||
387 target->
transport == PJSIP_TRANSPORT_TCP6) {
389 target->
transport == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_TCP : target->
transport);
391 if (target->
transport == PJSIP_TRANSPORT_UNSPECIFIED || target->
transport == PJSIP_TRANSPORT_TLS ||
392 target->
transport == PJSIP_TRANSPORT_TLS6) {
394 target->
transport == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_TLS : target->
transport);
408 resolve->
addresses.count = address_count;
415 ast_debug(2,
"[%p] New queries added, performing parallel resolution again\n", resolve);
421 ast_debug(2,
"[%p] Resolution completed - %d viable targets\n", resolve, resolve->
addresses.count);
447 if (pj_inet_aton(host, &dummy) > 0) {
451 if (pj_inet_pton(pj_AF_INET6(), host, &dummy6) == PJ_SUCCESS) {
468 static void sip_resolve(pjsip_resolver_t *resolver, pj_pool_t *
pool,
const pjsip_host_info *target,
469 void *token, pjsip_resolver_callback *cb)
472 pjsip_transport_type_e
type = target->type;
474 char host[NI_MAXHOST];
479 ast_debug(2,
"Performing SIP DNS resolution of target '%s'\n", host);
485 if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
488 if (target->flag & PJSIP_TRANSPORT_SECURE) {
489 type = PJSIP_TRANSPORT_TLS;
490 }
else if (target->flag & PJSIP_TRANSPORT_RELIABLE) {
491 type = PJSIP_TRANSPORT_TCP;
497 if (ip_addr_ver || target->addr.port) {
498 type = PJSIP_TRANSPORT_UDP;
501 if (ip_addr_ver == 6) {
502 type = (pjsip_transport_type_e)((
int) type | PJSIP_TRANSPORT_IPV6);
506 ast_debug(2,
"Transport type for target '%s' is '%s'\n", host, pjsip_transport_get_type_desc(type));
511 .entry[0].type =
type,
515 if (ip_addr_ver == 4) {
516 addresses.entry[0].addr_len =
sizeof(pj_sockaddr_in);
517 pj_sockaddr_init(pj_AF_INET(), &addresses.entry[0].addr,
NULL, 0);
518 pj_inet_aton(&target->addr.host, &addresses.entry[0].addr.ipv4.sin_addr);
520 addresses.entry[0].addr_len =
sizeof(pj_sockaddr_in6);
521 pj_sockaddr_init(pj_AF_INET6(), &addresses.entry[0].addr,
NULL, 0);
522 pj_inet_pton(pj_AF_INET6(), &target->addr.host, &addresses.entry[0].addr.ipv6.sin6_addr);
525 pj_sockaddr_set_port(&addresses.entry[0].addr, !target->addr.port ? pjsip_transport_get_default_port_for_type(type) : target->addr.port);
527 ast_debug(2,
"Target '%s' is an IP address, skipping resolution\n", host);
529 cb(PJ_SUCCESS, token, &addresses);
536 cb(PJ_ENOMEM, token,
NULL);
545 cb(PJ_ENOMEM, token,
NULL);
549 ast_debug(2,
"[%p] Created resolution tracking for target '%s'\n", resolve, host);
552 if (!target->addr.port) {
553 char srv[NI_MAXHOST];
568 if (type == PJSIP_TRANSPORT_UNSPECIFIED ||
571 if (snprintf(srv,
sizeof(srv),
"_sips._tcp.%s", host) < NI_MAXHOST) {
573 type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_TLS : type, 0);
576 if (type == PJSIP_TRANSPORT_UNSPECIFIED ||
579 if (snprintf(srv,
sizeof(srv),
"_sip._tcp.%s", host) < NI_MAXHOST) {
581 type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_TCP : type, 0);
584 if (type == PJSIP_TRANSPORT_UNSPECIFIED ||
587 if (snprintf(srv,
sizeof(srv),
"_sip._udp.%s", host) < NI_MAXHOST) {
589 type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : type, 0);
596 res |=
sip_resolve_add(resolve, host, T_AAAA, C_IN, (type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP6 : type), target->addr.port);
598 res |=
sip_resolve_add(resolve, host, T_AAAA, C_IN, type | PJSIP_TRANSPORT_IPV6, target->addr.port);
603 res |=
sip_resolve_add(resolve, host, T_A, C_IN, (type == PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : type), target->addr.port);
608 cb(PJ_ENOMEM, token,
NULL);
612 ast_debug(2,
"[%p] No resolution queries for target '%s'\n", resolve, host);
614 cb(PJLIB_UTIL_EDNSNOANSWERREC, token,
NULL);
620 ast_debug(2,
"[%p] Starting initial resolution using parallel queries for target '%s'\n", resolve, host);
638 pjsip_tpmgr_fla2_param prm;
641 pjsip_tpmgr_fla2_param_default(&prm);
644 if (transport == PJSIP_TRANSPORT_UDP) {
646 }
else if (transport == PJSIP_TRANSPORT_TCP) {
648 }
else if (transport == PJSIP_TRANSPORT_TLS) {
650 }
else if (transport == PJSIP_TRANSPORT_UDP6) {
652 }
else if (transport == PJSIP_TRANSPORT_TCP6) {
654 }
else if (transport == PJSIP_TRANSPORT_TLS6) {
657 ast_verb(2,
"'%s' is an unsupported SIP transport\n", name);
662 pool, &prm) == PJ_SUCCESS) {
663 ast_verb(2,
"'%s' is an available SIP transport\n", name);
666 ast_verb(2,
"'%s' is not an available SIP transport, disabling resolver support for it\n",
719 ast_log(
LOG_NOTICE,
"The version of PJSIP in use does not support external resolvers, using PJSIP provided resolver\n");
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
const struct ast_dns_record * ast_dns_record_get_next(const struct ast_dns_record *record)
Get the next DNS record.
static int sip_resolve_invoke_user_callback(void *data)
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw DNS record.
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
static int sip_available_transports[]
Available transports on the system.
static void dummy(char *unused,...)
static void sip_resolve_destroy(void *data)
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
struct ast_dns_query_set * ast_dns_query_set_create(void)
Create a query set to hold queries.
enum ast_cc_service_type service
size_t ast_dns_record_get_data_size(const struct ast_dns_record *record)
Retrieve the size of the raw DNS record.
pjsip_server_addresses addresses
Current viable server addresses.
#define ao2_alloc_options(data_size, destructor_fn, options)
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.
const char * ast_dns_naptr_get_service(const struct ast_dns_record *record)
Get the service from a NAPTR record.
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.
struct ast_taskprocessor * ast_threadpool_serializer_get_current(void)
Get the threadpool serializer currently associated with this thread.
#define ast_verb(level,...)
unsigned short ast_dns_srv_get_port(const struct ast_dns_record *record)
Get the port from an SRV record.
static void sip_resolve_callback(const struct ast_dns_query_set *query_set)
const char * ast_dns_srv_get_host(const struct ast_dns_record *record)
Get the hostname from an SRV record.
#define ast_strlen_zero(foo)
AST_VECTOR(targets, struct sip_target)
The vector used for current targets.
pjsip_transport_type_e transport
The transport to be used.
#define ast_debug(level,...)
Log a DEBUG message.
void * token
User provided data.
Structure which contains transport+port information for an active query.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
pjsip_resolver_callback * callback
Callback to invoke upon completion.
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.
#define ao2_ref(o, delta)
struct ast_dns_query_set * queries
Active queries.
static int sip_resolve_add(struct sip_resolve *resolve, const char *name, int rr_type, int rr_class, pjsip_transport_type_e transport, int port)
The result of a DNS query.
const char * ast_dns_naptr_get_flags(const struct ast_dns_record *record)
Get the flags from a NAPTR record.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
struct ast_dns_result * ast_dns_query_get_result(const struct ast_dns_query *query)
Get the result information for a DNS query.
static int sip_transport_is_available(enum pjsip_transport_type_e transport)
const struct ast_dns_record * ast_dns_result_get_records(const struct ast_dns_result *result)
Get the first record of a DNS Result.
An API for managing task processing threads that can be shared across modules.
struct targets resolving
Addresses currently being resolved, indexed based on index of queries in query set.
static int sip_resolve_handle_naptr(struct sip_resolve *resolve, const struct ast_dns_record *record, const char *service, pjsip_transport_type_e transport)
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
int ast_dns_query_get_rr_type(const struct ast_dns_query *query)
Get the record resource type of a DNS query.
DNS NAPTR Record Parsing API.
unsigned short ast_dns_naptr_get_order(const struct ast_dns_record *record)
Get the order from a NAPTR record.
A ast_taskprocessor structure is a singleton by name.
static int sip_replace_resolver(void *data)
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
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.
static void sip_resolve(pjsip_resolver_t *resolver, pj_pool_t *pool, const pjsip_host_info *target, void *token, pjsip_resolver_callback *cb)
struct ast_taskprocessor * serializer
Serializer to run async callback into pjlib.
const char * ast_dns_naptr_get_replacement(const struct ast_dns_record *record)
Get the replacement value from a NAPTR record.
void ast_sip_initialize_resolver(void)
DNS SRV Record Parsing API.
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.
static int sip_resolve_get_ip_addr_ver(const pj_str_t *host)
int ast_dns_record_get_rr_type(const struct ast_dns_record *record)
Get the resource record type of a DNS record.
static void sip_check_transport(pj_pool_t *pool, pjsip_transport_type_e transport, const char *name)
#define DEBUG_ATLEAST(level)
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.
Structure which keeps track of resolution.
sip_resolver_transport
Our own defined transports, reduces the size of sip_available_transports.
static pjsip_ext_resolver ext_resolver
External resolver implementation for PJSIP.