X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fsetup.c;h=6ef2d120eeed53d85b4aab2718fdb16be639b18c;hb=c8c7c813c5b3685f31eab503197ffa86203d54c1;hp=137d22b090a616f0b11785fa667665ca612930ff;hpb=a719a4bedec2bc512b7f95f7446e02f6662ebbc7;p=adns.git diff --git a/src/setup.c b/src/setup.c index 137d22b..6ef2d12 100644 --- a/src/setup.c +++ b/src/setup.c @@ -23,11 +23,13 @@ #include #include -#include +#include #include #include #include +#include +#include #include #include "internal.h" @@ -74,6 +76,23 @@ static void configparseerr(adns_state ads, const char *fn, int lno, fputc('\n',ads->diagfile); } +static int nextword(const char **bufp_io, const char **word_r, int *l_r) { + const char *p, *q; + + p= *bufp_io; + while (ctype_whitespace(*p)) p++; + if (!*p) return 0; + + q= p; + while (*q && !ctype_whitespace(*q)) q++; + + *l_r= q-p; + *word_r= p; + *bufp_io= q; + + return 1; +} + static void ccf_nameserver(adns_state ads, const char *fn, int lno, const char *buf) { struct in_addr ia; @@ -86,42 +105,56 @@ static void ccf_nameserver(adns_state ads, const char *fn, int lno, const char * } static void ccf_search(adns_state ads, const char *fn, int lno, const char *buf) { + const char *bufp, *word; + char *newchars, **newptrs, **pp; + int count, tl, l; + if (!buf) return; - adns__diag(ads,-1,0,"warning - `search' ignored fixme"); + + bufp= buf; + count= 0; + tl= 0; + while (nextword(&bufp,&word,&l)) { count++; tl += l+1; } + + newptrs= malloc(sizeof(char*)*count); if (!newptrs) { saveerr(ads,errno); return; } + newchars= malloc(tl); if (!newchars) { saveerr(ads,errno); free(newptrs); return; } + + bufp= buf; + pp= newptrs; + while (nextword(&bufp,&word,&l)) { + *pp++= newchars; + memcpy(newchars,word,l); + newchars += l; + *newchars++ = 0; + } + + free(ads->searchlist); + ads->nsearchlist= count; + ads->searchlist= newptrs; } -static void ccf_sortlist(adns_state ads, const char *fn, int lno, const char *bufp) { - const char *p, *q; +static void ccf_sortlist(adns_state ads, const char *fn, int lno, const char *buf) { + const char *word; char tbuf[200], *slash, *ep; struct in_addr base, mask; int l; unsigned long initial, baselocal; + if (!buf) return; + ads->nsortlist= 0; - if (!bufp) return; - - for (;;) { - while (ctype_whitespace(*bufp)) bufp++; - if (!*bufp) return; - - q= bufp; - while (*q && !ctype_whitespace(*q)) q++; - - p= bufp; - l= q-p; - bufp= q; - + while (nextword(&buf,&word,&l)) { if (ads->nsortlist >= MAXSORTLIST) { - adns__diag(ads,-1,0,"too many sortlist entries, ignoring %.*s onwards",l,p); + adns__diag(ads,-1,0,"too many sortlist entries, ignoring %.*s onwards",l,word); return; } if (l >= sizeof(tbuf)) { - configparseerr(ads,fn,lno,"sortlist entry `%.*s' too long",l,p); + configparseerr(ads,fn,lno,"sortlist entry `%.*s' too long",l,word); continue; } - memcpy(tbuf,p,l); + memcpy(tbuf,word,l); tbuf[l]= 0; slash= strchr(tbuf,'/'); if (slash) *slash++= 0; @@ -172,8 +205,44 @@ static void ccf_sortlist(adns_state ads, const char *fn, int lno, const char *bu } static void ccf_options(adns_state ads, const char *fn, int lno, const char *buf) { + const char *word; + char *ep; + unsigned long v; + int l; + if (!buf) return; - adns__diag(ads,-1,0,"warning - `options' ignored fixme"); + + while (nextword(&buf,&word,&l)) { + if (l==5 && !memcmp(word,"debug",5)) { + ads->iflags |= adns_if_debug; + continue; + } + if (l>=6 && !memcmp(word,"ndots:",6)) { + v= strtoul(word+6,&ep,10); + if (l==6 || ep != word+l || v > INT_MAX) { + configparseerr(ads,fn,lno,"option `%.*s' malformed or has bad value",l,word); + continue; + } + ads->searchndots= v; + continue; + } + if (l>=12 && !memcmp(word,"adns_checkc:",12)) { + if (!strcmp(word+12,"none")) { + ads->iflags &= ~adns_if_checkc_freq; + ads->iflags |= adns_if_checkc_entex; + } else if (!strcmp(word+12,"entex")) { + ads->iflags &= ~adns_if_checkc_freq; + ads->iflags |= adns_if_checkc_entex; + } else if (!strcmp(word+12,"freq")) { + ads->iflags |= adns_if_checkc_freq; + } else { + configparseerr(ads,fn,lno, "option adns_checkc has bad value `%s' " + "(must be none, entex or freq", word+12); + } + continue; + } + adns__diag(ads,-1,0,"%s:%d: unknown option `%.*s'", fn,lno, l,word); + } } static void ccf_clearnss(adns_state ads, const char *fn, int lno, const char *buf) { @@ -386,16 +455,20 @@ static int init_begin(adns_state *ads_r, adns_initflags flags, FILE *diagfile) { ads->iflags= flags; ads->diagfile= diagfile; + ads->configerrno= 0; LIST_INIT(ads->timew); LIST_INIT(ads->childw); LIST_INIT(ads->output); + ads->forallnext= 0; ads->nextid= 0x311f; ads->udpsocket= ads->tcpsocket= -1; adns__vbuf_init(&ads->tcpsend); adns__vbuf_init(&ads->tcprecv); - ads->nservers= ads->nsortlist= ads->tcpserver= 0; + ads->nservers= ads->nsortlist= ads->nsearchlist= ads->tcpserver= 0; + ads->searchndots= 1; ads->tcpstate= server_disconnected; timerclear(&ads->tcptimeout); + ads->searchlist= 0; *ads_r= ads; return 0; @@ -429,6 +502,14 @@ static int init_finish(adns_state ads) { return r; } +static void init_abort(adns_state ads) { + if (ads->nsearchlist) { + free(ads->searchlist[0]); + free(ads->searchlist); + } + free(ads); +} + int adns_init(adns_state *ads_r, adns_initflags flags, FILE *diagfile) { adns_state ads; const char *res_options, *adns_res_options; @@ -455,9 +536,16 @@ int adns_init(adns_state *ads_r, adns_initflags flags, FILE *diagfile) { ccf_search(ads,"LOCALDOMAIN",-1,instrum_getenv(ads,"LOCALDOMAIN")); ccf_search(ads,"ADNS_LOCALDOMAIN",-1,instrum_getenv(ads,"ADNS_LOCALDOMAIN")); + if (ads->configerrno && ads->configerrno != EINVAL) { + r= ads->configerrno; + init_abort(ads); + return r; + } + r= init_finish(ads); if (r) return r; + adns__consistency(ads,0,cc_entex); *ads_r= ads; return 0; } @@ -472,16 +560,19 @@ int adns_init_strcfg(adns_state *ads_r, adns_initflags flags, readconfigtext(ads,configtext,""); if (ads->configerrno) { r= ads->configerrno; - free(ads); + init_abort(ads); return r; } r= init_finish(ads); if (r) return r; + adns__consistency(ads,0,cc_entex); *ads_r= ads; return 0; } + void adns_finish(adns_state ads) { + adns__consistency(ads,0,cc_entex); for (;;) { if (ads->timew.head) adns_cancel(ads->timew.head); else if (ads->childw.head) adns_cancel(ads->childw.head); @@ -494,3 +585,44 @@ void adns_finish(adns_state ads) { adns__vbuf_free(&ads->tcprecv); free(ads); } + +void adns_forallqueries_begin(adns_state ads) { + adns__consistency(ads,0,cc_entex); + ads->forallnext= + ads->timew.head ? ads->timew.head : + ads->childw.head ? ads->childw.head : + ads->output.head; +} + +adns_query adns_forallqueries_next(adns_state ads, void **context_r) { + adns_query qu, nqu; + + adns__consistency(ads,0,cc_entex); + nqu= ads->forallnext; + for (;;) { + qu= nqu; + if (!qu) return 0; + if (qu->next) { + nqu= qu->next; + } else if (qu == ads->timew.tail) { + if (ads->childw.head) { + nqu= ads->childw.head; + } else { + nqu= ads->output.head; + } + } else if (qu == ads->childw.tail) { + nqu= ads->output.head; + } else { + nqu= 0; + } + if (!qu->parent) break; + } + ads->forallnext= nqu; + if (context_r) *context_r= qu->ctx.ext; + return qu; +} + +void adns__checkqueues(adns_state ads) { + adns_forallqueries_begin(ads); + while (adns_forallqueries_next(ads,0)); +}