1
2udns(3)                    Library Functions Manual                    udns(3)
3
4
5

NAME

7       udns - stub DNS resolver library
8
9

SYNOPSYS

11       #include <udns.h>
12       struct dns_ctx;
13       struct dns_query;
14       extern struct dns_ctx dns_defctx;
15       struct dns_ctx *ctx;
16       typedef void dns_query_fn(ctx, void *result, void *data);
17       typedef int
18       dns_parse_fn(const unsigned char *qnd,
19              const unsigned char *pkt,
20              const unsigned char *cur,
21              const unsigned char *end,
22              void **resultp);
23
24       cc ... -ludns
25
26

DESCRIPTION

28       The  DNS  library, udns, implements thread-safe stub DNS resolver func‐
29       tionality, which may be used both traditional, syncronous way and asyn‐
30       cronously, with application-supplied event loop.
31
32
33       While  DNS  works with both TCP and UDP, performing UDP query first and
34       if the result does not fit in UDP buffer (512 bytes  max  for  original
35       DNS  protocol), retrying the query over TCP, the library uses UDP only,
36       but uses EDNS0 (RFC2671) extensions which allows larger UDP buffers.
37
38
39       The library uses single UDP socket to perform all operations even  when
40       asking  multiple  nameservers.   This way, it is very simple to use the
41       library in asyncronous event-loop applications: an  application  should
42       add  only  single  socket to the set of filedescriptors it monitors for
43       I/O.
44
45
46       The  library  uses  two  main  objects,  resolver   context   of   type
47       struct dns_ctx,  and query structure of type struct dns_query, both are
48       opaque for an application.  Resolver context holds  global  information
49       about  the resolver, such as list of nameservers to use, list of active
50       requests and the like.  Query objects holds information about a  single
51       DNS query in progress and are allocated/processed/freed by the library.
52       Pointer to query structure may be treated as an identifier  of  an  in-
53       progress  query  and  may be used to cancel the asyncronous query or to
54       wait for it to complete.
55
56
57       Asyncronous interface works as  follows.   An  application  initializes
58       resolver  context,  submits  any  number of queries for it using one of
59       supplied dns_submit_XXX() routines (each return the query identifier as
60       pointer  to query structure), waits for input on the UDP socket used by
61       the  library,  and  gives  some  control  to  the  library  by  calling
62       dns_ioevent()   and  dns_timeouts()  routines  when  appropriate.   The
63       library performs all necessary processing and executes application sup‐
64       plied  callback routine when a query completes (either successefully or
65       not), giving it the result if any,  pointer  to  the  resolver  context
66       (from  which  completion  status may be obtained), and the data pointer
67       supplied by an application when the query  has  been  submitted.   When
68       submitting  a query, an application requests how to handle the reply --
69       to either return raw DNS reply packet for its own low-level processing,
70       or it may provide an address of parsing routine of type dns_parse_fn to
71       perform conversion of on-wire format into easy to  use  data  structure
72       (the  library  provides  parsing  routines  for  several  commonly used
73       resource record types, as well as type-safe higher-level inteface  that
74       requests  parsing  automatically).  The I/O monitoring and timeout han‐
75       dling may be either traditional select() or poll() based, or any  call‐
76       back-driven technique may be used.
77
78
79       Additionally,  the  library  provides traditional syncronous interface,
80       which may be intermixed with asyncronous calls (during syncronous query
81       processing,  other  asyncronous  queries  for the same resolver context
82       continued to be processed as usual).  An application uses one of numer‐
83       ous  dns_resolve_XXX()  routines  provided  by the library to perform a
84       query.  As  with  asyncronous  interface,  an  application  may  either
85       request  to  return  raw  DNS packet or type-specific data structure by
86       providing the parsing routine to handle the reply.  Every routine  from
87       dns_resolve_XXX()  series  return  pointer to result or NULL in case of
88       any error.  Query completion status (or length of the raw  DNS  packet)
89       is  available from the resolver context using dns_status() routine, the
90       same way as for the asyncronous interface.
91
92
93       Internally, library uses on-wire format of domain names, referred to as
94       DN format in this manual page.  This is a series of domain labels whith
95       preceeding length byte, terminated by zero-length label wich  is  inte‐
96       gral  part  of  the  DN format.  There are several routines provided to
97       convert from traditional asciiz string to DN  and  back.   Higher-level
98       type-specific query interface hides the DN format from an application.
99
100

COMMON DEFINITIONS

102       Every  DNS  Resource  Record  (RR) has a type and a class.  The library
103       defines several integer constants, DNS_C_XXX and DNS_T_XXX, to  use  as
104       symbolic  names for RR classes and types, such as DNS_C_IN for Internet
105       class, DNS_T_A for IPv4 address record type  and  so  on.   See  udns.h
106       header file for complete list of all such constants.
107
108
109       The following constants are defined in udns.h header file:
110
111       DNS_MAXDN (255 bytes)
112              Maximum  length of the domain name in internal (on-wire) DN for‐
113              mat.
114
115       DNS_MAXLABEL (63 bytes)
116              Maximum length of a single label in DN format.
117
118       DNS_MAXNAME (1024 bytes)
119              Maximum length of asciiz format of a domain name.
120
121       DNS_HSIZE (12 bytes)
122              Size of header in DNS packet.
123
124       DNS_PORT (53)
125              Default port to use when contacting a DNS server.
126
127       DNS_MAXSERV (6 servers)
128              Maximum number of DNS servers to use.
129
130       DNS_MAXPACKET (512 bytes)
131              Maximum length of DNS UDP packet as specified  by  original  DNS
132              protocol
133
134       DNS_EDNS0PACKET (4096 bytes)
135              Default  length  of  DNS  UDP packet (with EDNS0 extensions) the
136              library uses.  Note that recursive nameservers  usually  resides
137              near  the  client asking them to resolve names, e.g. on the same
138              LAN segment or even on the same host, so UDP  packet  fragmenta‐
139              tion  isn't a problem in most cases.  Note also that the size of
140              actual packets will be  as  many  bytes  as  actual  reply  size
141              requires, which is smaller than this value in almost all cases.
142
143
144       Additionally,  several  constants are defined to simplify work with raw
145       DNS packets, such as DNS response codes (DNS_R_XXX), DNS header  layout
146       (DNS_H_XXX)  and others.  Again, see udns.h for complete list.  Library
147       error codes (DNS_E_XXX) are described later in this manual page.
148
149

RESOLVER CONTEXT

151       Resolver context, of type struct dns_ctx, is an object which is  opaque
152       to  an  application.   Several routines provided by the library to ini‐
153       tialize, copy and free resolver contexts.  Most other  high-level  rou‐
154       tines  in  this  library expects a pointer to resolver context, ctx, as
155       the first argument.  There is a  default  resolver  context  available,
156       named  dns_defctx.  When the context pointer ctx passed to a routine is
157       NULL, dns_defctx is used.  Several resolver contexts may be  active  at
158       the  same  time, for example, when an application is multi-threaded and
159       each thread uses resolver.
160
161       In order to use the library, an application should initialize and  open
162       one  or more resolver context objects.  These are two separate actions,
163       performed by dns_init() (or dns_reset()), and dns_open().  Between  the
164       two calls, an application is free to pefrorm additional initialisation,
165       such as setting custom nameservers, options  or  domain  search  lists.
166       Optionally,  in  case  no additional custom initialisation is required,
167       dns_init() may open the context if do_open argument (see below) is non-
168       zero.
169
170       When  initializing  resolver context, the library uses information from
171       system file /etc/resolv.conf (see resolv.conf(5)), consults environment
172       variables $LOCALDOMAIN, $DNSCACHEIP, $NAMESERVERS and $RES_OPTIONS, and
173       local host name to obtain list of local nameservers, domain name search
174       list and various resolver options.
175
176       The following routines to initialize resolver context are available:
177
178       void dns_reset(ctx)
179       int dns_init(ctx, int do_open)
180              dns_reset()  resets  a given resolver context to default values,
181              preparing it to be opened by dns_open().  It is ok to call  this
182              routine  against  opened and active context - all active queries
183              will be dropped, sockets will be closed and so on.  This routine
184              does  not  initialize  any  parameters from system configuration
185              files, use dns_init() for this.  There's no error return - oper‐
186              ation  always  succeeds.  dns_init() does everything dns_reset()
187              does, plus initializes various parameters of the context accord‐
188              ing  to  system configuration and process environment variables.
189              If do_open is non-zero, dns_init() calls dns_open(), so that the
190              whole library initialisation is performed in a single step.
191
192       struct dns_ctx *dns_new(struct dns_ctx *copy)
193       void dns_free(ctx)
194              dns_new()  allocates new resolver context and copies all parame‐
195              ters for a given resolver context copy, or  default  context  if
196              copy  is  NULL,  and returns pointer to the newly allocated con‐
197              text.   The  context  being  copied   should   be   initialized.
198              dns_new() may fail if there's no memory available to make a copy
199              of copy, in which case the routine  will  return  NULL  pointer.
200              dns_free()  is used to close assotiated socket and free resolver
201              context resources and cancelling (abandoming) all active queries
202              assotiated  with  it.   It's  an  error to free dns_defctx, only
203              dynamically allocated contexts returned by dns_new() are allowed
204              to be freed by dns_free().
205
206       int dns_add_serv(ctx, const char *servaddr)
207       int dns_add_serv_s(ctx, const struct sockaddr *sa)
208       int dns_add_srch(ctx, const char *srch)
209              Add  an  element  to  list  of  nameservers  (dns_add_serv(), as
210              asciiz-string servaddr with an IP address of the nameserver, and
211              dns_add_serv_s(),  as  initialized socket address sa), or search
212              list (dns_add_srch(), as a pointer to domain name) for the given
213              context ctx.  If the last argument is a NULL pointer, the corre‐
214              sponding list (search or nameserver)  is  reset  instead.   Upon
215              successeful  completion, each routine returns new number of ele‐
216              ments in the list in question.   On  error,  negative  value  is
217              returned  and global variable errno is set appropriately.  It is
218              an error to call any of this functions if the context is  opened
219              (after dns_open() or dns_init() with non-zero argument).
220
221       int dns_set_opts(ctx, const char *opts)
222              set  resolver  context options from opts string, in the same way
223              as processing options statement in resolv.conf and  $RES_OPTIONS
224              environment variable.
225
226       void dns_set_opt(ctx, int opt, val)
227              TODO  The  flags  argument  is a bitmask with the following bits
228              defined:
229
230              DNS_NOSRCH
231                     do not perform domain name search in search list.
232
233              DNS_NORD
234                     do not request recursion when  performing  queries  (i.e.
235                     don't set RD flag in querues).
236
237              DNS_AAONLY
238                     request  authoritative  answers only (i.e. set AA flag in
239                     queries).
240
241
242       int dns_open(ctx)
243       int dns_sock(const ctx)
244       void dns_close(ctx)
245              dns_open() opens the UDP socket used for queries if not  already
246              open, and return assotiated filedescriptor (or negative value in
247              case of error).  Before any query can be submitted, the  context
248              should  be  opened  using this routine.  And before opening, the
249              context should be initialized.  dns_sock() return the UDP socket
250              if  open, or -1 if not.  dns_close() closes the UDP socket if it
251              was open, and drops all active queries if any.
252
253
254       int dns_active(const ctx)
255              return number of active queries queued  for  the  given  context
256              ctx, or zero if none.
257
258
259       int dns_status(const ctx)
260              return  status  code from last operation.  When using syncronous
261              interface, this is the  query  completion  status  of  the  last
262              query.   With  asyncronous  interface,  from within the callback
263              routine, this is the query completion status of  the  query  for
264              which  the  callback  is  being  called.   When query submission
265              fails, this is the error code indicating  failure  reason.   All
266              error  codes  are negative and are represented by DNS_E_XXX con‐
267              stants described below.
268
269
270       void dns_ioevent(ctx, time_t now)
271              this routine may be called by  an  application  to  process  I/O
272              events  on  the  UDP  socket used by the library, as returned by
273              dns_sock().  The routine tries to receive incoming UDP  datagram
274              from the socket and process it.  The socket is set up to be non-
275              blocking, so it is safe to call the routine even if  there's  no
276              data to read.  The routine will process as many datagrams as are
277              queued for the socket, so it is  safe  to  use  it  with  either
278              level-triggered or edge-triggered I/O monitoring model.  The now
279              argument is either a current time as returned by time(),  or  0,
280              in which case the routine will obtain current time by it's own.
281
282
283       int dns_timeouts(ctx, int maxwait, time_t now)
284              process  any pending timeouts and return number of secounds from
285              current time (now if it is not 0) to the time when  the  library
286              wants  the application to pass it control to process more queued
287              requests.  In case when there are no requests pending, this time
288              is  -1.  The routine will not request a time larger than maxwait
289              secounds if it is greather or equal to zero.  If now is  0,  the
290              routine  will obtain current time by it's own; when it is not 0,
291              it should contain current time as returned by time().
292
293
294       typedef void dns_utm_fn(ctx, int timeout, void *data)
295       void dns_set_cbck(ctx, dns_utm_fn *utmfn, void *data)
296              An application may use custom  callback-based  I/O  multiplexing
297              mechanism.   Usually  such  a mechanism have concept of a timer,
298              and an ability to register a timer event in a form of a callback
299              routine which will be executed after certain amount of time.  In
300              order to use such an event mechanism, udns provides  an  ability
301              to  register and de-register timer events necessary for internal
302              processing using whatever event mechanism an  application  uses.
303              For  this  to  work,  it is possible to assotiate a pointer to a
304              routine that will perform  necessary  work  for  (de)registering
305              timer  events  with a given resolver context, and udns will call
306              that routine at appropriate times.  Prototype of such a  routine
307              is shown by dns_utm_fn typedef above.  Libudns assotiates single
308              timer with resolver context.  User-supplied utmfn  routine  will
309              be called by the library with the following arguments:
310
311              ctx == NULL
312                     delete user timer, at context free time or when an appli‐
313                     cation  changes  user   timer   request   routine   using
314                     dns_set_cbck();
315
316              ctx != NULL, timeout < 0
317                     don't  fire  timer  anymore,  when  there  are  no active
318                     requests;
319
320              ctx != NULL, timeout == 0
321                     fire timer at the next possibility, but not immediately;
322
323              ctx != NULL, timeout > 0
324                     fire timer after timeout seconds after now.
325
326              The data argument passed to the routine  will  be  the  same  as
327              passed to dns_set_cbck().
328
329              When  a  timer expires, an application should call dns_tmeouts()
330              routine (see below).  Non-callback timer usage is provided too.
331
332
333       XXXX TODO: some more resolver context  routines,  like  dns_set_dbgfn()
334       etc.
335
336

QUERY INTERFACE

338       There  are two ways to perform DNS queries: traditional syncronous way,
339       when udns performs all the necessary processing and return  control  to
340       the  application  only  when  the query completes, and asyncronous way,
341       when an application submits one or more queries to  the  library  using
342       given   resolver  context,  and  waits  for  completion  by  monitoring
343       filedescriptor used by library and calling library routines to  process
344       input  on  that  filedescriptor.   Asyncronous mode works with callback
345       routines: an application supplies an address of a  routine  to  execute
346       when  the  query  completes, and a data pointer, which is passed to the
347       callback routine.
348
349
350       Queries are submitted to the library in a form of struct dns_query.  To
351       perform  asyncronous  query,  an  application calls one of the dns_sub‐
352       mit_XXX() rounines, and provides necessary information for a  callback,
353       together  with  all  the  query  parameters.  When the query completes,
354       library will call application-supplied callback routine, giving it  the
355       resolver  context  (wich  holds  query  completion status), dynamically
356       allocated result (which will be either raw DNS packet or, if applicatin
357       requested  parsing  the  result  by  specifying non-NULL parse routine,
358       ready-to-use type-specific structure), and a data pointer  provided  by
359       an  application  when  it  submitted  the query.  It is the application
360       who's responsible for freeing the result memory.
361
362       Generic query callback routine looks like this:
363       typedef void
364       dns_query_fn(ctx, void *result, void *data)
365       Type-specific query interface expects similar form of callback  routine
366       with  the  only  difference  in  type of result argument, which will be
367       pointer to specific data structure (decoded reply) instead of this void
368       pointer to raw DNS packet data.
369
370
371       Result parsing routine looks like this:
372       typedef int
373       dns_parse_fn(const unsigned char *qdn,
374             const unsigned char *pkt,
375             const unsigned char *cur,
376             const unsigned char *end,
377             void **resultp);
378       When called by the library, the arguments are as follows: pkt points to
379       the start of the packet received; end points past the end of the packet
380       received;  cur  points  past  the  query DN in the query section of the
381       packet; qdn points to the original query DN.  The routine should  allo‐
382       cate a single buffer to hold the result, parse the reply filling in the
383       buffer, and return the buffer using resultp argument.  It returns 0  in
384       case  of  error,  or  udns  error code (DNS_E_XXX constants) in case of
385       error.  Note that by the time when the parse routine is called  by  the
386       library,  packet  is  already  verified  to  be a reply to the original
387       query, by matching query DN, query class and query type.
388
389
390       Type-specific query inteface supplies necessary parsing routines  auto‐
391       matically.
392
393
394       In  case  of  error,  query  completion  status as returned by dns_sta‐
395       tus(ctx), will contain one of the following values:
396
397       positive value
398              length of raw DNS packet if parsing is not requested.
399
400       0      the query was successeful and the reply points to  type-specific
401              data structure.
402
403       DNS_E_TEMPFAIL
404              temporary error, the resolver nameserver was not able to process
405              our query or timed out.
406
407       DNS_E_PROTOCOL
408              protocol error, a nameserver returned malformed reply.
409
410       DNS_E_NXDOMAIN
411              the domain name does not exist.
412
413       DNS_E_NODATA
414              there is no data of requested type found.
415
416       DNS_E_NOMEM
417              out of memory while processing request.
418
419       DNS_E_BADQUERY
420              some aspect of the query (most common  is  the  domain  name  in
421              question) is invalid, and the library can't even start a query.
422
423
424       Library provides two series of routines which uses similar interface --
425       one for asyncronous queries and another for syncronous queries.   There
426       are  two  general  low-level  routines  in each series to submit (asyn‐
427       cronous interface) and resolve (syncronous interface) queries, as  well
428       as several type-specific routines with more easy-to-use interfaces.  To
429       submit an asyncronous query, use one of dns_submit_XXX() routine,  each
430       of  which accepts query parameters, pointers to callback routine and to
431       callback data, and optional  current  time  hint.   Note  type-specific
432       dns_submit_XXX() routines expects specific type of the callback routine
433       as well, which accepts reply as a pointer to  corresponding  structure,
434       not  a void pointer).  Every dns_submit_XXX() routine return pointer to
435       internal query structure of type struct dns_query, used as  an  identi‐
436       fier for the given query.
437
438
439       To resolve a query syncronously, use one of dns_resolve_XXX() routines,
440       which accepts the same query parameters (but not the callback pointers)
441       as  corresponding  dns_submit_XXX(), and return the query result, which
442       is the same as passed to the callback routine in  case  of  asyncronous
443       interface.
444
445
446       In  either  case,  the  result memory (if the query completed successe‐
447       fully) is dynamically allocated and should be freed by an  application.
448       If  the query failed for any reason, the result will be NULL, and error
449       status will be available from dns_status(ctx) routine as shown above.
450
451
452       struct dns_query *
453       dns_submit_dn(ctx,
454            const unsigned char *dn, qcls, qtyp, flags,
455            parse, cbck, data)
456       struct dns_query *
457       dns_submit_p(ctx,
458            const char *name, qcls, qtyp, flags,
459            parse, cbck, data)
460          enum dns_class qcls;
461          enum dns_type qtyp;
462          int flags;
463          dns_parse_fn *parse;
464          dns_query_fn *cbck;
465          void *data;
466              submit a query for processing for  the  given  resolver  context
467              ctx.  Two routines differs only in 3rd argument, which is domain
468              name in DN format (dn) or asciiz string (name).  The query  will
469              be  performed for the given domain name, with type qtyp in class
470              qcls, using option bits  in  flags,  using  RR  parsing  routine
471              pointed by parse if not-NULL, and upon completion, cbck function
472              will be called with the data argument.  In case  of  successeful
473              query  submission,  the routine return pointer to internal query
474              structure which may be treated as an identifier of the query  as
475              used by the library, and may be used as an argument for dns_can‐
476              cel() routine.  In case of error, NULL  will  be  returned,  and
477              context error status (available using dns_status() routine) will
478              be set to corresponding error code, which in this  case  may  be
479              DNS_E_BADQUERY  if  the  name  of  dn is invalid, DNS_E_NOMEM if
480              there's no memory available  to  allocate  query  structure,  or
481              DNS_E_TEMPFAIL if an internal error occured.
482
483
484       void *dns_resolve_dn(ctx,
485            const unsigned char *dn, qcls, qtyp, flags, parse);
486       void *dns_resolve_p(ctx,
487            const char *name, qcls, qtyp, flags, parse)
488          enum dns_class qcls;
489          enum dns_type qtyp;
490          int flags;
491          dns_parse_fn *parse;
492              syncronous interface.  The routines perform all the steps neces‐
493              sary to resolve the given  query  and  return  the  result.   If
494              there's  no  positive  result  for  any reason, all the routines
495              return NULL, and  set  context  error  status  (available  using
496              dns_status()  routine) to indicate the error code.  If the query
497              was successeful, context status code  will  contain  either  the
498              length  of  the  raw DNS reply packet if parse argument was NULL
499              (in which case the return value is  pointer  to  the  reply  DNS
500              packet),  or  0 (in which case the return value is the result of
501              parse routine).  If the query successeful (return value  is  not
502              NULL),  the  memory  returned  was  dynamically allocated by the
503              library and should be free()d by application after use.
504
505
506       void *dns_resolve(ctx, struct dns_query *q)
507              wait for the given query q,  as  returned  by  one  of  dns_sub‐
508              mit_XXX()  routines, for completion, and return the result.  The
509              callback routine will not be called for this query.  After  com‐
510              pletion,   the   query   identifier   q   is   not  valid.  Both
511              dns_resolve_dn() and dns_resolve_p() are  just  wrappers  around
512              corresponding submit routines and this dns_resolve() routine.
513
514
515       void dns_cancel(ctx, struct dns_query *q)
516              cancel  an  active  query q, without calling a callback routine.
517              After completion, the query identifier q is not valid.
518
519

TYPE-SPECIFIC QUERIES

521       In addition to the generic low-level query interface, the library  pro‐
522       vides a set of routines to perform specific queries in a type-safe man‐
523       ner, as well as parsers for several well-known resource  record  types.
524       The  library  implements  high-level interface for A, AAAA, PTR, MX and
525       TXT records and DNSBL and RHSBL functionality.  These routines  returns
526       specific  types  as result of a query, instead of raw DNS packets.  The
527       following types and routines are available.
528
529
530       struct dns_rr_null {
531         char *dnsn_qname;     /* original query name */
532         char *dnsn_cname;     /* canonical name */
533         unsigned dnsn_ttl;    /* Time-To-Live (TTL) value */
534         int dnsn_nrr;         /* number of records in the set */
535       };
536
537       NULL RR set, used as a base for all other RR type structures.  Every RR
538       structure  as  used  by  the  library  have  four standard fields as in
539       struct dns_rr_null.
540
541
542   IN A Queries
543       struct dns_rr_a4 {       /* IN A RRset */
544         char *dnsa4_qname;     /* original query name */
545         char *dnsa4_cname;     /* canonical name */
546         unsigned dnsa4_ttl;    /* Time-To-Live (TTL) value */
547         int dnsa4_nrr;         /* number of addresses in the set */
548         struct in_addr dnsa4_addr[]; /* array of addresses */
549       };
550       typedef void
551         dns_query_a4_fn(ctx, struct dns_rr_a4 *result, data)
552       dns_parse_fn dns_parse_a4;
553       struct dns_query *
554       dns_submit_a4(ctx, const char *name, int flags,
555          dns_query_a4_fn *cbck, data);
556       struct dns_rr_a4 *
557       dns_resolve_a4(ctx, const char *name, int flags);
558
559       The dns_rr_a4 structure holds a result of an IN A query,  which  is  an
560       array of IPv4 addresses.  Callback routine for IN A queries expected to
561       be of type dns_query_a4_fn, which expects pointer to  dns_rr_a4  struc‐
562       ture  as query result instead of raw DNS packet.  The dns_parse_a4() is
563       used to convert raw DNS reply packet into dns_rr_a4  structure  (it  is
564       used  internally and may be used directly too with generic query inter‐
565       face).  Routines dns_submit_a4() and dns_resolve_a4() are used to  per‐
566       form  A  IN  queries  in a type-safe manner.  The name parameter is the
567       domain name in question, and flags is query  flags  bitmask,  with  one
568       bit,  DNS_NOSRCH,  of practical interest (if the name is absolute, that
569       is, it ends up with a dot, DNS_NOSRCH flag will be set automatically).
570
571
572   IN AAAA Queries
573       struct dns_rr_a6 {       /* IN AAAA RRset */
574         char *dnsa6_qname;     /* original query name */
575         char *dnsa6_cname;     /* canonical name */
576         unsigned dnsa6_ttl;    /* Time-To-Live (TTL) value */
577         int dnsa6_nrr;         /* number of addresses in the set */
578         struct in6_addr dnsa6_addr[]; /* array of addresses */
579       };
580       typedef void
581         dns_query_a6_fn(ctx, struct dns_rr_a6 *result, data)
582       dns_parse_fn dns_parse_a6;
583       struct dns_query *
584       dns_submit_a6(ctx, const char *name, int flags,
585          dns_query_a6_fn *cbck, data);
586       struct dns_rr_a6 *
587       dns_resolve_a6(ctx, const char *name, int flags);
588
589       The dns_rr_a6 structure holds a result of an IN AAAA query, which is an
590       array of IPv6 addresses.  Callback routine for IN AAAA queries expected
591       to be of type  dns_query_a6_fn,  which  expects  pointer  to  dns_rr_a6
592       structure   as   query   result   instead   of  raw  DNS  packet.   The
593       dns_parse_a6() is used to convert raw DNS reply packet  into  dns_rr_a6
594       structure  (it  is  used  internally  and may be used directly too with
595       generic    query    interface).     Routines    dns_submit_a6()     and
596       dns_resolve_a6()  are  used  to  perform AAAA IN queries in a type-safe
597       manner.  The name parameter is the domain name in question,  and  flags
598       is query flags bitmask, with one bit, DNS_NOSRCH, of practical interest
599       (if the name is absolute, that is, it ends up with  a  dot,  DNS_NOSRCH
600       flag will be set automatically).
601
602
603   IN PTR Queries
604       struct dns_rr_ptr {       /* IN PTR RRset */
605         char *dnsptr_qname;     /* original query name */
606         char *dnsptr_cname;     /* canonical name */
607         unsigned dnsptr_ttl;    /* Time-To-Live (TTL) value */
608         int dnsptr_nrr;         /* number of domain name pointers */
609         char *dnsptr_ptr[];     /* array of domain name pointers */
610       };
611       typedef void
612         dns_query_ptr_fn(ctx, struct dns_rr_ptr *result, data)
613       dns_parse_fn dns_parse_ptr;
614       struct dns_query *
615       dns_submit_a4ptr(ctx, const struct in_addr *addr,
616          dns_query_ptr_fn *cbck, data);
617       struct dns_rr_ptr *
618       dns_resolve_a4ptr(ctx, const struct in_addr *addr);
619       struct dns_query *
620       dns_submit_a6ptr(ctx, const struct in6_addr *addr,
621          dns_query_ptr_fn *cbck, data);
622       struct dns_rr_ptr *
623       dns_resolve_a6ptr(ctx, const struct in6_addr *addr);
624
625       The dns_rr_ptr structure holds a result of an IN PTR query, which is an
626       array of domain name pointers for a given IPv4 or IPv6 address.   Call‐
627       back   routine   for   IN   PTR   queries   expected   to  be  of  type
628       dns_query_ptr_fn, which expects  pointer  to  dns_rr_ptr  structure  as
629       query result instead of raw DNS packet.  The dns_parse_ptr() is used to
630       convert raw DNS reply packet into  dns_rr_ptr  structure  (it  is  used
631       internally  and may be used directly too with generic query interface).
632       Routines dns_submit_a4ptr() and dns_resolve_a4ptr() are used to perform
633       IN  PTR  queries  for  IPv4  addresses  in a type-safe manner. Routines
634       dns_submit_a6ptr() and dns_resolve_a6ptr() are used to perform  IN  PTR
635       queries for IPv6 addresses.
636
637
638   IN MX Queries
639       struct dns_mx {          /* single MX record */
640         int priority;          /* priority value of this MX */
641         char *name;            /* domain name of this MX */
642       };
643       struct dns_rr_mx {       /* IN MX RRset */
644         char *dnsmx_qname;     /* original query name */
645         char *dnsmx_cname;     /* canonical name */
646         unsigned dnsmx_ttl;    /* Time-To-Live (TTL) value */
647         int dnsmx_nrr;         /* number of mail exchangers in the set */
648         struct dns_mx dnsmx_mx[]; /* array of mail exchangers */
649       };
650       typedef void
651         dns_query_mx_fn(ctx, struct dns_rr_mx *result, data)
652       dns_parse_fn dns_parse_mx;
653       struct dns_query *
654       dns_submit_mx(ctx, const char *name, int flags,
655          dns_query_mx_fn *cbck, data);
656       struct dns_rr_mx *
657       dns_resolve_mx(ctx, const char *name, int flags);
658
659       The  dns_rr_mx  structure holds a result of an IN MX query, which is an
660       array of mail exchangers for a given domain.  Callback routine  for  IN
661       MX  queries  expected  to  be  of  type  dns_query_mx_fn, which expects
662       pointer to dns_rr_mx structure as  query  result  instead  of  raw  DNS
663       packet.   The  dns_parse_mx()  is  used to convert raw DNS reply packet
664       into dns_rr_mx structure  (it  is  used  internally  and  may  be  used
665       directly  too  with generic query interface).  Routines dns_submit_mx()
666       and dns_resolve_mx() are used to perform IN MX queries in  a  type-safe
667       manner.   The  name parameter is the domain name in question, and flags
668       is query flags bitmask, with one bit, DNS_NOSRCH, of practical interest
669       (if  the  name  is absolute, that is, it ends up with a dot, DNS_NOSRCH
670       flag will be set automatically).
671
672
673   TXT Queries
674       struct dns_txt {          /* single TXT record */
675         int len;                /* length of the text */
676         unsigned char *txt;     /* pointer to the text */
677       };
678       struct dns_rr_txt {       /* TXT RRset */
679         char *dnstxt_qname;     /* original query name */
680         char *dnstxt_cname;     /* canonical name */
681         unsigned dnstxt_ttl;    /* Time-To-Live (TTL) value */
682         int dnstxt_nrr;         /* number of text records in the set */
683         struct dns_txt dnstxt_txt[]; /* array of TXT records */
684       };
685       typedef void
686         dns_query_txt_fn(ctx, struct dns_rr_txt *result, data)
687       dns_parse_fn dns_parse_txt;
688       struct dns_query *
689       dns_submit_txt(ctx, const char *name, enum dns_class qcls,
690          int flags, dns_query_txt_fn *cbck, data);
691       struct dns_rr_txt *
692       dns_resolve_txt(ctx, const char *name,
693                    enum dns_class qcls, int flags);
694
695       The dns_rr_txt structure holds a result of a TXT  query,  which  is  an
696       array  of  text  records for a given domain name.  Callback routine for
697       TXT queries expected to be  of  type  dns_query_txt_fn,  which  expects
698       pointer  to  dns_rr_txt  structure  as  query result instead of raw DNS
699       packet.  The dns_parse_txt() is used to convert raw  DNS  reply  packet
700       into  dns_rr_txt  structure  (it  is  used  internally  and may be used
701       directly too with generic query interface).  Routines  dns_submit_txt()
702       and  dns_resolve_txt() are used to perform IN MX queries in a type-safe
703       manner.  The name parameter is the domain name in question,  and  flags
704       is query flags bitmask, with one bit, DNS_NOSRCH, of practical interest
705       (if the name is absolute, that is, it ends up with  a  dot,  DNS_NOSRCH
706       flag  will  be set automatically).  Note that each TXT string is repre‐
707       sented by struct dns_txt, while zero-terminated (and the len  field  of
708       the  structure  does  not include the terminator), may contain embedded
709       null characters -- content of TXT records is  not  interpreted  by  the
710       library in any way.
711
712
713   SRV Queries
714       struct dns_srv {          /* single SRV record */
715         int priority;           /* priority of the record */
716         int weight;             /* weight of the record */
717         int port;               /* the port number to connect to */
718         char *name;             /* target host name */
719       };
720       struct dns_rr_srv {       /* SRV RRset */
721         char *dnssrv_qname;     /* original query name */
722         char *dnssrv_cname;     /* canonical name */
723         unsigned dnssrv_ttl;    /* Time-To-Live (TTL) value */
724         int dnssrv_nrr;         /* number of text records in the set */
725         struct dns_srv dnssrv_srv[]; /* array of SRV records */
726       };
727       typedef void
728         dns_query_srv_fn(ctx, struct dns_rr_srv *result, data)
729       dns_parse_fn dns_parse_srv;
730       struct dns_query *
731       dns_submit_srv(ctx, const char *name, const char *service, const char *protocol,
732          int flags, dns_query_txt_fn *cbck, data);
733       struct dns_rr_srv *
734       dns_resolve_srv(ctx, const char *name, const char *service, const char *protocol,
735                    int flags);
736
737       The  dns_rr_srv  structure holds a result of an IN SRV (rfc2782) query,
738       which is an array of servers (together with  port  numbers)  which  are
739       performing  operations  for  a  given service using given protocol on a
740       target domain name.  Callback routine for IN SRV queries expected to be
741       of type dns_query_srv_fn, which expects pointer to dns_rr_srv structure
742       as query result instead of raw DNS packet.  The dns_parse_srv() is used
743       to  convert  raw DNS reply packet into dns_rr_srv structure (it is used
744       internally and may be used directly too with generic query  interface).
745       Routines  dns_submit_srv() and dns_resolve_srv() are used to perform IN
746       SRV queries in a type-safe manner.  The name parameter  is  the  domain
747       name  in  question,  service  and protocl specifies the service and the
748       protocol in question (the library will construct query DN according  to
749       rfc2782  rules)  and may be NULL (in this case the library assumes name
750       parameter holds the complete SRV query), and flags is query flags  bit‐
751       mask,  with  one bit, DNS_NOSRCH, of practical interest (if the name is
752       absolute, that is, it ends up with a dot, DNS_NOSRCH flag will  be  set
753       automatically).
754
755
756   NAPTR Queries
757       struct dns_naptr {        /* single NAPTR record */
758         int order;              /* record order */
759         int preference;         /* preference of this record */
760         char *flags;            /* application-specific flags */
761         char *services;         /* service parameters */
762         char *regexp;           /* substitutional regular expression */
763         char *replacement;      /* replacement string */
764       };
765       struct dns_rr_naptr {     /* NAPTR RRset */
766         char *dnsnaptr_qname;   /* original query name */
767         char *dnsnaptr_cname;   /* canonical name */
768         unsigned dnsnaptr_ttl;  /* Time-To-Live (TTL) value */
769         int dnsnaptr_nrr;       /* number of text records in the set */
770         struct dns_naptr dnsnaptr_naptr[]; /* array of NAPTR records */
771       };
772       typedef void
773         dns_query_naptr_fn(ctx, struct dns_rr_naptr *result, data)
774       dns_parse_fn dns_parse_naptr;
775       struct dns_query *
776       dns_submit_naptr(ctx, const char *name, int flags,
777          dns_query_txt_fn *cbck, data);
778       struct dns_rr_naptr *
779       dns_resolve_naptr(ctx, const char *name, int flags);
780
781       The  dns_rr_naptr  structure  holds  a  result of an IN NAPTR (rfc3403)
782       query.  Callback routine for IN NAPTR queries expected to  be  of  type
783       dns_query_naptr_fn,  expects pointer to dns_rr_naptr structure as query
784       result instead of raw DNS packet.  The  dns_parse_naptr()  is  used  to
785       convert  raw  DNS  reply packet into dns_rr_naptr structure (it is used
786       internally and may be used directly too with generic query  interface).
787       Routines dns_submit_naptr() and dns_resolve_naptr() are used to perform
788       IN NAPTR queries in a type-safe manner.   The  name  parameter  is  the
789       domain  name  in  question,  and flags is query flags bitmask, with one
790       bit, DNS_NOSRCH, of practical interest (if the name is  absolute,  that
791       is, it ends up with a dot, DNS_NOSRCH flag will be set automatically).
792
793
794   DNSBL Interface
795       A  DNS-based  blocklists,  or a DNSBLs, are in wide use nowadays, espe‐
796       cially to protect mailservers  from  spammers.   The  library  provides
797       DNSBL  interface,  a set of routines to perform queries against DNSBLs.
798       Routines accepts an IP address (IPv4 and IPv6 are both supported) and a
799       base  DNSBL  zone  as query parameters, and returns either dns_rr_a4 or
800       dns_rr_txt structure.  Note that IPv6 interface return IPv4 RRset.
801
802       struct dns_query *
803       dns_submit_a4dnsbl(ctx,
804         const struct in_addr *addr, const char *dnsbl,
805         dns_query_a4_fn *cbck, void *data);
806       struct dns_query *
807       dns_submit_a4dnsbl_txt(ctx,
808         const struct in_addr *addr, const char *dnsbl,
809         dns_query_txt_fn *cbck, void *data);
810       struct dns_query *
811       dns_submit_a6dnsbl(ctx,
812         const struct in6_addr *addr, const char *dnsbl,
813         dns_query_a4_fn *cbck, void *data);
814       struct dns_query *
815       dns_submit_a6dnsbl_txt(ctx,
816         const struct in6_addr *addr, const char *dnsbl,
817         dns_query_txt_fn *cbck, void *data);
818       struct dns_rr_a4 *dns_resolve_a4dnsbl(ctx,
819         const struct in_addr *addr, const char *dnsbl)
820       struct dns_rr_txt *dns_resolve_a4dnsbl_txt(ctx,
821         const struct in_addr *addr, const char *dnsbl)
822       struct dns_rr_a4 *dns_resolve_a6dnsbl(ctx,
823         const struct in6_addr *addr, const char *dnsbl)
824       struct dns_rr_txt *dns_resolve_a6dnsbl_txt(ctx,
825         const struct in6_addr *addr, const char *dnsbl)
826       Perform (submit or resolve) a DNSBL query for the  given  dnsbl  domain
827       and an IP addr in question, requesting either A or TXT records.
828
829
830   RHSBL Interface
831       RHSBL  is similar to DNSBL, but instead of an IP address, the parameter
832       is a domain name.
833
834       struct dns_query *
835       dns_submit_rhsbl(ctx, const char *name, const char *rhsbl,
836         dns_query_a4_fn *cbck, void *data);
837       struct dns_query *
838       dns_submit_rhsbl_txt(ctx, const char *name, const char *rhsbl,
839         dns_query_txt_fn *cbck, void *data);
840       struct dns_rr_a4 *
841       dns_resolve_rhsbl(ctx, const char *name, const char *rhsbl);
842       struct dns_rr_txt *
843       dns_resolve_rhsbl_txt(ctx, const char *name, const char *rhsbl);
844       Perform (submit or resolve) a RHSBL query for the  given  rhsbl  domain
845       and name in question, requesting either A or TXT records.
846
847
848

LOW-LEVEL INTERFACE

850   Domain Names (DNs)
851       A  DN  is  a series of domain name labels each starts with length byte,
852       followed by empty label (label with zero length).  The  following  rou‐
853       tines to work with DNs are provided.
854
855
856       unsigned dns_dnlen(const unsigned char *dn)
857              return  length  of the domain name dn, including the terminating
858              label.
859
860
861       unsigned dns_dnlabels(const unsigned char *dn)
862              return number of non-zero labels in domain name dn.
863
864
865       unsigned dns_dnequal(dn1, dn2)
866         const unsigned char *dn1, *dn2;
867              test whenever the two domain  names,  dn1  and  dn2,  are  equal
868              (case-insensitive).   Return domain name length if equal or 0 if
869              not.
870
871
872       unsigned dns_dntodn(sdn, ddn, dnsiz)
873         const unsigned char *sdn;
874         unsigned char *ddn;
875         unsigned dnsiz;
876              copies the source domain name sdn to destination buffer  ddn  of
877              size dnsiz.  Return domain name length or 0 if ddn is too small.
878
879
880       int dns_ptodn(name, namelen, dn, dnsiz, isabs)
881       int dns_sptodn(name, dn, dnsiz)
882         const char *name; unsigned namelen;
883         unsigned char *dn; unsigned dnsiz;
884         int *isabs;
885              convert asciiz name name of length namelen to DN format, placing
886              result into buffer dn of size dnsiz.  Return length of the DN if
887              successeful,  0 if the dn buffer supplied is too small, or nega‐
888              tive value if name is invalid.  If isabs is non-NULL and conver‐
889              sion  was  successeful,  *isabs  will  be  set  to either 1 or 0
890              depending whenever name was absolute (i.e. ending with a dot) or
891              not.   Name  length,  namelength,  may  be  zero,  in which case
892              strlen(name) will be used.  Second form, dns_sptodn(), is a sim‐
893              plified form of dns_ptodn(), equivalent to
894              dns_ptodn(name, 0, dn, dnlen, 0).
895
896
897       extern const unsigned char dns_inaddr_arpa_dn[]
898       int dns_a4todn(const struct in_addr *addr, const unsigned char *tdn,
899             unsigned char *dn, unsigned dnsiz)
900       int dns_a4ptodn(const struct in_addr *addr, const char *tname,
901             unsigned char *dn, unsigned dnsiz)
902       extern const unsigned char dns_ip6_arpa_dn[]
903       int dns_a6todn(const struct in6_addr *addr, const unsigned char *tdn,
904             unsigned char *dn, unsigned dnsiz)
905       int dns_a6ptodn(const struct in6_addr *addr, const char *tname,
906             unsigned char *dn, unsigned dnsiz)
907              several  variants  of  routines to convert IPv4 and IPv6 address
908              addr into reverseDNS-like domain  name  in  DN  format,  storing
909              result  in  dn  of  size dnsiz.  tdn (or tname) is the base zone
910              name, like in-addr.arpa for IPv4 or in6.arpa for IPv6.   If  tdn
911              (or tname) is NULL, dns_inaddr_arpa_dn (or dns_ip6_arpa_dn) will
912              be used.  The routines may be used to construct a DN for a DNSBL
913              lookup for example.  All routines return length of the resulting
914              DN on success, -1 if resulting DN is invalid, or  0  if  the  dn
915              buffer (dnsiz) is too small.  To hold standard rDNS DN, a buffer
916              of size DNS_A4RSIZE (30 bytes) for IPv4 address, or  DNS_A6RSIZE
917              (74 bytes) for IPv6 address, is sufficient.
918
919
920       int dns_dntop(dn, name, namesiz)
921          const unsigned char *dn;
922          const char *name; unsigned namesiz;
923              convert  domain  name  dn in DN format to asciiz string, placing
924              result into name buffer of  size  namesiz.   Maximum  length  of
925              asciiz  representation  of  domain  name  is  DNS_MAXNAME (1024)
926              bytes.  Root domain is  represented  as  empty  string.   Return
927              length  of  the resulting name (including terminating character,
928              i.e. strlen(name)+1) on success, 0 if the  name  buffer  is  too
929              small,  or  negative  value  if  dn is invalid (last case should
930              never happen since all routines in this  library  which  produce
931              domain names ensure the DNs generated are valid).
932
933
934       const char *dns_dntosp(const unsigned char *dn)
935              convert  domain  name  dn  in  DN  format to asciiz string using
936              static buffer.  Return the resulting asciiz string on success or
937              NULL on failure.  Note since this routine uses static buffer, it
938              is not thread-safe.
939
940
941       unsigned dns_dntop_size(const unsigned char *dn)
942              return the buffer size needed to convert the dn domain  name  in
943              DN format to asciiz string, for dns_dntop().  The routine return
944              either the size of buffer required, including the trailing  zero
945              byte, or 0 if dn is invalid.
946
947
948   Working with DNS Packets
949       The  following  routines  are provided to encode and decode DNS on-wire
950       packets.  This is low-level interface.
951
952
953       DNS response codes (returned by dns_rcode()  routine)  are  defined  as
954       constants  prefixed  with  DNS_R_.  See udns.h header file for the com‐
955       plete list.  In particular, constants  DNS_R_NOERROR  (0),  DNS_R_SERV‐
956       FAIL, DNS_R_NXDOMAIN may be of interest to an application.
957
958
959       unsigned dns_get16(const unsigned char *p)
960       unsigned dns_get32(const unsigned char *p)
961              helper  routines,  convert  16-bit  or 32-bit integer in on-wire
962              format pointed to by p to unsigned.
963
964
965       unsigned char *dns_put16(unsigned char *d, unsigned n)
966       unsigned char *dns_put32(unsigned char *d, unsigned n)
967              helper routine, convert unsigned 16-bit or 32-bit integer  n  to
968              on-wire format to buffer pointed to by d, return d+2 or d+4.
969
970
971       DNS_HSIZE (12)
972              defines  size  of  DNS  header.   Data section in the DNS packet
973              immediately follows the header.  In the header, there are  query
974              identifier (id), various flags and codes, and number of resource
975              records in various data sections.  See udns.h  header  file  for
976              complete list of DNS header definitions.
977
978
979       unsigned dns_qid(const unsigned char *pkt)
980       int dns_rd(const unsigned char *pkt)
981       int dns_tc(const unsigned char *pkt)
982       int dns_aa(const unsigned char *pkt)
983       int dns_qr(const unsigned char *pkt)
984       int dns_ra(const unsigned char *pkt)
985       unsigned dns_opcode(const unsigned char *pkt)
986       unsigned dns_rcode(const unsigned char *pkt)
987       unsigned dns_numqd(const unsigned char *pkt)
988       unsigned dns_numan(const unsigned char *pkt)
989       unsigned dns_numns(const unsigned char *pkt)
990       unsigned dns_numar(const unsigned char *pkt)
991       const unsigned char *dns_payload(const unsigned char *pkt)
992              return various parts from the DNS packet header pkt: query iden‐
993              tifier (qid), recursion desired (rd)  flag,  truncation  occured
994              (tc)  flag,  authoritative answer (aa) flag, query response (qr)
995              flag, recursion available (ra) flag,  operation  code  (opcode),
996              result  code  (rcode),  number  of  entries  in question section
997              (numqd), number of answers (numan), number of authority  records
998              (numns),  number  of additional records (numar), and the pointer
999              to the packet data (payload).
1000
1001
1002       int dns_getdn(pkt, curp, pkte, dn, dnsiz)
1003       const unsigned char *dns_skipdn(cur, pkte)
1004          const unsigned char *pkt, *pkte, **curp, *cur;
1005          unsigned char *dn; unsigned dnsiz;
1006              dns_getdn() extract DN from DNS packet  pkt  which  ends  before
1007              pkte  starting at position *curp into buffer pointed to by dn of
1008              size dnsiz.  Upon successeful completion, *curp  will  point  to
1009              the next byte in the packet after the extracted domain name.  It
1010              return positive number (length of the DN if dn) upon successeful
1011              completion,  negative  value  on error (when the packet contains
1012              invalid data), or zero if the dnsiz is too small (maximum length
1013              of  a domain name is DNS_MAXDN).  dns_skipdn() return pointer to
1014              the next byte in DNS packet which ends up before  pkte  after  a
1015              domain  name which starts at the cur byte, or NULL if the packet
1016              is invalid.  dns_skipdn() is more or  less  equivalent  to  what
1017              dns_getdn() does, except it does not actually extract the domain
1018              name in question, and uses simpler interface.
1019
1020
1021       struct dns_rr {
1022         unsigned char dnsrr_dn[DNS_MAXDN]; /* the RR DN name */
1023         enum dns_class dnsrr_cls;          /* class of the RR */
1024         enum dns_type  dnsrr_typ;          /* type of the RR */
1025         unsigned dnsrr_ttl;                /* TTL value */
1026         unsigned dnsrr_dsz;                /* size of data in bytes */
1027         const unsigned char *dnsrr_dptr;   /* pointer to the first data byte */
1028         const unsigned char *dnsrr_dend;   /* next byte after RR */
1029       };
1030              The dns_rr structure is used to hold  information  about  single
1031              DNS Resource Record (RR) in an easy to use form.
1032
1033
1034       struct dns_parse {
1035         const unsigned char *dnsp_pkt; /* pointer to the packet being parsed */
1036         const unsigned char *dnsp_end; /* end of the packet pointer */
1037         const unsigned char *dnsp_cur; /* current packet positionn */
1038         const unsigned char *dnsp_ans; /* pointer to the answer section */
1039         int dnsp_rrl;                  /* number of RRs left */
1040         int dnsp_nrr;                  /* number of relevant RRs seen so far */
1041         unsigned dnsp_ttl;             /* TTL value so far */
1042         const unsigned char *dnsp_qdn; /* the domain of interest or NULL */
1043         enum dns_class dnsp_qcls;      /* class of interest or 0 for any */
1044         enum dns_type  dnsp_qtyp;      /* type of interest or 0 for any */
1045         unsigned char dnsp_dnbuf[DNS_MAXDN]; /* domain name buffer */
1046       };
1047              The  dns_parse  structure is used to parse DNS reply packet.  It
1048              holds information  about  the  packet  being  parsed  (dnsp_pkt,
1049              dnsp_end and dnsp_cur fields), number of RRs in the current sec‐
1050              tion left to do, and the information  about  specific  RR  which
1051              we're looking for (dnsp_qdn, dnsp_qcls and dnsp_qtyp fields).
1052
1053
1054       int dns_initparse(struct dns_parse *p,
1055         const unsigned char *qdn,
1056         const unsigned char *pkt,
1057         const unsigned char *cur,
1058         const unsigned char *end)
1059              initializes  the RR parsing structure p.  Arguments pkt, cur and
1060              end should describe the received packet: pkt is the start of the
1061              packet, end points to the next byte after the end of the packet,
1062              and cur points past the query DN  in  query  section  (to  query
1063              class+type  information).  And qdn points to the query DN.  This
1064              is the arguments passed  to  dns_parse_fn()  routine.  dns_init‐
1065              parse()  initializes  dnsp_pkt,  dnsp_end and dnsp_qdn fields to
1066              the corresponding arguments, extracts and initializes  dnsp_qcls
1067              and  dnsp_qtyp  fields  to the values found at cur pointer, ini‐
1068              tializes dnsp_cur and dnsp_ans fields to be cur+4 (to the  start
1069              of  answer section), and initializes dnsp_rrl field to be number
1070              of entries in answer section. dnsp_ttl will be set  to  max  TTL
1071              value, 0xffffffff, and dnsp_nrr to 0.
1072
1073
1074       int dns_nextrr(struct dns_parse *p, struct dns_rr *rr);
1075              searches  for  next  RR in the packet based on the criteria pro‐
1076              vided in the p  structure,  filling  in  the  rr  structure  and
1077              advancing  p->dnsp_cur  to the next RR in the packet.  RR selec‐
1078              tion is based on dnsp_qdn, dnsp_qcls and dnsp_qtyp fields in the
1079              dns_parse  structure.   Any  (or  all) of the 3 fields may be 0,
1080              which means any actual value from the packet is acceptable.   In
1081              case  the  field  isn't  0 (or NULL for dnsp_qdn), only RRs with
1082              corresponding  characteristics  are  acceptable.   Additionally,
1083              when dnsp_qdn is non-NULL, dns_nextrr() performs automatic CNAME
1084              expansion.  Routine will return positive value on success, 0  in
1085              case  it  reached  the  end  of  current  section  in the packet
1086              (p->dnsp_rrl is zero), or negative value if next RR can  not  be
1087              decoded   (packet  format  is  invalid).   The  routine  updates
1088              p->dnsp_qdn automatically when this field  is  non-NULL  and  it
1089              encounters   appropriate  CNAME  RRs  (saving  CNAME  target  in
1090              p->dnsp_dnbuf), so after end of the  process,  p->dnsp_qdn  will
1091              point  to canonical name of the domain in question.  The routine
1092              updates p->dnsp_ttl value to be  the  minimum  TTL  of  all  RRs
1093              found.
1094
1095
1096       void dns_rewind(struct dns_parse *p, const unsigned char *qdn)
1097              this routine "rewinds" the packet parse state structure to be at
1098              the same state as after a call to dns_initparse(), i.e.  reposi‐
1099              tion  the  parse  structure p to the start of answer section and
1100              initialize p->dnsp_rrl to the number of entries in  answer  sec‐
1101              tion.
1102
1103
1104       int dns_stdrr_size(const struct dns_parse *p);
1105              return  size  to  hold  standard RRset structure information, as
1106              shown in dns_rr_null structure  (for  the  query  and  canonical
1107              names).  Used to calculate amount of memory to allocate for com‐
1108              mon part of type-specific RR structures in parsing routines.
1109
1110
1111       void *dns_stdrr_finish(struct dns_rr_null *ret, char *cp,
1112         const struct dns_parse *p);
1113              initializes standard RRset fields in ret structure using  buffer
1114              pointed  to  by  cp, which should have at least as many bytes as
1115              dns_stdrr_size(p) returned.  Used to  finalize  common  part  of
1116              type-specific RR structures in parsing routines.
1117
1118
1119       See  library  source for usage examples of all the above low-level rou‐
1120       tines, especially source of the parsing routines.
1121
1122
1123   Auxilary Routines
1124       int dns_pton(int af, const char *src, void *dst);
1125              privides functionality similar to standard inet_pton()  routine,
1126              to  convert  printable representation of an IP address of family
1127              af (either AF_INET or AF_INET6) pointed to by  src  into  binary
1128              form  suitable  for  socket addresses and transmission over net‐
1129              work, in buffer pointed  to  by  dst.   The  destination  buffer
1130              should  be of size 4 for AF_INET family or 16 for AF_INET6.  The
1131              return value is positive on success, 0 if src  is  not  a  valid
1132              text  representation  of an address of family af, or negative if
1133              the given address family is not supported.
1134
1135
1136       const char *dns_ntop(int af, const void *src,
1137           char *dst, int dstsize)
1138              privides functionality similar to standard inet_ntop()  routine,
1139              to  convert  binary representation of an IP address of family af
1140              (either AF_INET or AF_INET6) pointed to by src (either 4  or  16
1141              bytes) into printable form in buffer in buffer pointed to by dst
1142              of size dstsize.  The destination buffer should be at  least  of
1143              size  16 bytes for AF_INET family or 46 bytes for AF_INET6.  The
1144              return value is either dst, or NULL pointer if  dstsize  is  too
1145              small to hold this address or if the given address family is not
1146              supported.
1147
1148

AUTHOR

1150       The udns library has been written by Michael Tokarev, mjt@corpit.ru.
1151
1152

VERSION

1154       This manual page corresponds to udns version 0.0.9, released Jan-2007.
1155
1156
1157
1158Library Functions                  Jan 2007                            udns(3)
Impressum