Skip site navigation (1)Skip section navigation (2)

  
 
  

home | help
udns(3) 		    Library Functions Manual			 udns(3)

NAME
     udns - stub DNS resolver library

SYNOPSYS
     #include <udns.h>
     struct dns_ctx;
     struct dns_query;
     extern struct dns_ctx dns_defctx;
     struct dns_ctx *ctx;
     typedef void dns_query_fn(ctx, void *result, void *data);
     typedef int
     dns_parse_fn(const unsigned char *qnd,
	    const unsigned char *pkt,
	    const unsigned char *cur,
	    const unsigned char *end,
	    void **resultp);

     cc ... -ludns

DESCRIPTION
     The DNS library, udns, implements thread-safe stub DNS resolver functional-
     ity,  which  may  be  used  both traditional, synchronous way and asynchro-
     nously, with application-supplied event loop.

     While DNS works with both TCP and UDP, performing UDP query  first  and  if
     the  result does not fit in UDP buffer (512 bytes max for original DNS pro-
     tocol), retrying the query over TCP, the library uses UDP	only,  but  uses
     EDNS0 (RFC2671) extensions which allows larger UDP buffers.

     The library uses single UDP socket to perform all operations even when ask-
     ing  multiple  nameservers.  This way, it is very simple to use the library
     in asynchronous event-loop applications: an  application  should  add  only
     single socket to the set of filedescriptors it monitors for I/O.

     The library uses two main objects, resolver context of type struct dns_ctx,
     and query structure of type struct dns_query, both are opaque for an appli-
     cation.  Resolver context holds global information about the resolver, such
     as list of nameservers to use, list of active requests and the like.  Query
     objects  holds information about a single DNS query in progress and are al-
     located/processed/freed by the library.   Pointer to query structure may be
     treated as an identifier of an in-progress query and may be used to  cancel
     the asynchronous query or to wait for it to complete.

     Asynchronous  interface  works  as follows.  An application initializes re-
     solver context, submits any number of queries for it using one of	supplied
     dns_submit_XXX()  routines  (each return the query identifier as pointer to
     query structure), waits for input on the UDP socket used  by  the	library,
     and  gives  some  control	to  the  library  by  calling  dns_ioevent() and
     dns_timeouts() routines when appropriate.	The library performs all  neces-
     sary  processing  and executes application supplied callback routine when a
     query completes (either successefully or not), giving it the result if any,
     pointer to the resolver context (from which completion status  may  be  ob-
     tained), and the data pointer supplied by an application when the query has
     been  submitted.	When  submitting a query, an application requests how to
     handle the reply -- to either return raw DNS reply packet for its own  low-
     level  processing,  or it may provide an address of parsing routine of type
     dns_parse_fn to perform conversion of on-wire format into easy to use  data
     structure	(the library provides parsing routines for several commonly used
     resource record types, as well as type-safe higher-level interface that re-
     quests parsing automatically).  The I/O monitoring and timeout handling may
     be either traditional select() or	poll()	based,	or  any  callback-driven
     technique may be used.

     Additionally, the library provides traditional synchronous interface, which
     may  be  intermixed  with asynchronous calls (during synchronous query pro-
     cessing, other asynchronous queries for the same resolver context continued
     to be processed as usual).  An application uses  one  of  numerous  dns_re-
     solve_XXX()  routines  provided by the library to perform a query.  As with
     asynchronous interface, an application may either request to return raw DNS
     packet or type-specific data structure by providing the parsing routine  to
     handle  the  reply.   Every  routine  from  dns_resolve_XXX() series return
     pointer to result or NULL in case of any error.   Query  completion  status
     (or  length  of  the raw DNS packet) is available from the resolver context
     using dns_status() routine, the same way as for the asynchronous interface.

     Internally, library uses on-wire format of domain names, referred to as  DN
     format in this manual page.  This is a series of domain labels with preced-
     ing  length byte, terminated by zero-length label which is integral part of
     the DN format.  There are several routines provided to convert from  tradi-
     tional  asciiz string to DN and back.  Higher-level type-specific query in-
     terface hides the DN format from an application.

COMMON DEFINITIONS
     Every DNS Resource Record (RR) has a type and a class.  The library defines
     several integer constants, DNS_C_XXX and  DNS_T_XXX,  to  use  as	symbolic
     names  for  RR  classes  and  types,  such  as DNS_C_IN for Internet class,
     DNS_T_A for IPv4 address record type and so on.  See udns.h header file for
     complete list of all such constants.

     The following constants are defined in udns.h header file:

     DNS_MAXDN (255 bytes)
	    Maximum length of the domain name in internal (on-wire) DN format.

     DNS_MAXLABEL (63 bytes)
	    Maximum length of a single label in DN format.

     DNS_MAXNAME (1024 bytes)
	    Maximum length of asciiz format of a domain name.

     DNS_HSIZE (12 bytes)
	    Size of header in DNS packet.

     DNS_PORT (53)
	    Default port to use when contacting a DNS server.

     DNS_MAXSERV (6 servers)
	    Maximum number of DNS servers to use.

     DNS_MAXPACKET (512 bytes)
	    Maximum length of DNS UDP packet as specified by original DNS proto-
	    col

     DNS_EDNS0PACKET (4096 bytes)
	    Default length of DNS UDP packet (with EDNS0 extensions) the library
	    uses.  Note that recursive	nameservers  usually  resides  near  the
	    client asking them to resolve names, e.g. on the same LAN segment or
	    even  on  the same host, so UDP packet fragmentation isn't a problem
	    in most cases.  Note also that the size of actual packets will be as
	    many bytes as actual reply size requires, which is smaller than this
	    value in almost all cases.

     Additionally, several constants are defined to simplify work with	raw  DNS
     packets,  such  as  DNS  response	codes  (DNS_R_XXX),  DNS  header  layout
     (DNS_H_XXX) and others.  Again, see udns.h for complete list.  Library  er-
     ror codes (DNS_E_XXX) are described later in this manual page.

RESOLVER CONTEXT
     Resolver  context,  of type struct dns_ctx, is an object which is opaque to
     an application.  Several routines provided by the	library  to  initialize,
     copy  and	free  resolver contexts.  Most other high-level routines in this
     library expects a pointer to resolver context, ctx, as the first  argument.
     There  is a default resolver context available, named dns_defctx.	When the
     context pointer ctx passed to a routine is NULL, dns_defctx is used.   Sev-
     eral resolver contexts may be active at the same time, for example, when an
     application is multi-threaded and each thread uses resolver.

     In  order to use the library, an application should initialize and open one
     or more resolver context objects.	These are  two	separate  actions,  per-
     formed  by  dns_init()  (or  dns_reset()), and dns_open().  Between the two
     calls, an application is free to pefrorm additional initialisation, such as
     setting custom nameservers, options or domain search lists.  Optionally, in
     case no additional custom initialisation is required, dns_init()  may  open
     the context if do_open argument (see below) is non-zero.

     When  initializing resolver context, the library uses information from sys-
     tem file /etc/resolv.conf (see resolv.conf(5)), consults environment  vari-
     ables  $LOCALDOMAIN,  $NSCACHEIP,	$NAMESERVERS and $RES_OPTIONS, and local
     host name to obtain list of local nameservers, domain name search list  and
     various resolver options.

     The following routines to initialize resolver context are available:

     void dns_reset(ctx)
     int dns_init(ctx, int do_open)
	    dns_reset()  resets  a  given  resolver  context  to default values,
	    preparing it to be opened by dns_open().  It is ok to call this rou-
	    tine against opened and active context - all active queries will  be
	    dropped,  sockets  will  be closed and so on.  This routine does not
	    initialize any  parameters	from  system  configuration  files,  use
	    dns_init()	for  this.   There's  no error return - operation always
	    succeeds.  dns_init() does everything dns_reset()  does,  plus  ini-
	    tializes  various parameters of the context according to system con-
	    figuration and process environment variables.  If  do_open	is  non-
	    zero,  dns_init()  calls  dns_open(), so that the whole library ini-
	    tialisation is performed in a single step.

     struct dns_ctx *dns_new(struct dns_ctx *copy)
     void dns_free(ctx)
	    dns_new() allocates new resolver context and copies  all  parameters
	    for  a  given  resolver  context copy, or default context if copy is
	    NULL, and returns pointer to the newly allocated context.  The  con-
	    text  being  copied  should  be  initialized.  dns_new() may fail if
	    there's no memory available to make a copy of copy,  in  which  case
	    the  routine  will return NULL pointer.  dns_free() is used to close
	    associated socket and free resolver context resources and cancelling
	    (abandoming) all active queries associated with it.  It's  an  error
	    to	free dns_defctx, only dynamically allocated contexts returned by
	    dns_new() are allowed to be freed by dns_free().

     int dns_add_serv(ctx, const char *servaddr)
     int dns_add_serv_s(ctx, const struct sockaddr *sa)
     int dns_add_srch(ctx, const char *srch)
	    Add an element to list of nameservers  (dns_add_serv(),  as  asciiz-
	    string   servaddr	with  an  IP  address  of  the	nameserver,  and
	    dns_add_serv_s(), as initialized socket address sa), or search  list
	    (dns_add_srch(),  as a pointer to domain name) for the given context
	    ctx.  If the last argument is a NULL pointer, the corresponding list
	    (search or nameserver) is reset instead.  Upon  successeful  comple-
	    tion,  each  routine  returns  new number of elements in the list in
	    question.  On error, negative value is returned and global	variable
	    errno  is  set  appropriately.   It  is an error to call any of this
	    functions if the context is opened (after dns_open()  or  dns_init()
	    with non-zero argument).

     int dns_set_opts(ctx, const char *opts)
	    set  resolver  context  options from opts string, in the same way as
	    processing options statement in resolv.conf and  $RES_OPTIONS  envi-
	    ronment  variable.	 Return  number  of unrecognized/invalid options
	    found (all recognized and valid options gets processed).

     void dns_set_opt(ctx, int opt, val)
	    TODO The flags argument is a bitmask with  the  following  bits  de-
	    fined:

	    DNS_NOSRCH
		   do not perform domain name search in search list.

	    DNS_NORD
		   do  not request recursion when performing queries (i.e. don't
		   set RD flag in querues).

	    DNS_AAONLY
		   request authoritative answers  only	(i.e.  set  AA	flag  in
		   queries).

     int dns_open(ctx)
     int dns_sock(const ctx)
     void dns_close(ctx)
	    dns_open()	opens  the  UDP  socket  used for queries if not already
	    open, and return associated filedescriptor	(or  negative  value  in
	    case  of  error).	Before	any  query can be submitted, the context
	    should be opened using this routine.  And before opening,  the  con-
	    text  should  be  initialized.   dns_sock() return the UDP socket if
	    open, or -1 if not.  dns_close() closes the UDP  socket  if  it  was
	    open, and drops all active queries if any.

     int dns_active(const ctx)
	    return number of active queries queued for the given context ctx, or
	    zero if none.

     int dns_status(const ctx)
	    return  status code from last operation.  When using synchronous in-
	    terface, this is the query completion  status  of  the  last  query.
	    With  asynchronous interface, from within the callback routine, this
	    is the query completion status of the query for which  the	callback
	    is	being  called.	 When  query submission fails, this is the error
	    code indicating failure reason.  All error codes  are  negative  and
	    are represented by DNS_E_XXX constants described below.

     void dns_ioevent(ctx, time_t now)
	    this  routine  may be called by an application to process I/O events
	    on the UDP socket used by the library, as  returned  by  dns_sock().
	    The  routine  tries to receive incoming UDP datagram from the socket
	    and process it.  The socket is set up to be non-blocking, so  it  is
	    safe  to call the routine even if there's no data to read.	The rou-
	    tine will process as many datagrams as are queued for the socket, so
	    it is safe to use it with either level-triggered  or  edge-triggered
	    I/O  monitoring model.  The now argument is either a current time as
	    returned by time(), or 0, in which case the routine will obtain cur-
	    rent time by it's own.

     int dns_timeouts(ctx, int maxwait, time_t now)
	    process any pending timeouts and return number of secounds from cur-
	    rent time (now if it is not 0) to the time when  the  library  wants
	    the  application to pass it control to process more queued requests.
	    In case when there are no requests pending, this time  is  -1.   The
	    routine  will  not request a time larger than maxwait secounds if it
	    is greather or equal to zero.  If now is 0, the routine will  obtain
	    current  time  by it's own; when it is not 0, it should contain cur-
	    rent time as returned by time().

     typedef void dns_utm_fn(ctx, int timeout, void *data)
     void dns_set_tmcbck(ctx, dns_utm_fn *utmfn, void *data)
	    An application may use custom callback-based I/O multiplexing mecha-
	    nism.  Usually such a mechanism have concept  of  a  timer,  and  an
	    ability  to  register  a timer event in a form of a callback routine
	    which will be executed after certain amount of time.   In  order  to
	    use  such  an  event mechanism, udns provides an ability to register
	    and de-register timer events necessary for internal processing using
	    whatever event mechanism an application uses.  For this to work,  it
	    is	possible  to  assotiate a pointer to a routine that will perform
	    necessary work for (de)registering timer events  with  a  given  re-
	    solver  context,  and  udns  will  call  that routine at appropriate
	    times.  Prototype of such a routine is shown by  dns_utm_fn  typedef
	    above.   Libudns  assotiates  single  timer  with  resolver context.
	    User-supplied utmfn routine will be called by the library  with  the
	    following arguments:

	    ctx == NULL
		   delete  user  timer, at context free time or when an applica-
		   tion changes user timer  request  routine  using  dns_set_tm-
		   cbck();

	    ctx != NULL, timeout < 0
		   don't fire timer anymore, when there are no active requests;

	    ctx != NULL, timeout == 0
		   fire timer at the next possibility, but not immediately;

	    ctx != NULL, timeout > 0
		   fire timer after timeout seconds after now.

	    The  data  argument passed to the routine will be the same as passed
	    to dns_set_tmcbck().

	    When a timer expires, an application should call dns_timeouts() rou-
	    tine (see below).  Non-callback timer usage is provided too.

     XXXX TODO: some more resolver context routines, like dns_set_dbgfn() etc.

QUERY INTERFACE
     There are two ways to perform DNS	queries:  traditional  synchronous  way,
     when  udns  performs all the necessary processing and return control to the
     application only when the query completes, and asynchronous  way,	when  an
     application submits one or more queries to the library using given resolver
     context,  and waits for completion by monitoring filedescriptor used by li-
     brary and calling library routines to process input on that filedescriptor.
     Asynchronous mode works with callback routines: an application supplies  an
     address  of  a  routine  to  execute  when  the query completes, and a data
     pointer, which is passed to the callback routine.

     Queries are submitted to the library in a	form  of  struct dns_query.   To
     perform  asynchronous  query,  an	application  calls  one  of the dns_sub-
     mit_XXX() rounines, and provides necessary information for a callback,  to-
     gether  with  all	the query parameters.  When the query completes, library
     will call application-supplied callback routine,  giving  it  the	resolver
     context (which holds query completion status), dynamically allocated result
     (which  will  be  either raw DNS packet or, if applicatin requested parsing
     the result by specifying non-NULL parse routine, ready-to-use type-specific
     structure), and a data pointer provided by an application when it submitted
     the query.  It is the application who's responsible for freeing the  result
     memory.

     Generic query callback routine looks like this:
     typedef void
     dns_query_fn(ctx, void *result, void *data)
     Type-specific query interface expects similar form of callback routine with
     the  only	difference  in type of result argument, which will be pointer to
     specific data structure (decoded reply) instead of this void pointer to raw
     DNS packet data.

     Result parsing routine looks like this:
     typedef int
     dns_parse_fn(const unsigned char *qdn,
	   const unsigned char *pkt,
	   const unsigned char *cur,
	   const unsigned char *end,
	   void **resultp);
     When called by the library, the arguments are as follows: pkt points to the
     start of the packet received; end points past the end  of	the  packet  re-
     ceived;  cur  points  past the query DN in the query section of the packet;
     qdn points to the original query DN.  The routine should allocate a  single
     buffer  to  hold the result, parse the reply filling in the buffer, and re-
     turn the buffer using resultp argument.  It returns 0 in case of error,  or
     udns  error  code (DNS_E_XXX constants) in case of error.	Note that by the
     time when the parse routine is called by the  library,  packet  is  already
     verified  to  be a reply to the original query, by matching query DN, query
     class and query type.

     Type-specific query interface supplies necessary parsing routines automati-
     cally.

     In case of error, query completion status as returned  by	dns_status(ctx),
     will contain one of the following values:

     positive value
	    length of raw DNS packet if parsing is not requested.

     0	    the query was successeful and the reply points to type-specific data
	    structure.

     DNS_E_TEMPFAIL
	    temporary error, the resolver nameserver was not able to process our
	    query or timed out.

     DNS_E_PROTOCOL
	    protocol error, a nameserver returned malformed reply.

     DNS_E_NXDOMAIN
	    the domain name does not exist.

     DNS_E_NODATA
	    there is no data of requested type found.

     DNS_E_NOMEM
	    out of memory while processing request.

     DNS_E_BADQUERY
	    some  aspect  of  the query (most common is the domain name in ques-
	    tion) is invalid, and the library can't even start a query.

     Library provides two series of routines which uses similar interface -- one
     for asynchronous queries and another for synchronous  queries.   There  are
     two  general  low-level routines in each series to submit (asynchronous in-
     terface) and resolve (synchronous interface) queries, as  well  as  several
     type-specific  routines  with  more  easy-to-use  interfaces.  To submit an
     asynchronous query, use one of dns_submit_XXX() routine, each of which  ac-
     cepts  query parameters, pointers to callback routine and to callback data,
     and optional current time hint.  Note type-specific  dns_submit_XXX()  rou-
     tines  expects specific type of the callback routine as well, which accepts
     reply as a pointer to corresponding structure, not a void pointer).   Every
     dns_submit_XXX() routine return pointer to internal query structure of type
     struct dns_query, used as an identifier for the given query.

     To  resolve  a  query synchronously, use one of dns_resolve_XXX() routines,
     which accepts the same query parameters (but not the callback pointers)  as
     corresponding  dns_submit_XXX(),  and return the query result, which is the
     same as passed to the callback routine in case of asynchronous interface.

     In either case, the result memory (if the query completed successefully) is
     dynamically allocated and should be freed by an application.  If the  query
     failed  for  any  reason, the result will be NULL, and error status will be
     available from dns_status(ctx) routine as shown above.

     struct dns_query *
     dns_submit_dn(ctx,
	  const unsigned char *dn, qcls, qtyp, flags,
	  parse, cbck, data)
     struct dns_query *
     dns_submit_p(ctx,
	  const char *name, qcls, qtyp, flags,
	  parse, cbck, data)
	enum dns_class qcls;
	enum dns_type qtyp;
	int flags;
	dns_parse_fn *parse;
	dns_query_fn *cbck;
	void *data;
	    submit a query for processing for the given  resolver  context  ctx.
	    Two  routines  differs only in 3rd argument, which is domain name in
	    DN format (dn) or asciiz string (name).  The query will be performed
	    for the given domain name, with type qtyp in class qcls,  using  op-
	    tion  bits	in  flags,  using RR parsing routine pointed by parse if
	    not-NULL, and upon completion, cbck function will be called with the
	    data argument.  In case of successeful query submission, the routine
	    return pointer to internal query structure which may be  treated  as
	    an	identifier  of the query as used by the library, and may be used
	    as an argument for dns_cancel() routine.  In  case	of  error,  NULL
	    will be returned, and context error status (available using dns_sta-
	    tus()  routine)  will  be  set to corresponding error code, which in
	    this case may be DNS_E_BADQUERY  if  the  name  of	dn  is	invalid,
	    DNS_E_NOMEM  if there's no memory available to allocate query struc-
	    ture, or DNS_E_TEMPFAIL if an internal error occurred.

     void *dns_resolve_dn(ctx,
	  const unsigned char *dn, qcls, qtyp, flags, parse);
     void *dns_resolve_p(ctx,
	  const char *name, qcls, qtyp, flags, parse)
	enum dns_class qcls;
	enum dns_type qtyp;
	int flags;
	dns_parse_fn *parse;
	    synchronous interface.  The routines perform all the steps necessary
	    to resolve the given query and return the  result.	 If  there's  no
	    positive  result  for  any reason, all the routines return NULL, and
	    set context error status (available using dns_status()  routine)  to
	    indicate the error code.  If the query was successeful, context sta-
	    tus  code will contain either the length of the raw DNS reply packet
	    if parse argument was NULL	(in  which  case  the  return  value  is
	    pointer  to  the  reply  DNS packet), or 0 (in which case the return
	    value is the result of parse routine).   If  the  query  successeful
	    (return  value is not NULL), the memory returned was dynamically al-
	    located by the library and should be free()d  by  application  after
	    use.

     void *dns_resolve(ctx, struct dns_query *q)
	    wait  for  the given query q, as returned by one of dns_submit_XXX()
	    routines, for completion, and return the result.  The callback  rou-
	    tine will not be called for this query.  After completion, the query
	    identifier q is not valid. Both dns_resolve_dn() and dns_resolve_p()
	    are  just  wrappers  around  corresponding	submit routines and this
	    dns_resolve() routine.

     void dns_cancel(ctx, struct dns_query *q)
	    cancel an active query q, without calling a callback routine.  After
	    completion, the query identifier q is not valid.

TYPE-SPECIFIC QUERIES
     In addition to the generic low-level query interface, the library	provides
     a	set  of  routines  to perform specific queries in a type-safe manner, as
     well as parsers for several well-known resource record types.  The  library
     implements  high-level  interface	for A, AAAA, PTR, MX and TXT records and
     DNSBL and RHSBL functionality.  These routines returns  specific  types  as
     result  of  a  query,  instead of raw DNS packets.  The following types and
     routines are available.

     struct dns_rr_null {
       char *dnsn_qname;     /* original query name */
       char *dnsn_cname;     /* canonical name */
       unsigned dnsn_ttl;    /* Time-To-Live (TTL) value */
       int dnsn_nrr;	     /* number of records in the set */
     };

     NULL RR set, used as a base for all other RR  type  structures.   Every  RR
     structure	as  used  by  the  library  have  four	standard  fields  as  in
     struct dns_rr_null.

   IN A Queries
     struct dns_rr_a4 {       /* IN A RRset */
       char *dnsa4_qname;     /* original query name */
       char *dnsa4_cname;     /* canonical name */
       unsigned dnsa4_ttl;    /* Time-To-Live (TTL) value */
       int dnsa4_nrr;	      /* number of addresses in the set */
       struct in_addr dnsa4_addr[]; /* array of addresses */
     };
     typedef void
       dns_query_a4_fn(ctx, struct dns_rr_a4 *result, data)
     dns_parse_fn dns_parse_a4;
     struct dns_query *
     dns_submit_a4(ctx, const char *name, int flags,
	dns_query_a4_fn *cbck, data);
     struct dns_rr_a4 *
     dns_resolve_a4(ctx, const char *name, int flags);

     The dns_rr_a4 structure holds a result of an IN A query, which is an  array
     of  IPv4  addresses.   Callback  routine for IN A queries expected to be of
     type dns_query_a4_fn, which expects pointer to dns_rr_a4 structure as query
     result instead of raw DNS packet.	The dns_parse_a4() is  used  to  convert
     raw  DNS  reply  packet into dns_rr_a4 structure (it is used internally and
     may be used directly too with generic query interface).  Routines	dns_sub-
     mit_a4()  and  dns_resolve_a4() are used to perform A IN queries in a type-
     safe manner.  The name parameter is the domain name in question, and  flags
     is query flags bitmask, with one bit, DNS_NOSRCH, of practical interest (if
     the  name is absolute, that is, it ends up with a dot, DNS_NOSRCH flag will
     be set automatically).

   IN AAAA Queries
     struct dns_rr_a6 {       /* IN AAAA RRset */
       char *dnsa6_qname;     /* original query name */
       char *dnsa6_cname;     /* canonical name */
       unsigned dnsa6_ttl;    /* Time-To-Live (TTL) value */
       int dnsa6_nrr;	      /* number of addresses in the set */
       struct in6_addr dnsa6_addr[]; /* array of addresses */
     };
     typedef void
       dns_query_a6_fn(ctx, struct dns_rr_a6 *result, data)
     dns_parse_fn dns_parse_a6;
     struct dns_query *
     dns_submit_a6(ctx, const char *name, int flags,
	dns_query_a6_fn *cbck, data);
     struct dns_rr_a6 *
     dns_resolve_a6(ctx, const char *name, int flags);

     The dns_rr_a6 structure holds a result of an IN AAAA query, which is an ar-
     ray of IPv6 addresses.  Callback routine for IN AAAA queries expected to be
     of type dns_query_a6_fn, which expects pointer to	dns_rr_a6  structure  as
     query result instead of raw DNS packet.  The dns_parse_a6() is used to con-
     vert  raw	DNS reply packet into dns_rr_a6 structure (it is used internally
     and may be used directly  too  with  generic  query  interface).	Routines
     dns_submit_a6() and dns_resolve_a6() are used to perform AAAA IN queries in
     a type-safe manner.  The name parameter is the domain name in question, and
     flags is query flags bitmask, with one bit, DNS_NOSRCH, of practical inter-
     est  (if  the  name is absolute, that is, it ends up with a dot, DNS_NOSRCH
     flag will be set automatically).

   IN PTR Queries
     struct dns_rr_ptr {       /* IN PTR RRset */
       char *dnsptr_qname;     /* original query name */
       char *dnsptr_cname;     /* canonical name */
       unsigned dnsptr_ttl;    /* Time-To-Live (TTL) value */
       int dnsptr_nrr;	       /* number of domain name pointers */
       char *dnsptr_ptr[];     /* array of domain name pointers */
     };
     typedef void
       dns_query_ptr_fn(ctx, struct dns_rr_ptr *result, data)
     dns_parse_fn dns_parse_ptr;
     struct dns_query *
     dns_submit_a4ptr(ctx, const struct in_addr *addr,
	dns_query_ptr_fn *cbck, data);
     struct dns_rr_ptr *
     dns_resolve_a4ptr(ctx, const struct in_addr *addr);
     struct dns_query *
     dns_submit_a6ptr(ctx, const struct in6_addr *addr,
	dns_query_ptr_fn *cbck, data);
     struct dns_rr_ptr *
     dns_resolve_a6ptr(ctx, const struct in6_addr *addr);

     The dns_rr_ptr structure holds a result of an IN PTR query, which is an ar-
     ray of domain name pointers for a given IPv4  or  IPv6  address.	Callback
     routine  for  IN PTR queries expected to be of type dns_query_ptr_fn, which
     expects pointer to dns_rr_ptr structure as query result instead of raw  DNS
     packet.   The  dns_parse_ptr() is used to convert raw DNS reply packet into
     dns_rr_ptr structure (it is used internally and may be  used  directly  too
     with  generic  query  interface).	 Routines dns_submit_a4ptr() and dns_re-
     solve_a4ptr() are used to perform IN PTR queries for IPv4	addresses  in  a
     type-safe	manner.  Routines dns_submit_a6ptr() and dns_resolve_a6ptr() are
     used to perform IN PTR queries for IPv6 addresses.

   IN MX Queries
     struct dns_mx {	      /* single MX record */
       int priority;	      /* priority value of this MX */
       char *name;	      /* domain name of this MX */
     };
     struct dns_rr_mx {       /* IN MX RRset */
       char *dnsmx_qname;     /* original query name */
       char *dnsmx_cname;     /* canonical name */
       unsigned dnsmx_ttl;    /* Time-To-Live (TTL) value */
       int dnsmx_nrr;	      /* number of mail exchangers in the set */
       struct dns_mx dnsmx_mx[]; /* array of mail exchangers */
     };
     typedef void
       dns_query_mx_fn(ctx, struct dns_rr_mx *result, data)
     dns_parse_fn dns_parse_mx;
     struct dns_query *
     dns_submit_mx(ctx, const char *name, int flags,
	dns_query_mx_fn *cbck, data);
     struct dns_rr_mx *
     dns_resolve_mx(ctx, const char *name, int flags);

     The dns_rr_mx structure holds a result of an IN MX query, which is an array
     of mail exchangers for a given domain.  Callback routine for IN MX  queries
     expected  to be of type dns_query_mx_fn, which expects pointer to dns_rr_mx
     structure as query result instead of raw DNS packet.  The dns_parse_mx() is
     used to convert raw DNS reply packet into dns_rr_mx structure (it	is  used
     internally  and  may  be  used  directly too with generic query interface).
     Routines dns_submit_mx() and dns_resolve_mx() are used  to  perform  IN  MX
     queries  in  a  type-safe manner.	The name parameter is the domain name in
     question, and flags is query flags bitmask, with one  bit,  DNS_NOSRCH,  of
     practical	interest  (if  the  name is absolute, that is, it ends up with a
     dot, DNS_NOSRCH flag will be set automatically).

   TXT Queries
     struct dns_txt {	       /* single TXT record */
       int len; 	       /* length of the text */
       unsigned char *txt;     /* pointer to the text */
     };
     struct dns_rr_txt {       /* TXT RRset */
       char *dnstxt_qname;     /* original query name */
       char *dnstxt_cname;     /* canonical name */
       unsigned dnstxt_ttl;    /* Time-To-Live (TTL) value */
       int dnstxt_nrr;	       /* number of text records in the set */
       struct dns_txt dnstxt_txt[]; /* array of TXT records */
     };
     typedef void
       dns_query_txt_fn(ctx, struct dns_rr_txt *result, data)
     dns_parse_fn dns_parse_txt;
     struct dns_query *
     dns_submit_txt(ctx, const char *name, enum dns_class qcls,
	int flags, dns_query_txt_fn *cbck, data);
     struct dns_rr_txt *
     dns_resolve_txt(ctx, const char *name,
		  enum dns_class qcls, int flags);

     The dns_rr_txt structure holds a result of a TXT query, which is  an  array
     of  text records for a given domain name.	Callback routine for TXT queries
     expected  to  be  of  type  dns_query_txt_fn,  which  expects  pointer   to
     dns_rr_txt  structure  as	query  result  instead	of  raw DNS packet.  The
     dns_parse_txt() is used to convert raw DNS  reply	packet	into  dns_rr_txt
     structure	(it is used internally and may be used directly too with generic
     query interface).	Routines dns_submit_txt() and dns_resolve_txt() are used
     to perform IN MX queries in a type-safe manner.  The name parameter is  the
     domain  name  in  question, and flags is query flags bitmask, with one bit,
     DNS_NOSRCH, of practical interest (if the name is	absolute,  that  is,  it
     ends  up with a dot, DNS_NOSRCH flag will be set automatically).  Note that
     each TXT string is represented  by  struct dns_txt,  while  zero-terminated
     (and  the	len field of the structure does not include the terminator), may
     contain embedded null characters -- content of TXT records  is  not  inter-
     preted by the library in any way.

   SRV Queries
     struct dns_srv {	       /* single SRV record */
       int priority;	       /* priority of the record */
       int weight;	       /* weight of the record */
       int port;	       /* the port number to connect to */
       char *name;	       /* target host name */
     };
     struct dns_rr_srv {       /* SRV RRset */
       char *dnssrv_qname;     /* original query name */
       char *dnssrv_cname;     /* canonical name */
       unsigned dnssrv_ttl;    /* Time-To-Live (TTL) value */
       int dnssrv_nrr;	       /* number of text records in the set */
       struct dns_srv dnssrv_srv[]; /* array of SRV records */
     };
     typedef void
       dns_query_srv_fn(ctx, struct dns_rr_srv *result, data)
     dns_parse_fn dns_parse_srv;
     struct dns_query *
     dns_submit_srv(ctx, const char *name, const char *service, const char *protocol,
	int flags, dns_query_txt_fn *cbck, data);
     struct dns_rr_srv *
     dns_resolve_srv(ctx, const char *name, const char *service, const char *protocol,
		  int flags);

     The dns_rr_srv structure holds a result of an IN SRV (rfc2782) query, which
     is  an  array  of servers (together with port numbers) which are performing
     operations for a given service using given  protocol  on  a  target  domain
     name.   Callback  routine	for  IN  SRV  queries  expected  to  be  of type
     dns_query_srv_fn, which expects pointer to dns_rr_srv  structure  as  query
     result  instead  of raw DNS packet.  The dns_parse_srv() is used to convert
     raw DNS reply packet into dns_rr_srv structure (it is used  internally  and
     may  be used directly too with generic query interface).  Routines dns_sub-
     mit_srv() and dns_resolve_srv() are used to perform IN  SRV  queries  in  a
     type-safe	manner.  The name parameter is the domain name in question, ser-
     vice and protocl specifies the service and the protocol  in  question  (the
     library will construct query DN according to rfc2782 rules) and may be NULL
     (in  this	case  the  library assumes name parameter holds the complete SRV
     query), and flags is query flags bitmask,	with  one  bit,  DNS_NOSRCH,  of
     practical	interest  (if  the  name is absolute, that is, it ends up with a
     dot, DNS_NOSRCH flag will be set automatically).

   NAPTR Queries
     struct dns_naptr {        /* single NAPTR record */
       int order;	       /* record order */
       int preference;	       /* preference of this record */
       char *flags;	       /* application-specific flags */
       char *service;	       /* service parameter */
       char *regexp;	       /* substitutional regular expression */
       char *replacement;      /* replacement string */
     };
     struct dns_rr_naptr {     /* NAPTR RRset */
       char *dnsnaptr_qname;   /* original query name */
       char *dnsnaptr_cname;   /* canonical name */
       unsigned dnsnaptr_ttl;  /* Time-To-Live (TTL) value */
       int dnsnaptr_nrr;       /* number of text records in the set */
       struct dns_naptr dnsnaptr_naptr[]; /* array of NAPTR records */
     };
     typedef void
       dns_query_naptr_fn(ctx, struct dns_rr_naptr *result, data)
     dns_parse_fn dns_parse_naptr;
     struct dns_query *
     dns_submit_naptr(ctx, const char *name, int flags,
	dns_query_txt_fn *cbck, data);
     struct dns_rr_naptr *
     dns_resolve_naptr(ctx, const char *name, int flags);

     The dns_rr_naptr structure holds a result of an IN NAPTR  (rfc3403)  query.
     Callback	routine   for	IN   NAPTR   queries  expected	to  be	of  type
     dns_query_naptr_fn, expects pointer to dns_rr_naptr structure as query  re-
     sult  instead  of raw DNS packet.	The dns_parse_naptr() is used to convert
     raw DNS reply packet into dns_rr_naptr structure (it is used internally and
     may be used directly too with generic query interface).  Routines	dns_sub-
     mit_naptr() and dns_resolve_naptr() are used to perform IN NAPTR queries in
     a type-safe manner.  The name parameter is the domain name in question, and
     flags is query flags bitmask, with one bit, DNS_NOSRCH, of practical inter-
     est  (if  the  name is absolute, that is, it ends up with a dot, DNS_NOSRCH
     flag will be set automatically).

   DNSBL Interface
     A DNS-based blocklists, or a DNSBLs, are in wide use  nowadays,  especially
     to  protect  mailservers  from spammers.  The library provides DNSBL inter-
     face, a set of routines to perform queries against  DNSBLs.   Routines  ac-
     cepts  an	IP  address  (IPv4 and IPv6 are both supported) and a base DNSBL
     zone as query parameters, and returns either dns_rr_a4 or dns_rr_txt struc-
     ture.  Note that IPv6 interface return IPv4 RRset.

     struct dns_query *
     dns_submit_a4dnsbl(ctx,
       const struct in_addr *addr, const char *dnsbl,
       dns_query_a4_fn *cbck, void *data);
     struct dns_query *
     dns_submit_a4dnsbl_txt(ctx,
       const struct in_addr *addr, const char *dnsbl,
       dns_query_txt_fn *cbck, void *data);
     struct dns_query *
     dns_submit_a6dnsbl(ctx,
       const struct in6_addr *addr, const char *dnsbl,
       dns_query_a4_fn *cbck, void *data);
     struct dns_query *
     dns_submit_a6dnsbl_txt(ctx,
       const struct in6_addr *addr, const char *dnsbl,
       dns_query_txt_fn *cbck, void *data);
     struct dns_rr_a4 *dns_resolve_a4dnsbl(ctx,
       const struct in_addr *addr, const char *dnsbl)
     struct dns_rr_txt *dns_resolve_a4dnsbl_txt(ctx,
       const struct in_addr *addr, const char *dnsbl)
     struct dns_rr_a4 *dns_resolve_a6dnsbl(ctx,
       const struct in6_addr *addr, const char *dnsbl)
     struct dns_rr_txt *dns_resolve_a6dnsbl_txt(ctx,
       const struct in6_addr *addr, const char *dnsbl)
     Perform (submit or resolve) a DNSBL query for the given dnsbl domain and an
     IP addr in question, requesting either A or TXT records.

   RHSBL Interface
     RHSBL is similar to DNSBL, but instead of an IP address, the parameter is a
     domain name.

     struct dns_query *
     dns_submit_rhsbl(ctx, const char *name, const char *rhsbl,
       dns_query_a4_fn *cbck, void *data);
     struct dns_query *
     dns_submit_rhsbl_txt(ctx, const char *name, const char *rhsbl,
       dns_query_txt_fn *cbck, void *data);
     struct dns_rr_a4 *
     dns_resolve_rhsbl(ctx, const char *name, const char *rhsbl);
     struct dns_rr_txt *
     dns_resolve_rhsbl_txt(ctx, const char *name, const char *rhsbl);
     Perform (submit or resolve) a RHSBL query for the given  rhsbl  domain  and
     name in question, requesting either A or TXT records.

LOW-LEVEL INTERFACE
   Domain Names (DNs)
     A	DN  is a series of domain name labels each starts with length byte, fol-
     lowed by empty label (label with zero length).  The following  routines  to
     work with DNs are provided.

     unsigned dns_dnlen(const unsigned char *dn)
	    return  length  of the domain name dn, including the terminating la-
	    bel.

     unsigned dns_dnlabels(const unsigned char *dn)
	    return number of non-zero labels in domain name dn.

     unsigned dns_dnequal(dn1, dn2)
       const unsigned char *dn1, *dn2;
	    test whenever the two domain names, dn1 and dn2, are equal (case-in-
	    sensitive).  Return domain name length if equal or 0 if not.

     unsigned dns_dntodn(sdn, ddn, dnsiz)
       const unsigned char *sdn;
       unsigned char *ddn;
       unsigned dnsiz;
	    copies the source domain name sdn to destination buffer ddn of  size
	    dnsiz.  Return domain name length or 0 if ddn is too small.

     int dns_ptodn(name, namelen, dn, dnsiz, isabs)
     int dns_sptodn(name, dn, dnsiz)
       const char *name; unsigned namelen;
       unsigned char *dn; unsigned dnsiz;
       int *isabs;
	    convert asciiz name name of length namelen to DN format, placing re-
	    sult  into buffer dn of size dnsiz.  Return length of the DN if suc-
	    cesseful, 0 if the dn buffer supplied  is  too  small,  or	negative
	    value  if  name is invalid.  If isabs is non-NULL and conversion was
	    successeful, *isabs will be set to either 1 or 0 depending	whenever
	    name  was  absolute  (i.e.	ending with a dot) or not.  Name length,
	    namelength, may be zero, in which case strlen(name)  will  be  used.
	    Second  form,  dns_sptodn(),  is  a  simplified form of dns_ptodn(),
	    equivalent to
	    dns_ptodn(name, 0, dn, dnlen, 0).

     extern const unsigned char dns_inaddr_arpa_dn[]
     int dns_a4todn(const struct in_addr *addr, const unsigned char *tdn,
	   unsigned char *dn, unsigned dnsiz)
     int dns_a4ptodn(const struct in_addr *addr, const char *tname,
	   unsigned char *dn, unsigned dnsiz)
     extern const unsigned char dns_ip6_arpa_dn[]
     int dns_a6todn(const struct in6_addr *addr, const unsigned char *tdn,
	   unsigned char *dn, unsigned dnsiz)
     int dns_a6ptodn(const struct in6_addr *addr, const char *tname,
	   unsigned char *dn, unsigned dnsiz)
	    several variants of routines to convert IPv4 and IPv6  address  addr
	    into  reverseDNS-like domain name in DN format, storing result in dn
	    of size dnsiz.  tdn (or tname) is  the  base  zone	name,  like  in-
	    addr.arpa for IPv4 or in6.arpa for IPv6.  If tdn (or tname) is NULL,
	    dns_inaddr_arpa_dn	(or dns_ip6_arpa_dn) will be used.  The routines
	    may be used to construct a DN for a DNSBL lookup for  example.   All
	    routines return length of the resulting DN on success, -1 if result-
	    ing  DN  is invalid, or 0 if the dn buffer (dnsiz) is too small.  To
	    hold standard rDNS DN, a buffer of size DNS_A4RSIZE (30  bytes)  for
	    IPv4  address, or DNS_A6RSIZE (74 bytes) for IPv6 address, is suffi-
	    cient.

     int dns_dntop(dn, name, namesiz)
	const unsigned char *dn;
	const char *name; unsigned namesiz;
	    convert domain name dn in DN format to asciiz string, placing result
	    into name buffer of size namesiz.  Maximum length of  asciiz  repre-
	    sentation  of  domain name is DNS_MAXNAME (1024) bytes.  Root domain
	    is represented as empty string.  Return length of the resulting name
	    (including terminating character, i.e. strlen(name)+1) on success, 0
	    if the name buffer is too small, or negative value if dn is  invalid
	    (last  case  should  never happen since all routines in this library
	    which produce domain names ensure the DNs generated are valid).

     const char *dns_dntosp(const unsigned char *dn)
	    convert domain name dn in DN format to asciiz  string  using  static
	    buffer.   Return  the  resulting asciiz string on success or NULL on
	    failure.  Note since this routine uses  static  buffer,  it  is  not
	    thread-safe.

     unsigned dns_dntop_size(const unsigned char *dn)
	    return  the  buffer  size needed to convert the dn domain name in DN
	    format to asciiz string, for dns_dntop().  The routine return either
	    the size of buffer required, including the trailing zero byte, or  0
	    if dn is invalid.

   Working with DNS Packets
     The  following routines are provided to encode and decode DNS on-wire pack-
     ets.  This is low-level interface.

     DNS response codes (returned by dns_rcode() routine) are  defined	as  con-
     stants prefixed with DNS_R_.  See udns.h header file for the complete list.
     In  particular, constants DNS_R_NOERROR (0), DNS_R_SERVFAIL, DNS_R_NXDOMAIN
     may be of interest to an application.

     unsigned dns_get16(const unsigned char *p)
     unsigned dns_get32(const unsigned char *p)
	    helper routines, convert 16-bit or 32-bit integer in on-wire  format
	    pointed to by p to unsigned.

     unsigned char *dns_put16(unsigned char *d, unsigned n)
     unsigned char *dns_put32(unsigned char *d, unsigned n)
	    helper  routine,  convert unsigned 16-bit or 32-bit integer n to on-
	    wire format to buffer pointed to by d, return d+2 or d+4.

     DNS_HSIZE (12)
	    defines size of DNS header.  Data section in the DNS packet  immedi-
	    ately follows the header.  In the header, there are query identifier
	    (id),  various  flags  and	codes, and number of resource records in
	    various data sections.  See udns.h header file for complete list  of
	    DNS header definitions.

     unsigned dns_qid(const unsigned char *pkt)
     int dns_rd(const unsigned char *pkt)
     int dns_tc(const unsigned char *pkt)
     int dns_aa(const unsigned char *pkt)
     int dns_qr(const unsigned char *pkt)
     int dns_ra(const unsigned char *pkt)
     unsigned dns_opcode(const unsigned char *pkt)
     unsigned dns_rcode(const unsigned char *pkt)
     unsigned dns_numqd(const unsigned char *pkt)
     unsigned dns_numan(const unsigned char *pkt)
     unsigned dns_numns(const unsigned char *pkt)
     unsigned dns_numar(const unsigned char *pkt)
     const unsigned char *dns_payload(const unsigned char *pkt)
	    return  various  parts from the DNS packet header pkt: query identi-
	    fier (qid), recursion desired (rd) flag,  truncation  occurred  (tc)
	    flag,  authoritative answer (aa) flag, query response (qr) flag, re-
	    cursion available (ra) flag, operation code  (opcode),  result  code
	    (rcode),  number  of  entries in question section (numqd), number of
	    answers (numan), number of authority records (numns), number of  ad-
	    ditional  records  (numar), and the pointer to the packet data (pay-
	    load).

     int dns_getdn(pkt, curp, pkte, dn, dnsiz)
     const unsigned char *dns_skipdn(cur, pkte)
	const unsigned char *pkt, *pkte, **curp, *cur;
	unsigned char *dn; unsigned dnsiz;
	    dns_getdn() extract DN from DNS packet pkt which  ends  before  pkte
	    starting  at position *curp into buffer pointed to by dn of size dn-
	    siz.  Upon successeful completion, *curp will point to the next byte
	    in the packet after the extracted domain name.  It	return	positive
	    number  (length  of the DN if dn) upon successeful completion, nega-
	    tive value on error (when the packet contains invalid data), or zero
	    if the dnsiz is too small  (maximum  length  of  a	domain	name  is
	    DNS_MAXDN).   dns_skipdn()	return	pointer  to the next byte in DNS
	    packet which ends up before pkte after a domain name which starts at
	    the cur byte, or NULL if the packet  is  invalid.	dns_skipdn()  is
	    more or less equivalent to what dns_getdn() does, except it does not
	    actually  extract  the domain name in question, and uses simpler in-
	    terface.

     struct dns_rr {
       unsigned char dnsrr_dn[DNS_MAXDN]; /* the RR DN name */
       enum dns_class dnsrr_cls;	  /* class of the RR */
       enum dns_type  dnsrr_typ;	  /* type of the RR */
       unsigned dnsrr_ttl;		  /* TTL value */
       unsigned dnsrr_dsz;		  /* size of data in bytes */
       const unsigned char *dnsrr_dptr;   /* pointer to the first data byte */
       const unsigned char *dnsrr_dend;   /* next byte after RR */
     };
	    The dns_rr structure is used to hold information  about  single  DNS
	    Resource Record (RR) in an easy to use form.

     struct dns_parse {
       const unsigned char *dnsp_pkt; /* pointer to the packet being parsed */
       const unsigned char *dnsp_end; /* end of the packet pointer */
       const unsigned char *dnsp_cur; /* current packet position */
       const unsigned char *dnsp_ans; /* pointer to the answer section */
       int dnsp_rrl;		      /* number of RRs left */
       int dnsp_nrr;		      /* number of relevant RRs seen so far */
       unsigned dnsp_ttl;	      /* TTL value so far */
       const unsigned char *dnsp_qdn; /* the domain of interest or NULL */
       enum dns_class dnsp_qcls;      /* class of interest or 0 for any */
       enum dns_type  dnsp_qtyp;      /* type of interest or 0 for any */
       unsigned char dnsp_dnbuf[DNS_MAXDN]; /* domain name buffer */
     };
	    The dns_parse structure is used to parse DNS reply packet.	It holds
	    information  about	the  packet being parsed (dnsp_pkt, dnsp_end and
	    dnsp_cur fields), number of RRs in the current section left  to  do,
	    and  the  information  about  specific  RR	which  we're looking for
	    (dnsp_qdn, dnsp_qcls and dnsp_qtyp fields).

     int dns_initparse(struct dns_parse *p,
       const unsigned char *qdn,
       const unsigned char *pkt,
       const unsigned char *cur,
       const unsigned char *end)
	    initializes the RR parsing structure p.  Arguments pkt, cur and  end
	    should describe the received packet: pkt is the start of the packet,
	    end  points  to  the  next byte after the end of the packet, and cur
	    points past the query DN in query section (to query  class+type  in-
	    formation).   And qdn points to the query DN.  This is the arguments
	    passed  to	dns_parse_fn()	routine.   dns_initparse()   initializes
	    dnsp_pkt,  dnsp_end  and  dnsp_qdn fields to the corresponding argu-
	    ments, extracts and initializes dnsp_qcls and  dnsp_qtyp  fields  to
	    the  values  found at cur pointer, initializes dnsp_cur and dnsp_ans
	    fields to be cur+4 (to the start of answer section), and initializes
	    dnsp_rrl field to be number of entries in answer  section.	dnsp_ttl
	    will be set to max TTL value, 0xffffffff, and dnsp_nrr to 0.

     int dns_nextrr(struct dns_parse *p, struct dns_rr *rr);
	    searches for next RR in the packet based on the criteria provided in
	    the   p  structure,  filling  in  the  rr  structure  and  advancing
	    p->dnsp_cur to the next RR in the packet.  RR selection is based  on
	    dnsp_qdn, dnsp_qcls and dnsp_qtyp fields in the dns_parse structure.
	    Any  (or all) of the 3 fields may be 0, which means any actual value
	    from the packet is acceptable.  In case the field isn't 0  (or  NULL
	    for  dnsp_qdn),  only RRs with corresponding characteristics are ac-
	    ceptable.  Additionally, when  dnsp_qdn  is  non-NULL,  dns_nextrr()
	    performs  automatic  CNAME	expansion.  Routine will return positive
	    value on success, 0 in case it reached the end of current section in
	    the packet (p->dnsp_rrl is zero), or negative value if next  RR  can
	    not  be  decoded  (packet  format  is invalid).  The routine updates
	    p->dnsp_qdn automatically when this field is non-NULL and it encoun-
	    ters appropriate CNAME RRs (saving CNAME target  in  p->dnsp_dnbuf),
	    so	after  end  of	the process, p->dnsp_qdn will point to canonical
	    name of the domain in question.   The  routine  updates  p->dnsp_ttl
	    value to be the minimum TTL of all RRs found.

     void dns_rewind(struct dns_parse *p, const unsigned char *qdn)
	    this routine "rewinds" the packet parse state structure to be at the
	    same  state  as after a call to dns_initparse(), i.e. reposition the
	    parse structure p to the start  of	answer	section  and  initialize
	    p->dnsp_rrl to the number of entries in answer section.

     int dns_stdrr_size(const struct dns_parse *p);
	    return  size  to hold standard RRset structure information, as shown
	    in dns_rr_null structure (for the query and canonical names).   Used
	    to	calculate  amount of memory to allocate for common part of type-
	    specific RR structures in parsing routines.

     void *dns_stdrr_finish(struct dns_rr_null *ret, char *cp,
       const struct dns_parse *p);
	    initializes standard RRset fields  in  ret	structure  using  buffer
	    pointed  to  by  cp,  which  should  have  at least as many bytes as
	    dns_stdrr_size(p) returned.  Used to finalize common part  of  type-
	    specific RR structures in parsing routines.

     See  library source for usage examples of all the above low-level routines,
     especially source of the parsing routines.

   Auxilary Routines
     int dns_pton(int af, const char *src, void *dst);
	    privides functionality similar to standard inet_pton()  routine,  to
	    convert  printable representation of an IP address of family af (ei-
	    ther AF_INET or AF_INET6) pointed to by src into binary  form  suit-
	    able  for  socket addresses and transmission over network, in buffer
	    pointed to by dst.	The destination buffer should be of size  4  for
	    AF_INET  family or 16 for AF_INET6.  The return value is positive on
	    success, 0 if src is not a valid text representation of  an  address
	    of	family	af,  or negative if the given address family is not sup-
	    ported.

     const char *dns_ntop(int af, const void *src,
	 char *dst, int dstsize)
	    privides functionality similar to standard inet_ntop()  routine,  to
	    convert  binary representation of an IP address of family af (either
	    AF_INET or AF_INET6) pointed to by src (either 4 or 16  bytes)  into
	    printable  form  in  buffer in buffer pointed to by dst of size dst-
	    size.  The destination buffer should be at least of  size  16  bytes
	    for  AF_INET  family  or 46 bytes for AF_INET6.  The return value is
	    either dst, or NULL pointer if dstsize is too small to hold this ad-
	    dress or if the given address family is not supported.

AUTHOR
     The udns library has been written by Michael Tokarev, mjt+udns@tls.msk.ru.

VERSION
     This manual page corresponds to udns version 0.6, released Jul-2024.

Library Functions		    Jan 2014				 udns(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=udns&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help