X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fadns.h;h=b8072eeb77b37c9b288eb4ba3615799c369c4507;hb=2b44fb38172ff0d64d1d5d907e3322d5e1a6a8ca;hp=a29b568f33b8061de88e54b3883eb9d914f61557;hpb=2c6eb096dd80e37c12ec5a301b771ff011fc00ce;p=adns.git diff --git a/src/adns.h b/src/adns.h index a29b568..b8072ee 100644 --- a/src/adns.h +++ b/src/adns.h @@ -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 + * 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 - * Copyright (C) 1999-2000 Tony Finch - * * 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, @@ -47,11 +45,8 @@ * * 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 @@ -65,11 +60,31 @@ #include #include #include +#include #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 % in IPv6 literals */ + adns_qf_addrlit_scope_numeric=0x00004000,/* % 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 |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