X-Git-Url: https://git.distorted.org.uk/~mdw/adns/blobdiff_plain/74c948317bd4785fbfa8b6047b8da2e1705b1863..18276fcd4232e410285dae7965d13d6609af9228:/src/internal.h diff --git a/src/internal.h b/src/internal.h index dadd854..2b604b7 100644 --- a/src/internal.h +++ b/src/internal.h @@ -5,7 +5,12 @@ * - comments regarding library data structures */ /* - * This file is part of adns, which is Copyright (C) 1997-1999 Ian Jackson + * This file is + * Copyright (C) 1997-1999 Ian Jackson + * + * It is part of adns, which is + * Copyright (C) 1997-1999 Ian Jackson + * Copyright (C) 1999 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 @@ -33,10 +38,12 @@ typedef unsigned char byte; #include #include #include +#include #include #include "adns.h" +#include "dlist.h" /* Configuration and constants */ @@ -59,6 +66,12 @@ typedef unsigned char byte; #define MAX_POLLFDS ADNS_POLLFDS_RECOMMENDED typedef enum { + cc_user, + cc_entex, + cc_freq +} consistency_checks; + +typedef enum { rcode_noerror, rcode_formaterror, rcode_servfail, @@ -151,14 +164,14 @@ typedef struct { struct adns__query { adns_state ads; - enum { query_udp, query_tcpwait, query_tcpsent, query_child, query_done } state; + enum { query_tosend, 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 *head, *tail; } allocations; - int interim_allocd; + int interim_allocd, preserved_allocd; void *final_allocspace; - + const typeinfo *typei; byte *query_dgram; int query_dglen; @@ -205,14 +218,14 @@ struct adns__query { /* Possible states: * - * state Queue child id nextudpserver sentudp failedtcp + * state Queue child id nextudpserver udpsent tcpfailed * - * udp NONE null >=0 0 zero zero - * udp timew null >=0 any nonzero zero - * udp NONE null >=0 any nonzero zero + * tosend NONE null >=0 0 zero zero + * tosend timew null >=0 any nonzero zero + * tosend NONE null >=0 any nonzero zero * - * tcpwait timew null >=0 irrelevant zero any - * tcpsent timew null >=0 irrelevant zero any + * tcpwait timew null >=0 irrelevant any any + * tcpsent timew null >=0 irrelevant any any * * child childw set >=0 irrelevant irrelevant irrelevant * child NONE null >=0 irrelevant irrelevant irrelevant @@ -264,9 +277,10 @@ struct adns__state { FILE *diagfile; int configerrno; struct { adns_query head, tail; } timew, childw, output; + adns_query forallnext; int nextid, udpsocket, tcpsocket; vbuf tcpsend, tcprecv; - int nservers, nsortlist, nsearchlist, searchndots, tcpserver; + int nservers, nsortlist, nsearchlist, searchndots, tcpserver, tcprecv_skip; enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate; struct timeval tcptimeout; struct sigaction stdsigpipe; @@ -332,7 +346,8 @@ void adns__sigpipe_unprotect(adns_state); /* If SIGPIPE protection is not disabled, will block all signals except * SIGPIPE, and set SIGPIPE's disposition to SIG_IGN. (And then restore.) * Each call to _protect must be followed by a call to _unprotect before - * any significant amount of code gets to run. + * any significant amount of code gets to run, since the old signal mask + * is stored in the adns structure. */ /* From transmit.c: */ @@ -358,15 +373,18 @@ void adns__query_tcp(adns_query qu, struct timeval now); * * adns__tcp_tryconnect should already have been called - _tcp * will only use an existing connection (if there is one), which it - * may break. If the conn list lost then the caller is responsible for any + * may break. If the conn is lost then the caller is responsible for any * reestablishment and retry. */ -void adns__query_udp(adns_query qu, struct timeval now); -/* Query must be in state udp/NONE; it will be moved to a new state, +void adns__query_send(adns_query qu, struct timeval now); +/* Query must be in state tosend/NONE; it will be moved to a new state, * and no further processing can be done on it for now. * (Resulting state is one of udp/timew, tcpwait/timew (if server not connected), * tcpsent/timew, child/childw or done/output.) + * __query_send may decide to use either UDP or TCP depending whether + * _qf_usevc is set (or has become set) and whether the query is too + * large. */ /* From query.c: */ @@ -389,12 +407,14 @@ adns_status adns__internal_submit(adns_state ads, adns_query *query_r, * 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. + * taken off the global childw queue. + * + * The callback should either call adns__query_done, if it is + * complete, or adns__query_fail, if an error has occurred, in which + * case the other children (if any) will be cancelled. If the parent + * has more unfinished children (or has just submitted more) then the + * callback may choose to wait for them - it must then put the parent + * back on the childw queue. */ void adns__search_next(adns_state ads, adns_query qu, struct timeval now); @@ -408,20 +428,27 @@ void adns__search_next(adns_state ads, adns_query qu, struct timeval now); */ void *adns__alloc_interim(adns_query qu, size_t sz); +void *adns__alloc_preserved(adns_query qu, size_t sz); /* Allocates some memory, and records which query it came from * and how much there was. * - * If an error occurs in the query, all its memory is simply freed. - * - * If the query succeeds, one large buffer will be made which is - * big enough for all these allocations, and then adns__alloc_final - * will get memory from this buffer. + * If an error occurs in the query, all the memory from _interim is + * simply freed. If the query succeeds, one large buffer will be made + * which is big enough for all these allocations, and then + * adns__alloc_final will get memory from this buffer. * * _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. + * The memory from _preserved is is kept and transferred into the + * larger buffer - unless we run out of memory, in which case it too + * is freed. When you use _preserved you have to add code to the + * x_nomem error exit case in adns__makefinal_query to clear out the + * pointers you made to those allocations, because that's when they're + * thrown away; you should also make a note in the declaration of + * those pointer variables, to note that they are _preserved rather + * than _interim. If they're in the answer, note it here: + * answer->cname and answer->owner are _preserved. */ void adns__transfer_interim(adns_query from, adns_query to, void *block, size_t sz); @@ -451,12 +478,12 @@ void *adns__alloc_final(adns_query qu, size_t sz); void adns__makefinal_block(adns_query qu, void **blpp, size_t sz); void adns__makefinal_str(adns_query qu, char **strp); -void adns__reset_cnameonly(adns_query qu); -/* Resets all of the memory management stuff etc. to - * take account of only the CNAME. Used when we find an error somewhere - * and want to just report the error (with perhaps CNAME info), and also - * when we're halfway through RRs in a datagram and discover that we - * need to retry the query. +void adns__reset_preserved(adns_query qu); +/* Resets all of the memory management stuff etc. to take account of + * only the _preserved stuff from _alloc_preserved. Used when we find + * an error somewhere and want to just report the error (with perhaps + * CNAME, owner, etc. info), and also when we're halfway through RRs + * in a datagram and discover that we need to retry the query. */ void adns__query_done(adns_query qu); @@ -465,7 +492,12 @@ void adns__query_fail(adns_query qu, adns_status stat); /* From reply.c: */ void adns__procdgram(adns_state ads, const byte *dgram, int len, - int serv, struct timeval now); + int serv, int viatcp, struct timeval now); +/* This function is allowed to cause new datagrams to be constructed + * and sent, or even new queries to be started. However, + * query-sending functions are not allowed to call any general event + * loop functions in case they accidentally call this. + */ /* From types.c: */ @@ -605,7 +637,10 @@ void adns__tcp_closenext(adns_state ads); void adns__tcp_tryconnect(adns_state ads, struct timeval now); void adns__autosys(adns_state ads, struct timeval now); -/* Make all the system calls we want to if the application wants us to. */ +/* Make all the system calls we want to if the application wants us to. + * Must not be called from within adns internal processing functions, + * lest we end up in recursive descent ! + */ void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io, struct timeval *tv_buf); @@ -618,6 +653,14 @@ void adns__fdevents(adns_state ads, int maxfd, const fd_set *readfds, const fd_set *writefds, const fd_set *exceptfds, struct timeval now, int *r_r); +int adns__internal_check(adns_state ads, + adns_query *query_io, + adns_answer **answer, + void **context_r); + +/* From check.c: */ + +void adns__consistency(adns_state ads, adns_query qu, consistency_checks cc); /* Useful static inline functions: */ @@ -636,6 +679,7 @@ 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'); } +static inline int ctype_822special(int c) { return strchr("()<>@,;:\\\".[]",c) != 0; } static inline int errno_resources(int e) { return e==ENOMEM || e==ENOBUFS; } @@ -645,28 +689,6 @@ static inline int errno_resources(int e) { return e==ENOMEM || e==ENOBUFS; } (( ((sz)+sizeof(union maxalign)-1) / sizeof(union maxalign) ) \ * 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 { \ - 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 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)++]) & 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))