Loading...
Searching...
No Matches
Sofia SIP User Agent Library - "sresolv" - Asynchronous DNS Resolver

# Module Information

The Sofia sresolv module consists of an asynchronous DNS resolver with EDNS extensions. The interface to library using su_root_t is declared in <sofia-sip/sresolv.h>.

An alternative interface is defined by <sofia-resolv/sres.h>, <sofia-resolv/sres_record.h>, <sofia-resolv/sres_async.h>, and <sofia-resolv/sres_cache.h>.

See also
  RFC 1034, RFC 1035, RFC 1886, RFC 2671, RFC 2782, RFC 2915

Contact:\n Pekka Pessi <Pekka.Pessi@nokia-email.address.hidden>

Status:\n Sofia SIP Core library

License:\n LGPL

Todo
  Caching Policy and Cache Poisoning

The policy for caching non-authoritave entries should be solved.

# Why Sofia Resolver?

The generally available open source DNS libraries are either synchronous, that is, they block the thread making the query or they resolve only host names. As SIP protocol uses NAPTR and SRV records in addition ot the usual A or AAAA records, these DNS libraries are inadequate for a SIP application.

Sofia resolver uses the usual configuration for DNS. In Unix-based systems, the DNS configuration is stored in the file /etc/resolv.conf, on Windows, it is available through the registry. Sofia resolvers reloads the configuration when it detect that it has been changed.

In addition to the configuration files, the environment variables SRES_OPTIONS and RES_OPTIONS can be used to change the behaviour of the resolver.

# Using Sofia Resolver

Sofia resolver works usually asynchronously, in other words, it generates a a query, sends it to DNS server and returns immediately to the caller. When a response is received and the query is completed, sresolv signals application through a callback function.

The application can either explicitly poll(2) or select(2) on file descriptors used by resolver and call the driver functions, or it can use su root a pointer to a su_root_t object. Third option is to use resolver synchronously with sres_blocking_query().

There is an internal cache used by sresolv. The query functions add records to the cache: using the cache is made similar as if receiving entries directly from DNS server.

Please note that you have to create a separate resolver object for each thread using Sofia resolver. The resolver objects can share the cache, however.

# Interface in <sofia-sip/sresolv.h>

The simple use of Sofia resolver driven from su_root_t is defined in <sofia-sip/sresolv.h>. The resolver object can be created with sres_resolver_create(). The provided root object takes care of calling the sres_query() and sres_query_sockaddr() callback functions.

#include <sofia-sip/sresolv.h>
sres_resolver_t *sres_resolver_create(su_root_t *root,
char const *resolv_conf,
tag_type_t, tag_value_t, ...);
int sres_resolver_destroy(sres_resolver_t *res);
sres_resolver_t
struct sres_resolver_s sres_resolver_t
Opaque type of DNS resolver object.
Definition sres.h:95
sresolv.h
Easy API for Sofia DNS Resolver.
sres_resolver_destroy
int sres_resolver_destroy(sres_resolver_t *res)
Destroy a resolver object.
Definition sresolv.c:154
sres_resolver_create
sres_resolver_t * sres_resolver_create(su_root_t *root, char const *resolv_conf, tag_type_t, tag_value_t,...)
Create a resolver object using root reactor.
Definition sresolv.c:100
tag_value_t
intptr_t tag_value_t
tag_type_t
struct tag_type_s const * tag_type_t
su_root_t
struct su_root_t su_root_t

# Sending DNS Queries

The second part of interface is used when sending DNS queries:

sres_query_t *sres_query(sres_resolver_t *res,
sres_answer_f *callback,
sres_context_t *context,
int socket,
uint16_t type,
char const *domain);
sres_query_t *sres_query_sockaddr(sres_resolver_t *res,
sres_answer_f *callback,
sres_context_t *context,
int socket,
uint16_t type,
struct sockaddr const *addr);
void sres_query_bind(sres_query_t *q,
sres_answer_f *callback,
sres_context_t *context);
sres_query_t
struct sres_query_s sres_query_t
Opaque type of DNS query object.
Definition sres.h:104
sres_query_bind
SRESPUBFUN void sres_query_bind(sres_query_t *q, sres_answer_f *callback, sres_context_t *context)
Rebind a DNS query.
Definition sres.c:1215
sres_query
SRESPUBFUN sres_query_t * sres_query(sres_resolver_t *res, sres_answer_f *callback, sres_context_t *context, uint16_t type, char const *domain)
Make a DNS query.
Definition sres.c:957
sres_answer_f
void sres_answer_f(sres_context_t *context, sres_query_t *query, sres_record_t **answers)
Prototype for callback function.
Definition sres.h:151
sres_context_t
struct sres_context_s sres_context_t
Application-defined type for sres_query_t context.
Definition sres.h:101
sres_query_sockaddr
SRESPUBFUN sres_query_t * sres_query_sockaddr(sres_resolver_t *res, sres_answer_f *callback, sres_context_t *context, uint16_t type, struct sockaddr const *addr)
Make a reverse DNS query.
Definition sres.c:1152
uint16_t
SU_U16_T uint16_t

# Handling DNS Records

The third part is used to handle the records which were returned by DNS query or stored into the cache:

sres_record_t **sres_cached_answers(sres_resolver_t *res,
uint16_t type,
char const *domain);
sres_record_t **sres_cached_answers_sockaddr(sres_resolver_t *res,
uint16_t type,
struct sockaddr const *addr);
int sres_sort_answers(sres_resolver_t *res, sres_record_t **answers);
int sres_filter_answers(sres_resolver_t *sres, sres_record_t **answers,
uint16_t type);
void sres_free_answers(sres_resolver_t *res, sres_record_t **answers);
void sres_free_answer(sres_resolver_t *res, sres_record_t *answer);
sres_cached_answers
SRESPUBFUN sres_record_t ** sres_cached_answers(sres_resolver_t *res, uint16_t type, char const *domain)
Get a list of matching (type/domain) records from cache.
Definition sres.c:1238
sres_cached_answers_sockaddr
SRESPUBFUN sres_record_t ** sres_cached_answers_sockaddr(sres_resolver_t *res, uint16_t type, struct sockaddr const *addr)
Get a list of matching (type/domain) records from cache.
Definition sres.c:1361
sres_filter_answers
SRESPUBFUN int sres_filter_answers(sres_resolver_t *res, sres_record_t **answers, uint16_t type)
Filter and sort the list of records.
Definition sres.c:1457
sres_sort_answers
SRESPUBFUN int sres_sort_answers(sres_resolver_t *, sres_record_t **answers)
Sort the list of records.
Definition sres.c:1423
sres_free_answers
SRESPUBFUN void sres_free_answers(sres_resolver_t *, sres_record_t **answers)
Free the list records.
Definition sres.c:1496
sres_record_t
union sres_record sres_record_t
Type representing any DNS record.
Definition sres.h:85
sres_free_answer
SRESPUBFUN void sres_free_answer(sres_resolver_t *res, sres_record_t *answer)
Free and zero one record.
Definition sres.c:1484

# Interface in <sofia-resolv/sres.h>

The generic interface to Sofia resolver is defined in <sofia-resolv/sres.h>. The first part of interface consists of functions for handling resolver objects:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sofia-resolv/sres.h>
sres_resolver_t *sres_resolver_new(char const *resolv_conf_path);
sres_resolver_t *sres_resolver_new_with_cache(char const *conf_file_path,
sres_cache_t *cache,
char const *options, ...);
sres_resolver_t *sres_resolver_ref(sres_resolver_t *res);
void sres_resolver_unref(sres_resolver_t *res);
sres_resolver_t *sres_resolver_copy(sres_resolver_t *);
void *sres_resolver_set_userdata(sres_resolver_t *res, void *userdata);
void *sres_resolver_get_userdata(sres_resolver_t const *res);
sres.h
Sofia DNS Resolver.
sres_resolver_get_userdata
SRESPUBFUN void * sres_resolver_get_userdata(sres_resolver_t const *res)
Get userdata pointer.
Definition sres.c:848
sres_resolver_copy
SRESPUBFUN sres_resolver_t * sres_resolver_copy(sres_resolver_t *)
Copy a resolver.
Definition sres.c:633
sres_cache_t
struct sres_cache sres_cache_t
Opaque type of DNS cache object.
Definition sres.h:91
sres_resolver_set_userdata
SRESPUBFUN void * sres_resolver_set_userdata(sres_resolver_t *res, void *userdata)
Set userdata pointer.
Definition sres.c:827
sres_resolver_ref
SRESPUBFUN sres_resolver_t * sres_resolver_ref(sres_resolver_t *res)
Increase reference count on a resolver object.
Definition sres.c:807
sres_resolver_new
SRESPUBFUN sres_resolver_t * sres_resolver_new(char const *resolv_conf_path)
New resolver object.
Definition sres.c:623
sres_resolver_unref
SRESPUBFUN void sres_resolver_unref(sres_resolver_t *res)
Decrease the reference count on a resolver object.
Definition sres.c:814
sres_resolver_new_with_cache
SRESPUBFUN sres_resolver_t * sres_resolver_new_with_cache(char const *conf_file_path, sres_cache_t *cache, char const *options,...)
New resolver object.
Definition sres.c:677

## Using Sofia Resolver Synchronously

The blocking interface defined in <sofia-resolv/sres.h> makes it possible to use Sofia resolver synchronously, that is, the function call making the DNS query does not return until the query is responded or it times out.

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sofia-resolv/sres.h>
int sres_blocking_query(sres_resolver_t *res,
uint16_t type,
char const *domain,
sres_record_t ***return_records);
int sres_blocking_query_sockaddr(sres_resolver_t *res,
uint16_t type,
struct sockaddr const *addr,
sres_record_t ***return_records);
sres_blocking_query
SRESPUBFUN int sres_blocking_query(sres_resolver_t *res, uint16_t type, char const *domain, int ignore_cache, sres_record_t ***return_records)
Send a query, wait for answer, return results.
Definition sres_blocking.c:292
sres_blocking_query_sockaddr
SRESPUBFUN int sres_blocking_query_sockaddr(sres_resolver_t *res, uint16_t type, struct sockaddr const *addr, int ignore_cache, sres_record_t ***return_records)
Send a a reverse DNS query, wait for answer, return results.
Definition sres_blocking.c:414

## Asynchronous Interface in <sofia-resolv/sres_async.h>

It is also possible to use resolver asynchronously without su_root_t object.

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sofia-resolv/sres_async.h>
sres_async_t *sres_resolver_set_async(sres_resolver_t *res,
sres_update_f *update,
sres_async_t *async,
int update_all);
sres_async_t *sres_resolver_get_async(sres_resolver_t const *res,
sres_update_f *update);
int sres_resolver_sockets(sres_resolver_t const *res, int *sockets, int n);
void sres_resolver_timer(sres_resolver_t *, int socket);
int sres_resolver_receive(sres_resolver_t *res, int socket);
int sres_resolver_error(sres_resolver_t *res, int socket);
sres_async.h
Asynchronous interface for Sofia DNS Resolver.
sres_update_f
int sres_update_f(sres_async_t *async, sres_socket_t new_socket, sres_socket_t old_socket)
Prototype for update function.
Definition sres_async.h:72
sres_async_t
SRES_ASYNC_T sres_async_t
Application-defined type for context used by asynchronous operation.
Definition sres_async.h:57
sres_resolver_timer
SRESPUBFUN void sres_resolver_timer(sres_resolver_t *, int dummy)
Resolver timer function.
Definition sres.c:2995
sres_resolver_receive
SRESPUBFUN int sres_resolver_receive(sres_resolver_t *, int socket)
Receive DNS response from socket.
Definition sres.c:3447
sres_resolver_sockets
SRESPUBFUN int sres_resolver_sockets(sres_resolver_t *, sres_socket_t *sockets, int n)
Create sockets for resolver.
Definition sres.c:3185
sres_resolver_error
SRESPUBFUN int sres_resolver_error(sres_resolver_t *, int socket)
Receive error message from socket.
Definition sres.c:3362
sres_resolver_get_async
SRESPUBFUN sres_async_t * sres_resolver_get_async(sres_resolver_t const *res, sres_update_f *update)
Get async operation data.
Definition sres.c:885
sres_resolver_set_async
SRESPUBFUN sres_async_t * sres_resolver_set_async(sres_resolver_t *res, sres_update_f *update, sres_async_t *async, int update_all)
Set asynchronous operation data.
Definition sres.c:865

Here is a short code fragment showing how to use resolver driven from su_root_t:

#define SRES_CONTEXT_T struct context
#include <sofia-sip/sresolv.h>
...
struct context
{
...
su_root_t *root;
sres_resolver_t *sres;
sres_query_t *query;
...
} *context;
...
context->sres = sres_resolver_create(context->root, NULL, TAG_END());
...
sres_record_t *results;
results = sres_cached_answers(context->sres, sres_type_naptr, domain);
if (results) {
process_natpr(context, NULL, results);
}
else {
context->query = sres_query(context->sres,
process_natpr, context,
sres_type_naptr, domain);
if (!context->query)
process_naptr(context, NULL, NULL);
}
}
...
void process_natpr(sres_context_t *context,
sres_query_t *q,
sres_record_t *answers[])
{
sres_sort_answers(context->sres, answers);
...
sres_free_answers(context->sres, answers);
}
sres_type_naptr
@ sres_type_naptr
Naming Authority PoinTeR (RFC 2915, sres_naptr_record).
Definition sres_record.h:235
TAG_END
#define TAG_END()

Sofia-SIP 1.12.11devel - Copyright (C) 2006 Nokia Corporation. All rights reserved. Licensed under the terms of the GNU Lesser General Public License.