udns man page on DragonFly

Man page or keyword search:  
man Server   44335 pages
apropos Keyword Search (all sections)
Output format
DragonFly logo
[printable version]


udns(3)								       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 func‐
       tionality, which may be used both traditional, syncronous way and asyn‐
       cronously, 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  protocol), 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
       asking  multiple	 nameservers.	This way, it is very simple to use the
       library in asyncronous 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 application.  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 allocated/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 asyncronous query or to
       wait for it to complete.

       Asyncronous interface works as  follows.	  An  application  initializes
       resolver	 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 necessary processing and executes application sup‐
       plied  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 obtained), 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 inteface  that
       requests	 parsing  automatically).  The I/O monitoring and timeout han‐
       dling may be either traditional select() or poll() based, or any	 call‐
       back-driven technique may be used.

       Additionally,  the  library  provides traditional syncronous interface,
       which may be intermixed with asyncronous calls (during syncronous query
       processing,  other  asyncronous	queries	 for the same resolver context
       continued to be processed as usual).  An application uses one of numer‐
       ous  dns_resolve_XXX()  routines	 provided  by the library to perform a
       query.  As  with	 asyncronous  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 asyncronous 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 whith
       preceeding length byte, terminated by zero-length label wich  is	 inte‐
       gral  part  of  the  DN format.	There are several routines provided to
       convert from traditional asciiz string to DN  and  back.	  Higher-level
       type-specific query interface 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 for‐
	      mat.

       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
	      protocol

       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  fragmenta‐
	      tion  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
       error 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 ini‐
       tialize, copy and free resolver contexts.  Most other  high-level  rou‐
       tines  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.  Several 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,
       performed 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
       system file /etc/resolv.conf (see resolv.conf(5)), consults environment
       variables  $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
	      routine  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 - oper‐
	      ation  always  succeeds.	dns_init() does everything dns_reset()
	      does, plus initializes various parameters of the context accord‐
	      ing  to  system configuration and process environment variables.
	      If do_open is non-zero, dns_init() calls dns_open(), so that the
	      whole library initialisation 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 parame‐
	      ters for a given resolver context copy, or  default  context  if
	      copy  is	NULL,  and returns pointer to the newly allocated con‐
	      text.   The  context  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 assotiated socket and free resolver
	      context resources and cancelling (abandoming) all active queries
	      assotiated  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 corre‐
	      sponding list (search or nameserver)  is	reset  instead.	  Upon
	      successeful  completion, each routine returns new number of ele‐
	      ments 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
	      environment  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
	      defined:

	      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 assotiated 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
	      context 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  syncronous
	      interface,  this	is  the	 query	completion  status of the last
	      query.  With asyncronous 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  con‐
	      stants 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 routine 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 current time by it's own.

       int dns_timeouts(ctx, int maxwait, time_t now)
	      process any pending timeouts and return number of secounds  from
	      current  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 current 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
	      mechanism.  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 resolver 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 appli‐
		     cation   changes	user   timer   request	routine	 using
		     dns_set_tmcbck();

	      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()
	      routine (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 syncronous  way,
       when  udns  performs all the necessary processing and return control to
       the application only when the query  completes,	and  asyncronous  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 library and calling library routines to process
       input on that filedescriptor.  Asyncronous  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 asyncronous query, an application calls	one  of	 the  dns_sub‐
       mit_XXX()  rounines, and provides necessary information for a callback,
       together with all the query  parameters.	  When	the  query  completes,
       library	will call application-supplied callback routine, giving it the
       resolver context (wich  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
       received; cur points past the query DN in  the  query  section  of  the
       packet;	qdn points to the original query DN.  The routine should allo‐
       cate a single buffer to hold the result, parse the reply filling in the
       buffer,	and return 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 inteface supplies necessary parsing routines auto‐
       matically.

       In case of error, query	completion  status  as	returned  by  dns_sta‐
       tus(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
	      question) is invalid, and the library can't even start a query.

       Library provides two series of routines which uses similar interface --
       one  for asyncronous queries and another for syncronous queries.	 There
       are two general low-level routines in  each  series  to	submit	(asyn‐
       cronous	interface) and resolve (syncronous interface) queries, as well
       as several type-specific routines with more easy-to-use interfaces.  To
       submit  an asyncronous query, use one of dns_submit_XXX() routine, each
       of which accepts query parameters, pointers to callback routine and  to
       callback	 data,	and  optional  current	time hint.  Note type-specific
       dns_submit_XXX() routines 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 identi‐
       fier for the given query.

       To resolve a query syncronously, 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 asyncronous
       interface.

       In either case, the result memory (if  the  query  completed  successe‐
       fully)  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  option  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_can‐
	      cel()  routine.	In  case  of error, NULL will be returned, and
	      context error status (available using dns_status() 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 structure, or
	      DNS_E_TEMPFAIL if an internal error occured.

       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;
	      syncronous interface.  The routines perform all the steps neces‐
	      sary  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  status  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  allocated  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_sub‐
	      mit_XXX() routines, for completion, and return the result.   The
	      callback	routine will not be called for this query.  After com‐
	      pletion,	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 pro‐
       vides a set of routines to perform specific queries in a type-safe man‐
       ner,  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 struc‐
       ture 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	inter‐
       face).	Routines dns_submit_a4() and dns_resolve_a4() are used to per‐
       form 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
       array 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 convert 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 interest
       (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
       array  of domain name pointers for a given IPv4 or IPv6 address.	 Call‐
       back  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_resolve_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	repre‐
       sented  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 interpreted 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_submit_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, service 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 bit‐
       mask, 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
       result  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_submit_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 interest (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,	 espe‐
       cially  to  protect  mailservers	 from  spammers.  The library provides
       DNSBL interface, a set of routines to perform queries  against  DNSBLs.
       Routines accepts 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 structure.  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,
       followed	 by  empty label (label with zero length).  The following rou‐
       tines to work with DNs are provided.

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

       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-insensitive).  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
	      result into buffer dn of size dnsiz.  Return length of the DN if
	      successeful, 0 if the dn buffer supplied is too small, or	 nega‐
	      tive value if name is invalid.  If isabs is non-NULL and conver‐
	      sion 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 sim‐
	      plified 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 resulting 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 sufficient.

       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 representation  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
       packets.	 This is low-level interface.

       DNS  response  codes  (returned	by dns_rcode() routine) are defined as
       constants prefixed with DNS_R_.	See udns.h header file	for  the  com‐
       plete  list.   In  particular, constants DNS_R_NOERROR (0), DNS_R_SERV‐
       FAIL, 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
	      immediately  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 iden‐
	      tifier  (qid),  recursion	 desired (rd) flag, truncation occured
	      (tc) flag, authoritative answer (aa) flag, query	response  (qr)
	      flag,  recursion	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 additional records (numar), and  the  pointer
	      to the packet data (payload).

       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  dnsiz.   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, negative 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 interface.

       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 positionn */
	 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 sec‐
	      tion  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 information).	And qdn points to the query DN.	  This
	      is  the  arguments  passed  to dns_parse_fn() routine. dns_init‐
	      parse() initializes dnsp_pkt, dnsp_end and  dnsp_qdn  fields  to
	      the  corresponding arguments, extracts and initializes dnsp_qcls
	      and dnsp_qtyp fields to the values found at  cur	pointer,  ini‐
	      tializes	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  pro‐
	      vided  in	 the  p	 structure,  filling  in  the rr structure and
	      advancing p->dnsp_cur to the next RR in the packet.   RR	selec‐
	      tion 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  acceptable.	 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
	      encounters  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. reposi‐
	      tion the parse structure p to the start of  answer  section  and
	      initialize  p->dnsp_rrl  to the number of entries in answer sec‐
	      tion.

       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 com‐
	      mon 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  rou‐
       tines, 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  (either  AF_INET  or AF_INET6) pointed to by src into binary
	      form suitable for socket addresses and  transmission  over  net‐
	      work,  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 supported.

       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	dstsize.  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 address 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.4, released Jan-2014.

Library Functions		   Jan 2014			       udns(3)
[top]

List of man pages available for DragonFly

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net