X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=adns.git;a=blobdiff_plain;f=src%2Finternal.h;h=e07978b701d7cf6dc5bc124bb5ed843791bfd444;hp=6c6a77eccd196c5477039d1b63b758f1e96ee99f;hb=1bc731c6994dda2c1ab12fb2d8261246bcbc139c;hpb=b0e8338ab13a968e398e8db4e81d5022af2059a2 diff --git a/src/internal.h b/src/internal.h index 6c6a77e..e07978b 100644 --- a/src/internal.h +++ b/src/internal.h @@ -69,6 +69,7 @@ typedef unsigned char byte; #define DNS_CLASS_IN 1 #define DNS_INADDR_ARPA "in-addr", "arpa" +#define DNS_IP6_ARPA "ip6", "arpa" #define MAX_POLLFDS ADNS_POLLFDS_RECOMMENDED @@ -108,6 +109,11 @@ typedef enum { rcode_refused } dns_rcode; +enum { + adns__qf_addr_answer= 0x01000000,/* addr query received an answer */ + adns__qf_addr_cname = 0x02000000 /* addr subquery performed on cname */ +}; + /* Shared data structures */ typedef struct { @@ -131,8 +137,14 @@ union gen_addr { struct af_addr { int af; union gen_addr addr; }; +#define NREVDOMAINS 2 /* keep in sync with addrfam! */ +struct revparse_state { + unsigned map; /* which domains are still live */ + byte ipv[NREVDOMAINS][32]; /* address components so far */ +}; + union checklabel_state { - struct { byte ipv[4]; } ptr; + struct revparse_state ptr; }; typedef struct { @@ -141,8 +153,12 @@ typedef struct { union { struct { + adns_rrtype rev_rrtype; struct af_addr addr; } ptr; + struct { + unsigned want, have; + } addr; } tinfo; /* type-specific state for the query itself: zero-init if you * don't know better. */ @@ -209,6 +225,12 @@ typedef struct typeinfo { /* Return the output resource-record element size; if this is null, then * the rrsz member can be used. */ + + void (*query_send)(adns_query qu, struct timeval now); + /* Send the query to nameservers, and hook it into the appropriate queue. + * Normal behaviour is to call adns__query_send, but this can be overridden + * for special effects. + */ } typeinfo; adns_status adns__ckl_hostname(adns_state ads, adns_queryflags flags, @@ -221,6 +243,7 @@ adns_status adns__ckl_hostname(adns_state ads, adns_queryflags flags, typedef struct allocnode { struct allocnode *next, *back; + size_t sz; } allocnode; union maxalign { @@ -304,6 +327,10 @@ struct adns__query { * Queries in state tcpw/tcpw have been sent (or are in the to-send buffer) * iff the tcp connection is in state server_ok. * + * Internal queries (from adns__submit_internal) end up on intdone + * instead of output, and the callbacks are made on the way out of + * adns, to avoid reentrancy hazards. + * * +------------------------+ * START -----> | tosend/NONE | * +------------------------+ @@ -342,14 +369,18 @@ struct adns__query { struct query_queue { adns_query head, tail; }; +#define MAXUDP 2 + struct adns__state { adns_initflags iflags; adns_logcallbackfn *logfn; void *logfndata; int configerrno; - struct query_queue udpw, tcpw, childw, output; + struct query_queue udpw, tcpw, childw, output, intdone; adns_query forallnext; - int nextid, udpsocket, tcpsocket; + int nextid, tcpsocket; + struct udpsocket { int af; int fd; } udpsocket[MAXUDP]; + int nudp; vbuf tcpsend, tcprecv; int nservers, nsortlist, nsearchlist, searchndots, tcpserver, tcprecv_skip; enum adns__tcpstate { @@ -438,6 +469,40 @@ char *adns__sockaddr_ntoa(const struct sockaddr *sa, char *buf); * ADNS_ADDR2TEXT_BUFLEN bytes long (unchecked). Return buf; can't fail. */ +extern int adns__make_reverse_domain(const struct sockaddr *sa, + const char *zone, + char **buf_io, size_t bufsz, + char **buf_free_r); +/* Construct a reverse domain string, given a socket address and a parent + * zone. If zone is null, then use the standard reverse-lookup zone for the + * address family. If the length of the resulting string is no larger than + * bufsz, then the result is stored starting at *buf_io; otherwise a new + * buffer is allocated is used, and a pointer to it is stored in both *buf_io + * and *buf_free_r (the latter of which should be null on entry). If + * something goes wrong, then an errno value is returned: ENOSYS if the + * address family of sa isn't recognized, or ENOMEM if the attempt to + * allocate an output buffer failed. + */ + +extern int adns__revparse_label(struct revparse_state *rps, int labnum, + const char *label, int lablen); +/* Parse a label in a reverse-domain name, given its index labnum (starting + * from zero), a pointer to its contents (which need not be null-terminated), + * and its length. The state in *rps is initialized implicitly when labnum + * is zero. + * + * Returns zero if the parse was successful, nonzero if the domain name is + * definitely invalid and the parse must be abandoned. + */ + +extern int adns__revparse_done(struct revparse_state *rps, int nlabels, + adns_rrtype *rrtype_r, struct af_addr *addr_r); +/* Finishes parsing a reverse-domain name, given the total number of labels + * in the name. On success, fills in the address in *addr_r, and the forward + * query type in *rrtype_r (because that turns out to be useful). Returns + * nonzero if the parse must be abandoned. + */ + /* From setup.c: */ int adns__setnonblock(adns_state ads, int fd); /* => errno value */ @@ -526,6 +591,15 @@ void adns__querysend_tcp(adns_query qu, struct timeval now); * might be broken, but no reconnect will be attempted. */ +struct udpsocket *adns__udpsocket_by_af(adns_state ads, int af); +/* Find the UDP socket structure in ads which has the given address family. + * Return null if there isn't one. + * + * This is used during initialization, so ads is only partially filled in. + * The requirements are that nudp is set, and that udpsocket[i].af are + * defined for 0<=icname and answer->owner are _preserved. */ -void adns__transfer_interim(adns_query from, adns_query to, - void *block, size_t sz); +void adns__transfer_interim(adns_query from, adns_query to, void *block); /* Transfers an interim allocation from one query to another, so that * the `to' query will have room for the data when we get to makefinal * and so that the free will happen when the `to' query is freed @@ -617,6 +691,10 @@ void adns__transfer_interim(adns_query from, adns_query to, * TTLs get inherited by their parents. */ +void adns__free_interim(adns_query qu, void *p); +/* Forget about a block allocated by adns__alloc_interim. + */ + void *adns__alloc_mine(adns_query qu, size_t sz); /* Like _interim, but does not record the length for later * copying into the answer. This just ensures that the memory @@ -638,8 +716,18 @@ void adns__reset_preserved(adns_query qu); * in a datagram and discover that we need to retry the query. */ +void adns__cancel(adns_query qu); void adns__query_done(adns_query qu); void adns__query_fail(adns_query qu, adns_status stat); +void adns__cancel_children(adns_query qu); + +void adns__returning(adns_state ads, adns_query qu); +/* Must be called before returning from adns any time that we have + * progressed (including made, finished or destroyed) queries. + * + * Might reenter adns via internal query callbacks, so + * external-faciing functions which call adns__returning should + * normally be avoided in internal code. */ /* From reply.c: */ @@ -805,6 +893,7 @@ void adns__autosys(adns_state ads, struct timeval now); void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io, struct timeval *tv_buf); +/* Call with care - might reentrantly cause queries to be completed! */ int adns__pollfds(adns_state ads, struct pollfd pollfds_buf[MAX_POLLFDS]); void adns__fdevents(adns_state ads,