X-Git-Url: https://git.distorted.org.uk/~mdw/adns/blobdiff_plain/ac868fa87da18cdebb86103b35ce250bd171f700..9da4a044c4d2e0a960cf8f33c62774db02f4402d:/src/internal.h?ds=sidebyside diff --git a/src/internal.h b/src/internal.h index 9a5f23d..b813215 100644 --- a/src/internal.h +++ b/src/internal.h @@ -51,6 +51,7 @@ typedef unsigned char byte; #define DNS_MAXUDP 512 #define DNS_MAXDOMAIN 255 #define DNS_HDRSIZE 12 +#define DNS_IDOFFSET 0 #define DNS_CLASS_IN 1 #define DNS_INADDR_ARPA "in-addr", "arpa" @@ -173,11 +174,24 @@ struct adns__query { * we found a cname (this corresponds to cname_dgram in the query * structure). type is set from the word go. nrrs and rrs * are set together, when we find how many rrs there are. + * owner is set during querying unless we're doing searchlist, + * in which case it is set only when we find an answer. */ byte *cname_dgram; int cname_dglen, cname_begin; /* If non-0, has been allocated using . */ + + vbuf search_vb; + int search_origlen, search_pos, search_doneabs; + /* Used by the searching algorithm. The query domain in textual form + * is copied into the vbuf, and _origlen set to its length. Then + * we walk the searchlist, if we want to. _pos says where we are + * (next entry to try), and _doneabs says whether we've done the + * absolute query yet (0=not yet, 1=done, -1=must do straight away, + * but not done yet). If flags doesn't have adns_qf_search then + * the vbuf is initialised but empty and everything else is zero. + */ int id, flags, udpretries; int udpnextserver; @@ -199,8 +213,11 @@ struct adns__query { * tcpsent timew null >=0 irrelevant zero any * * child childw set >=0 irrelevant irrelevant irrelevant + * child NONE null >=0 irrelevant irrelevant irrelevant * done output null -1 irrelevant irrelevant irrelevant * + * Queries are only not on a queue when they are actually being processed. + * * +------------------------+ * START -----> | udp/NONE | * +------------------------+ @@ -247,7 +264,7 @@ struct adns__state { struct { adns_query head, tail; } timew, childw, output; int nextid, udpsocket, tcpsocket; vbuf tcpsend, tcprecv; - int nservers, nsortlist, tcpserver; + int nservers, nsortlist, nsearchlist, searchndots, tcpserver; enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate; struct timeval tcptimeout; struct sigaction stdsigpipe; @@ -258,6 +275,7 @@ struct adns__state { struct sortlist { struct in_addr base, mask; } sortlist[MAXSORTLIST]; + char **searchlist; }; /* From setup.c: */ @@ -319,7 +337,8 @@ void adns__sigpipe_unprotect(adns_state); adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r, const char *owner, int ol, const typeinfo *typei, adns_queryflags flags); -/* Assembles a query packet in vb, and returns id at *id_r. */ +/* Assembles a query packet in vb. A new id is allocated and returned. + */ adns_status adns__mkquery_frdgram(adns_state ads, vbuf *vb, int *id_r, const byte *qd_dgram, int qd_dglen, int qd_begin, @@ -349,10 +368,10 @@ void adns__query_udp(adns_query qu, struct timeval now); /* From query.c: */ -int adns__internal_submit(adns_state ads, adns_query *query_r, - const typeinfo *typei, vbuf *qumsg_vb, int id, - adns_queryflags flags, struct timeval now, - adns_status failstat, const qcontext *ctx); +adns_status adns__internal_submit(adns_state ads, adns_query *query_r, + const typeinfo *typei, vbuf *qumsg_vb, int id, + adns_queryflags flags, struct timeval now, + const qcontext *ctx); /* Submits a query (for internal use, called during external submits). * * The new query is returned in *query_r, or we return adns_s_nomemory. @@ -361,10 +380,28 @@ int adns__internal_submit(adns_state ads, adns_query *query_r, * the memory for it is _taken over_ by this routine whether it * succeeds or fails (if it succeeds, the vbuf is reused for qu->vb). * - * If failstat is nonzero then if we are successful in creating the query - * it is immediately failed with code failstat (but _submit still succeds). - * * *ctx is copied byte-for-byte into the query. + * + * When the child query is done, ctx->callback will be called. The + * child will already have been taken off both the global list of + * queries in ads and the list of children in the parent. The child + * will be freed when the callback returns. The parent will have been + * taken off the global childw queue iff this is the last child for + * that parent. If there is no error detected in the callback, then + * it should call adns__query_done if and only if there are no more + * children (by checking parent->children.head). If an error is + * detected in the callback it should call adns__query_fail and any + * remaining children will automatically be cancelled. + */ + +void adns__search_next(adns_state ads, adns_query qu, struct timeval now); +/* Walks down the searchlist for a query with adns_qf_search. + * The query should have just had a negative response, or not had + * any queries sent yet, and should not be on any queue. + * The query_dgram if any will be freed and forgotten and a new + * one constructed from the search_* members of the query. + * + * Cannot fail (in case of error, calls adns__query_fail). */ void *adns__alloc_interim(adns_query qu, size_t sz); @@ -581,7 +618,7 @@ static inline void timevaladd(struct timeval *tv_io, long ms) { static inline int ctype_whitespace(int c) { return c==' ' || c=='\n' || c=='\t'; } static inline int ctype_digit(int c) { return c>='0' && c<='9'; } static inline int ctype_alpha(int c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' || c <= 'Z'); + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } /* Useful macros */ @@ -591,6 +628,7 @@ static inline int ctype_alpha(int c) { * sizeof(union maxalign) ) #define LIST_INIT(list) ((list).head= (list).tail= 0) +#define LINK_INIT(link) ((link).next= (link).back= 0) #define LIST_UNLINK_PART(list,node,part) \ do { \