X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=adns.git;a=blobdiff_plain;f=src%2Finternal.h;h=62f3e699570c2b92495d16901315ce55f72ac18d;hp=257953fd1185d66f57e84ba2b45124ed912d401b;hb=4b707d8b1701aec2cec7431d4656f771b96a9f00;hpb=9557e604273fc0ce783fe69da74858b37ae818e5 diff --git a/src/internal.h b/src/internal.h index 257953f..62f3e69 100644 --- a/src/internal.h +++ b/src/internal.h @@ -39,7 +39,8 @@ typedef unsigned char byte; /* Configuration and constants */ #define MAXSERVERS 5 -#define UDPMAXRETRIES /*15*/5 +#define MAXSORTLIST 15 +#define UDPMAXRETRIES 15 #define UDPRETRYMS 2000 #define TCPMS 30000 #define LOCALRESOURCEMS 20 @@ -50,6 +51,8 @@ typedef unsigned char byte; #define DNS_HDRSIZE 12 #define DNS_CLASS_IN 1 +#define DNS_INADDR_ARPA "in-addr", "arpa" + typedef enum { rcode_noerror, rcode_formaterror, @@ -75,19 +78,33 @@ typedef struct { byte *buf; } vbuf; -typedef union { - void *ext; - int dmaddr_index; -} qcontext; +typedef struct { + adns_state ads; + adns_query qu; + int serv; + const byte *dgram; + int dglen, nsstart, nscount, arcount; + struct timeval now; +} parseinfo; typedef struct { adns_rrtype type; - const char *name; + const char *rrtname; + const char *fmtname; int rrsz; - adns_status (*parse)(adns_query qu, int serv, - const byte *dgram, int dglen, int cbyte, int max, - void *store_r); + void (*makefinal)(adns_query qu, void *data); + /* Change memory management of *data. + * Previously, used alloc_interim, now use alloc_final. + */ + + adns_status (*convstring)(vbuf *vb, const void *data); + /* Converts the RR data to a string representation in vbuf. + * vbuf will be appended to (it must have been initialised), + * and will not be null-terminated by convstring. + */ + + adns_status (*parse)(const parseinfo *pai, int cbyte, int max, void *store_r); /* Parse one RR, in dgram of length dglen, starting at cbyte and * extending until at most max. * @@ -95,16 +112,18 @@ typedef struct { * * If there is an overrun which might indicate truncation, it should set * *rdstart to -1; otherwise it may set it to anything else positive. + * + * nsstart is the offset of the authority section. */ - void (*makefinal)(adns_query qu, void *data); - /* Change memory management of *data. - * Previously, used alloc_interim, now use alloc_final. + int (*diff_needswap)(adns_state ads, const void *datap_a, const void *datap_b); + /* Returns !0 if RR a should be strictly after RR b in the sort order, + * 0 otherwise. Must not fail. */ } typeinfo; typedef struct allocnode { - struct allocnode *next; + struct allocnode *next, *back; } allocnode; union maxalign { @@ -116,18 +135,27 @@ union maxalign { union maxalign *up; } data; +typedef struct { + void *ext; + void (*callback)(adns_query parent, adns_query child); + union { + adns_rr_addr ptr_parent_addr; + adns_rr_hostaddr *hostaddr; + } info; +} qcontext; + struct adns__query { adns_state ads; enum { query_udp, query_tcpwait, query_tcpsent, query_child, query_done } state; adns_query back, next, parent; struct { adns_query head, tail; } children; struct { adns_query back, next; } siblings; - struct allocnode *allocations; + struct { allocnode *head, *tail; } allocations; int interim_allocd; void *final_allocspace; const typeinfo *typei; - char *query_dgram; + byte *query_dgram; int query_dglen; vbuf vb; @@ -153,7 +181,8 @@ struct adns__query { int udpnextserver; unsigned long udpsent, tcpfailed; /* bitmap indexed by server */ struct timeval timeout; - qcontext context; + + qcontext ctx; /* Possible states: * @@ -211,15 +240,19 @@ struct adns__query { struct adns__state { adns_initflags iflags; FILE *diagfile; + int configerrno; struct { adns_query head, tail; } timew, childw, output; int nextid, udpsocket, tcpsocket; vbuf tcpsend, tcprecv; - int nservers, tcpserver; + int nservers, nsortlist, tcpserver; enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate; struct timeval tcptimeout; struct server { struct in_addr addr; } servers[MAXSERVERS]; + struct sortlist { + struct in_addr base, mask; + } sortlist[MAXSORTLIST]; }; /* From setup.c: */ @@ -246,8 +279,8 @@ void adns__vbuf_appendq(vbuf *vb, const byte *data, int len); void adns__vbuf_init(vbuf *vb); void adns__vbuf_free(vbuf *vb); -const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, vbuf *vb, - int flags, const byte *dgram, int dglen, int cbyte); +const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, + vbuf *vb, const byte *dgram, int dglen, int cbyte); /* Unpicks a domain in a datagram and returns a string suitable for * printing it as. Never fails - if an error occurs, it will * return some kind of string describing the error. @@ -259,6 +292,15 @@ const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, vbuf *vb, * vb before using the return value. */ +void adns__isort(void *array, int nobjs, int sz, void *tempbuf, + int (*needswap)(void *context, const void *a, const void *b), + void *context); +/* Does an insertion sort of array which must contain nobjs objects + * each sz bytes long. tempbuf must point to a buffer at least + * sz bytes long. needswap should return !0 if a>b (strictly, ie + * wrong order) 0 if a<=b (ie, order is fine). + */ + /* From transmit.c: */ adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r, @@ -266,6 +308,13 @@ adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r, const typeinfo *typei, adns_queryflags flags); /* Assembles a query packet in vb, and returns id at *id_r. */ +adns_status adns__mkquery_frdgram(adns_state ads, vbuf *vb, int *id_r, + const byte *qd_dgram, int qd_dglen, int qd_begin, + adns_rrtype type, adns_queryflags flags); +/* Same as adns__mkquery, but takes the owner domain from an existing datagram. + * That domain must be correct and untruncated. + */ + void adns__query_tcp(adns_query qu, struct timeval now); /* Query must be in state tcpwait/timew; it will be moved to a new state * if possible and no further processing can be done on it for now. @@ -302,7 +351,7 @@ int adns__internal_submit(adns_state ads, adns_query *query_r, * 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. + * *ctx is copied byte-for-byte into the query. */ void *adns__alloc_interim(adns_query qu, size_t sz); @@ -315,11 +364,21 @@ void *adns__alloc_interim(adns_query qu, size_t sz); * big enough for all these allocations, and then adns__alloc_final * will get memory from this buffer. * - * _alloc_interim can fail, in which case it will fail the query too, - * so nothing more need be done with it. + * _alloc_interim can fail (and return 0). + * The caller must ensure that the query is failed. + * + * adns__alloc_interim_{only,fail}(qu,0) will not return 0, + * but it will not necessarily return a distinct pointer each time. + */ + +void adns__transfer_interim(adns_query from, adns_query to, void *block, size_t sz); +/* 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 + * rather than the `from' query. * - * adns__alloc_interim(qu,0) will not return 0, but it will not - * necessarily return a distinct pointer each time. + * It is legal to call adns__transfer_interim with a null pointer; this + * has no effect. */ void *adns__alloc_mine(adns_query qu, size_t sz); @@ -402,8 +461,12 @@ adns_status adns__findlabel_next(findlabel_state *fls, int *lablen_r, int *labst * Do not then call findlabel_next again. */ +typedef enum { + pdf_quoteok= 0x001 +} parsedomain_flags; + adns_status adns__parse_domain(adns_state ads, int serv, adns_query qu, - vbuf *vb, int flags, + vbuf *vb, parsedomain_flags flags, const byte *dgram, int dglen, int *cbyte_io, int max); /* vb must already have been initialised; it will be reset if necessary. * If there is truncation, vb->used will be set to 0; otherwise @@ -417,29 +480,48 @@ adns_status adns__findrr(adns_query qu, int serv, const byte *dgram, int dglen, int *cbyte_io, int *type_r, int *class_r, int *rdlen_r, int *rdstart_r, int *ownermatchedquery_r); - /* Finds the extent and some of the contents of an RR in a datagram - * and does some checks. The datagram is *dgram, length dglen, and - * the RR starts at *cbyte_io (which is updated afterwards to point - * to the end of the RR). - * - * The type, class and RRdata length and start are returned iff - * the corresponding pointer variables are not null. type_r and - * class_r may not be null. - * - * If ownermatchedquery_r != 0 then the owner domain of this - * RR will be compared with that in the query (or, if the query - * has gone to a CNAME lookup, with the canonical name). - * In this case, *ownermatchedquery_r will be set to 0 or 1. - * The query datagram (or CNAME datagram) MUST be valid and not truncated. - * - * If there is truncation then *type_r will be set to -1 and - * *cbyte_io, *class_r, *rdlen_r, *rdstart_r and *eo_matched_r will be - * undefined. - * - * qu must obviously be non-null. - * - * If an error is returned then *type_r will be undefined too. - */ +/* Finds the extent and some of the contents of an RR in a datagram + * and does some checks. The datagram is *dgram, length dglen, and + * the RR starts at *cbyte_io (which is updated afterwards to point + * to the end of the RR). + * + * The type, class and RRdata length and start are returned iff + * the corresponding pointer variables are not null. type_r and + * class_r may not be null. + * + * If ownermatchedquery_r != 0 then the owner domain of this + * RR will be compared with that in the query (or, if the query + * has gone to a CNAME lookup, with the canonical name). + * In this case, *ownermatchedquery_r will be set to 0 or 1. + * The query datagram (or CNAME datagram) MUST be valid and not truncated. + * + * If there is truncation then *type_r will be set to -1 and + * *cbyte_io, *class_r, *rdlen_r, *rdstart_r and *eo_matched_r will be + * undefined. + * + * qu must obviously be non-null. + * + * If an error is returned then *type_r will be undefined too. + */ + +adns_status adns__findrr_anychk(adns_query qu, int serv, + const byte *dgram, int dglen, int *cbyte_io, + int *type_r, int *class_r, int *rdlen_r, int *rdstart_r, + const byte *eo_dgram, int eo_dglen, int eo_cbyte, + int *eo_matched_r); +/* Like adns__findrr_checked, except that the datagram and + * owner to compare with can be specified explicitly. + * + * If the caller thinks they know what the owner of the RR ought to + * be they can pass in details in eo_*: this is another (or perhaps + * the same datagram), and a pointer to where the putative owner + * starts in that datagram. In this case *eo_matched_r will be set + * to 1 if the datagram matched or 0 if it did not. Either + * both eo_dgram and eo_matched_r must both be non-null, or they + * must both be null (in which case eo_dglen and eo_cbyte will be ignored). + * The eo datagram and contained owner domain MUST be valid and + * untruncated. + */ int vbuf__append_quoted1035(vbuf *vb, const byte *buf, int len); @@ -479,24 +561,24 @@ static inline int ctype_alpha(int c) { #define LIST_UNLINK_PART(list,node,part) \ do { \ - if ((node)->back) (node)->back->part next= (node)->part next; \ - else (list).head= (node)->part next; \ - if ((node)->next) (node)->next->part back= (node)->part back; \ - else (list).tail= (node)->part back; \ + if ((node)->part back) (node)->part back->part next= (node)->part next; \ + else (list).head= (node)->part next; \ + if ((node)->part next) (node)->part next->part back= (node)->part back; \ + else (list).tail= (node)->part back; \ } while(0) #define LIST_LINK_TAIL_PART(list,node,part) \ do { \ - (node)->part back= 0; \ - (node)->part next= (list).tail; \ - if ((list).tail) (list).tail->part back= (node); else (list).part head= (node); \ + (node)->part next= 0; \ + (node)->part back= (list).tail; \ + if ((list).tail) (list).tail->part next= (node); else (list).head= (node); \ (list).tail= (node); \ } while(0) #define LIST_UNLINK(list,node) LIST_UNLINK_PART(list,node,) #define LIST_LINK_TAIL(list,node) LIST_LINK_TAIL_PART(list,node,) -#define GETIL_B(cb) (dgram[(cb)++]) +#define GETIL_B(cb) (((dgram)[(cb)++]) & 0x0ff) #define GET_B(cb,tv) ((tv)= GETIL_B((cb))) #define GET_W(cb,tv) ((tv)=0, (tv)|=(GETIL_B((cb))<<8), (tv)|=GETIL_B(cb), (tv))