chiark / gitweb /
adns_str* etc.: Return NULL rather than crashing, and docs
[adns.git] / src / adns.h
index a29b568f33b8061de88e54b3883eb9d914f61557..b8072eeb77b37c9b288eb4ba3615799c369c4507 100644 (file)
@@ -1,19 +1,17 @@
 /*
  * adns.h
- * - adns user-visible API (single-threaded, without any locking)
+ * - adns user-visible API
  */
 /*
  *
- *  This file is
- *    Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk>
+ *  This file is part of adns, which is
+ *    Copyright (C) 1997-2000,2003,2006,2014-2016  Ian Jackson
+ *    Copyright (C) 1999-2000,2003,2006 Tony Finch
+ *    Copyright (C) 1991 Massachusetts Institute of Technology
  *
- *  It is part of adns, which is
- *    Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk>
- *    Copyright (C) 1999-2000 Tony Finch <dot@dotat.at>
- *  
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2, or (at your option)
+ *  the Free Software Foundation; either version 3, or (at your option)
  *  any later version.
  *  
  *  This program is distributed in the hope that it will be useful,
  *
  *  You should have received a copy of the GNU General Public License,
  *  or the GNU Library General Public License, as appropriate, along
- *  with this program; if not, write to the Free Software Foundation,
- *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ *  with this program; if not, write to the Free Software Foundation.
  *
- *  $Id$
  */
 
 #ifndef ADNS_H_INCLUDED
 #include <netinet/in.h>
 #include <sys/time.h>
 #include <unistd.h>
+#include <net/if.h>
 
 #ifdef __cplusplus
 extern "C" { /* I really dislike this - iwj. */
 #endif
 
+/* Whether to support address families other than IPv4 in responses which use
+ * the `adns_rr_addr' structure.  This is a source-compatibility issue: old
+ * clients may not expect to find address families other than AF_INET in
+ * their query results.  There's a separate binary compatibility issue to do
+ * with the size of the `adns_rr_addr' structure, but we'll assume you can
+ * cope with that because you have this header file.  Define
+ * `ADNS_FEATURE_IPV4ONLY' if you only want to see AF_INET addresses by
+ * default, or `ADNS_FEATURE_MANYAF' to allow multiple address families; the
+ * default is currently to stick with AF_INET only, but this is likely to
+ * change in a later release of ADNS.  Note that any adns_qf_want_... flags
+ * in your query are observed: this setting affects only the default address
+ * families.
+ */
+#if !defined(ADNS_FEATURE_IPV4ONLY) && !defined(ADNS_FEATURE_MANYAF)
+#  define ADNS_FEATURE_IPV4ONLY
+#elif defined(ADNS_FEATURE_IPV4ONLY) && defined(ADNS_FEATURE_MANYAF)
+#  error "Feature flags ADNS_FEATURE_IPV4ONLY and ..._MANYAF are incompatible"
+#endif
+
 /* All struct in_addr anywhere in adns are in NETWORK byte order. */
 
 typedef struct adns__state *adns_state;
@@ -85,8 +100,20 @@ typedef enum { /* In general, or together the desired flags: */
  adns_if_noautosys=   0x0010,/* do not make syscalls at every opportunity */
  adns_if_eintr=       0x0020,/* allow _wait and _synchronous to return EINTR */
  adns_if_nosigpipe=   0x0040,/* applic has SIGPIPE ignored, do not protect */
+ adns_if_monotonic=   0x0080,/* enable if you can; see adns_processtimeouts  */
  adns_if_checkc_entex=0x0100,/* consistency checks on entry/exit to adns fns */
- adns_if_checkc_freq= 0x0300 /* consistency checks very frequently (slow!) */
+ adns_if_checkc_freq= 0x0300,/* consistency checks very frequently (slow!) */
+
+ adns_if_permit_ipv4= 0x0400,/* allow _addr queries to return IPv4 addresses  */
+ adns_if_permit_ipv6= 0x0800,/* allow _addr queries to return IPv6 addresses */
+ adns_if_afmask=      0x0c00,
+   /* These are policy flags, and overridden by the adns_af:... option in
+    * resolv.conf.  If the adns_qf_want_... query flags are incompatible with
+    * these settings (in the sense that no address families are permitted at
+    * all) then the query flags take precedence; otherwise only records which
+    * satisfy all of the stated requirements are allowed.
+    */
+ adns__if_sizeforce= 0x7fff,
 } adns_initflags;
 
 typedef enum { /* In general, or together the desired flags: */
@@ -99,15 +126,42 @@ typedef enum { /* In general, or together the desired flags: */
  adns_qf_quoteok_anshost=0x00000040,/*  ... in things supposedly hostnames */
  adns_qf_quotefail_cname=0x00000080,/* refuse if quote-req chars in CNAME we go via */
  adns_qf_cname_loose=    0x00000100,/* allow refs to CNAMEs - without, get _s_cname */
+ adns_qf_cname_strict=   0x00010000,/* forbid CNAME refs (default, currently) */
  adns_qf_cname_forbid=   0x00000200,/* don't follow CNAMEs, instead give _s_cname */
- adns__qf_internalmask=  0x0ff00000
+
+ adns_qf_want_ipv4=     0x00000400,/* try to return IPv4 addresses */
+ adns_qf_want_ipv6=     0x00000800,/* try to return IPv6 addresses */
+ adns_qf_want_allaf=    0x00000c00,/* all the above flag bits */
+   /* Without any of the _qf_want_... flags, _qtf_deref queries try to return
+    * all address families permitted by _if_permit_... (as overridden by the
+    * `adns_af:...'  configuration option).  Set flags to restrict the
+    * returned address families to the ones selected.
+    */
+ adns_qf_ipv6_mapv4=    0x00001000,/*  ... return IPv4 addresses as v6-mapped */
+
+ adns_qf_addrlit_scope_forbid=0x00002000,/* forbid %<scope> in IPv6 literals */
+ adns_qf_addrlit_scope_numeric=0x00004000,/* %<scope> may only be numeric */
+ adns_qf_addrlit_ipv4_quadonly=0x00008000,/* reject non-dotted-quad ipv4 */
+
+ adns__qf_internalmask=  0x0ff00000,
+ adns__qf_sizeforce=     0x7fffffff
 } adns_queryflags;
 
 typedef enum {
  adns_rrt_typemask=  0x0ffff,
- adns__qtf_deref=    0x10000,/* dereference domains; perhaps get extra data */
+ adns_rrt_reprmask= 0xffffff,
+ adns__qtf_deref_bit=0x10000,/* internal version of ..._deref below */
  adns__qtf_mail822=  0x20000,/* return mailboxes in RFC822 rcpt field fmt   */
 
+ adns__qtf_bigaddr=0x1000000,/* use the new larger sockaddr union */
+ adns__qtf_manyaf= 0x2000000,/* permitted to return multiple address families */
+
+ adns__qtf_deref=    adns__qtf_deref_bit|adns__qtf_bigaddr
+#ifdef ADNS_FEATURE_MANYAF
+                    |adns__qtf_manyaf
+#endif
+                           ,/* dereference domains; perhaps get extra data */
+
  adns_r_unknown=     0x40000,
    /* To use this, ask for records of type   <rr-type-code>|adns_r_unknown.
     * adns will not process the RDATA - you'll get adns_rr_byteblocks,
@@ -138,7 +192,7 @@ typedef enum {
  adns_r_soa_raw=          6,
  adns_r_soa=                 adns_r_soa_raw|adns__qtf_mail822, 
                     
- adns_r_ptr_raw=         12, /* do not mind PTR with wrong or missing A */
+ adns_r_ptr_raw=         12, /* do not mind PTR with wrong or missing addr */
  adns_r_ptr=                 adns_r_ptr_raw|adns__qtf_deref,
                     
  adns_r_hinfo=           13,  
@@ -151,13 +205,17 @@ typedef enum {
  adns_r_rp_raw=          17,
  adns_r_rp=                  adns_r_rp_raw|adns__qtf_mail822,
 
+ adns_r_aaaa=           28,
+
  /* For SRV records, query domain without _qf_quoteok_query must look
   * as expected from SRV RFC with hostname-like Name.  _With_
   * _quoteok_query, any query domain is allowed. */
  adns_r_srv_raw=         33,
  adns_r_srv=                 adns_r_srv_raw|adns__qtf_deref,
                     
- adns_r_addr=                adns_r_a|adns__qtf_deref
+ adns_r_addr=                adns_r_a|adns__qtf_deref,
+
+ adns__rrt_sizeforce= 0x7fffffff,
  
 } adns_rrtype;
 
@@ -258,8 +316,8 @@ typedef enum {
  adns_s_max_tempfail= 99,
 
  /* remote configuration errors */
- adns_s_inconsistent, /* PTR gives domain whose A does not exist and match */
- adns_s_prohibitedcname, /* CNAME, but eg A expected (not if _qf_loosecname) */
+ adns_s_inconsistent, /* PTR gives domain whose addr is missing or mismatch */
+ adns_s_prohibitedcname, /* CNAME, but eg A expected (not if _qf_cname_loose) */
  adns_s_answerdomaininvalid,
  adns_s_answerdomaintoolong,
  adns_s_invaliddata,
@@ -281,14 +339,29 @@ typedef enum {
  
 } adns_status;
 
+typedef union {
+  struct sockaddr sa;
+  struct sockaddr_in inet;
+} adns_sockaddr_v4only;
+
+typedef union {
+  struct sockaddr sa;
+  struct sockaddr_in inet;
+  struct sockaddr_in6 inet6;
+} adns_sockaddr;
+
 typedef struct {
   int len;
-  union {
-    struct sockaddr sa;
-    struct sockaddr_in inet;
-  } addr;
+  adns_sockaddr addr;
 } adns_rr_addr;
 
+typedef struct {
+  /* the old v4-only structure; handy if you have complicated binary
+   * compatibility problems. */
+  int len;
+  adns_sockaddr_v4only addr;
+} adns_rr_addr_v4only;
+
 typedef struct {
   char *host;
   adns_status astatus;
@@ -354,6 +427,7 @@ typedef struct {
     adns_rr_intstr *(*manyistr);     /* txt (list strs ends with i=-1, str=0)*/
     adns_rr_addr *addr;              /* addr */
     struct in_addr *inaddr;          /* a */
+    struct in6_addr *in6addr;       /* aaaa */
     adns_rr_hostaddr *hostaddr;      /* ns */
     adns_rr_intstrpair *intstrpair;  /* hinfo */
     adns_rr_strpair *strpair;        /* rp, rp_raw */
@@ -400,6 +474,33 @@ typedef struct {
  *  requested.
  */
 
+/* Threads:
+ *  adns does not use any static modifiable state, so it
+ *   is safe to call adns_init several times and then use the
+ *   resulting adns_states concurrently.
+ *  However, it is NOT safe to make simultaneous calls into
+ *   adns using the same adns_state; a single adns_state must be used
+ *   only by one thread at a time.  You can solve this problem by
+ *   having one adns_state per thread, or if that isn't feasible, you
+ *   could maintain a pool of adns_states.  Unfortunately neither of
+ *   these approaches has optimal performance.
+ */
+
+/*
+ * Use of time:
+ *
+ * adns needs to manipulate timeouts.  For API compatibility reasons
+ * (adns predates clock_gettime) the default is to use wall clock time
+ * from gettimeofday.  This will malfunction if the system clock is
+ * not suitably stable.  To avoid this, you should set
+ *   adns_if_monotonic
+ *
+ * If you specify adns_if_monotonic then all `now' values passed to
+ * adns must be from clock_gettime(CLOCK_MONOTONIC).  clock_gettime
+ * returns a struct timespec; you must convert it to a struct timeval
+ * by dividing the nsec by 1000 to make usec, rounding down.
+ */
+
 int adns_init(adns_state *newstate_r, adns_initflags flags,
              FILE *diagfile /*0=>stderr*/);
 
@@ -492,6 +593,21 @@ int adns_init_logfn(adns_state *newstate_r, adns_initflags flags,
  *   Changes the consistency checking frequency; this overrides the
  *   setting of adns_if_check_entex, adns_if_check_freq, or neither,
  *   in the flags passed to adns_init.
+ *
+ *  adns_af:{ipv4,ipv6},...  adns_af:any
+ *   Determines which address families ADNS looks up (either as an
+ *   adns_r_addr query, or when dereferencing an answer yielding hostnames
+ *   (e.g., adns_r_mx).  The argument is a comma-separated list: only the
+ *   address families listed will be looked up.  The default is `any'.
+ *   Lookups occur (logically) concurrently; use the `sortlist' directive to
+ *   control the relative order of addresses in answers.  This option
+ *   overrides the corresponding init flags (covered by adns_if_afmask).
+ *
+ *  adns_ignoreunkcfg
+ *   Ignore unknown options and configuration directives, rather than
+ *   logging them.  To be effective, appear in the configuration
+ *   before the unknown options.  ADNS_RES_OPTIONS is generally early
+ *   enough.
  * 
  * There are a number of environment variables which can modify the
  * behaviour of adns.  They take effect only if adns_init is used, and
@@ -597,6 +713,61 @@ void adns_finish(adns_state ads);
  * they will be cancelled.
  */
 
+#define ADNS_ADDR2TEXT_BUFLEN                                  \
+  (INET6_ADDRSTRLEN + 1/*%*/                                   \
+  + ((IF_NAMESIZE-1) > 9 ? (IF_NAMESIZE-1) : 9/*uint32*/)      \
+  + 1/* nul; included in IF_NAMESIZE */)
+
+int adns_text2addr(const char *text, uint16_t port, adns_queryflags flags,
+                  struct sockaddr *sa_r,
+                  socklen_t *salen_io /* updated iff OK or ENOSPC */);
+int adns_addr2text(const struct sockaddr *sa, adns_queryflags flags,
+                  char *buffer, int *buflen_io /* updated ONLY on ENOSPC */,
+                  int *port_r /* may be 0 */);
+  /*
+   * port is always in host byte order and is simply copied to and
+   * from the appropriate sockaddr field (byteswapped as necessary).
+   *
+   * The only flags supported are adns_qf_addrlit_...
+   *
+   * Error return values are:
+   *
+   *  ENOSPC    Output buffer is too small.  Can only happen if
+   *            *buflen_io < ADNS_ADDR2TEXT_BUFLEN or
+   *            *salen_io < sizeof(adns_sockaddr).  On return,
+   *            *buflen_io or *salen_io has been updated by adns.
+   *
+   *  EINVAL    text has invalid syntax.
+   *
+   *            text represents an address family not supported by
+   *            this version of adns.
+   *
+   *            Scoped address supplied (text contained "%" or
+   *            sin6_scope_id nonzero) but caller specified
+   *            adns_qf_addrlit_scope_forbid.
+   *
+   *            Scope name (rather than number) supplied in text but
+   *            caller specified adns_qf_addrlit_scope_numeric.
+   *
+   *  EAFNOSUPPORT   sa->sa_family is not supported (addr2text only).
+   *
+   *  ENOSYS    Unsupported flags set.
+   *
+   * Only if neither adns_qf_addrlit_scope_forbid nor
+   * adns_qf_addrlit_scope_numeric are set:
+   *
+   *  ENOSYS    Scope name supplied in text but IPv6 address part of
+   *            sockaddr is not a link local address.
+   *
+   *  ENXIO     Scope name supplied in text but if_nametoindex
+   *            said it wasn't a valid local interface name.
+   *
+   *  EIO       Scoped address supplied but if_nametoindex failed
+   *            in an unexpected way; adns has printed a message to
+   *            stderr.
+   *
+   *  any other   if_nametoindex failed in a more-or-less expected way.
+   */
 
 void adns_forallqueries_begin(adns_state ads);
 adns_query adns_forallqueries_next(adns_state ads, void **context_r);
@@ -664,6 +835,8 @@ int adns_processexceptional(adns_state ads, int fd, const struct timeval *now);
  * use that fd and only in the manner specified, regardless of whether
  * adns_if_noautosys was specified.
  *
+ * now is as for adns_processtimeouts.
+ *
  * adns_processexceptional should be called when select(2) reports an
  * exceptional condition, or poll(2) reports POLLPRI.
  *
@@ -679,15 +852,19 @@ void adns_processtimeouts(adns_state ads, const struct timeval *now);
 /* Gives adns flow-of-control so that it can process any timeouts
  * which might have happened.  Very like _processreadable/writeable.
  *
- * now may be 0; if it isn't, *now must be the current time, recently
- * obtained from gettimeofday.
+ * now may be 0; if it isn't, *now must be the current time from
+ * gettimeofday, or iff adns_if_monotonic it must be converted
+ * from the results of clock_gettime(CLOCK_MONOTONIC) (with the
+ * timespec.tv_nsec rounded down to make timeval.tv_usec).
  */
 
 void adns_firsttimeout(adns_state ads,
                       struct timeval **tv_mod, struct timeval *tv_buf,
                       struct timeval now);
 /* Asks adns when it would first like the opportunity to time
- * something out.  now must be the current time, from gettimeofday.
+ * something out.
+ *
+ * now must be the current time, as for adns_processtimeouts.
  * 
  * If tv_mod points to 0 then tv_buf must be non-null, and
  * _firsttimeout will fill in *tv_buf with the time until the first
@@ -711,8 +888,9 @@ void adns_globalsystemfailure(adns_state ads);
  * adns_s_systemfail, and adns will close any stream sockets it has
  * open.
  *
- * This is used by adns, for example, if gettimeofday() fails.
- * Without this the program's event loop might start to spin !
+ * This is used by adns, for example, if gettimeofday() or
+ * clock_gettime fails.  Without this the program's event loop might
+ * start to spin !
  *
  * This call will never block.
  */
@@ -728,9 +906,11 @@ void adns_beforeselect(adns_state ads, int *maxfd, fd_set *readfds,
 /* Find out file descriptors adns is interested in, and when it would
  * like the opportunity to time something out.  If you do not plan to
  * block then tv_mod may be 0.  Otherwise, tv_mod and tv_buf are as
- * for adns_firsttimeout.  readfds, writefds, exceptfds and maxfd_io may
+ * for adns_processtimeouts.  readfds, writefds, exceptfds and maxfd_io may
  * not be 0.
  *
+ * now is as for adns_processtimeouts.
+ *
  * If tv_mod is 0 on entry then this will never actually do any I/O,
  * or change the fds that adns is using or the timeouts it wants.  In
  * any case it won't block, and it will set the timeout to zero if a
@@ -744,6 +924,8 @@ void adns_afterselect(adns_state ads, int maxfd, const fd_set *readfds,
  * select.  This is just a fancy way of calling adns_processreadable/
  * writeable/timeouts as appropriate, as if select had returned the
  * data being passed.  Always succeeds.
+ *
+ * now is as for adns_processtimeouts.
  */
 
 /*
@@ -807,6 +989,8 @@ int adns_beforepoll(adns_state ads, struct pollfd *fds,
  * descriptors, and use _firsttimeout is used to find out when adns
  * might want to time something out.)
  *
+ * now is as for adns_processtimeouts.
+ *
  * adns_beforepoll will return 0 on success, and will not fail for any
  * reason other than the fds buffer being too small (ERANGE).
  *
@@ -817,7 +1001,7 @@ int adns_beforepoll(adns_state ads, struct pollfd *fds,
  * In any case this call won't block.
  */
 
-#define ADNS_POLLFDS_RECOMMENDED 2
+#define ADNS_POLLFDS_RECOMMENDED 3
 /* If you allocate an fds buf with at least RECOMMENDED entries then
  * you are unlikely to need to enlarge it.  You are recommended to do
  * so if it's convenient.  However, you must be prepared for adns to
@@ -829,6 +1013,8 @@ void adns_afterpoll(adns_state ads, const struct pollfd *fds, int nfds,
 /* Gives adns flow-of-control for a bit; intended for use after
  * poll(2).  fds and nfds should be the results from poll().  pollfd
  * structs mentioning fds not belonging to adns will be ignored.
+ *
+ * now is as for adns_processtimeouts.
  */
 
 
@@ -899,8 +1085,11 @@ const char *adns_errtypeabbrev(adns_status st);
  * the abbreviation of the error - eg, for adns_s_timeout it returns
  * "timeout".  adns_errtypeabbrev returns the abbreviation of the
  * error class: ie, for values up to adns_s_max_XXX it will return the
- * string XXX.  You MUST NOT call these functions with status values
- * not returned by the same adns library.
+ * string XXX.
+ *
+ * If you call these functions with status values not actually
+ * returned from other functions in the same adns library, the
+ * returned information may be NULL.
  */
 
 #ifdef __cplusplus