3 * - diagnostic functions
7 * This file is part of adns, which is Copyright (C) 1997-1999 Ian Jackson
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include <arpa/inet.h>
31 /* Core diagnostic functions */
33 void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
34 int serv, adns_query qu, const char *fmt, va_list al) {
35 const char *bef, *aft;
39 (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))))
42 fprintf(ads->diagfile,"adns%s: ",pfx);
44 vfprintf(ads->diagfile,fmt,al);
49 if (qu && qu->query_dgram) {
51 fprintf(ads->diagfile,"%sQNAME=%s, QTYPE=%s",
53 adns__diag_domain(qu->ads,-1,0, &vb,
54 qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
55 qu->typei ? qu->typei->rrtname : "<unknown>");
56 if (qu->typei && qu->typei->fmtname)
57 fprintf(ads->diagfile,"(%s)",qu->typei->fmtname);
62 fprintf(ads->diagfile,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
66 fputs(aft,ads->diagfile);
69 void adns__debug(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
73 adns__vdiag(ads," debug",0,serv,qu,fmt,al);
77 void adns__warn(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
81 adns__vdiag(ads," warning",adns_if_noerrprint|adns_if_noserverwarn,serv,qu,fmt,al);
85 void adns__diag(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
89 adns__vdiag(ads,"",adns_if_noerrprint,serv,qu,fmt,al);
95 void adns__vbuf_init(vbuf *vb) {
96 vb->used= vb->avail= 0; vb->buf= 0;
99 int adns__vbuf_ensure(vbuf *vb, int want) {
102 if (vb->avail >= want) return 1;
103 nb= realloc(vb->buf,want); if (!nb) return 0;
109 void adns__vbuf_appendq(vbuf *vb, const byte *data, int len) {
110 memcpy(vb->buf+vb->used,data,len);
114 int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
118 newlen= vb->used+len;
119 if (vb->avail < newlen) {
120 if (newlen<20) newlen= 20;
122 nb= realloc(vb->buf,newlen);
123 if (!nb) { newlen= vb->used+len; nb= realloc(vb->buf,newlen); }
128 adns__vbuf_appendq(vb,data,len);
132 int adns__vbuf_appendstr(vbuf *vb, const char *data) {
135 return adns__vbuf_append(vb,data,l);
138 void adns__vbuf_free(vbuf *vb) {
143 /* Additional diagnostic functions */
145 const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
146 vbuf *vb, const byte *dgram, int dglen, int cbyte) {
149 st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen);
150 if (st == adns_s_nomemory) {
151 return "<cannot report domain... out of memory>";
155 if (!(adns__vbuf_appendstr(vb,"<bad format... ") &&
156 adns__vbuf_appendstr(vb,adns_strerror(st)) &&
157 adns__vbuf_appendstr(vb,">") &&
158 adns__vbuf_append(vb,"",1))) {
159 return "<cannot report bad format... out of memory>";
163 adns__vbuf_appendstr(vb,"<truncated ...>");
164 adns__vbuf_append(vb,"",1);
169 adns_status adns_rr_info(adns_rrtype type,
170 const char **rrtname_r, const char **fmtname_r,
172 const void *datap, char **data_r) {
173 const typeinfo *typei;
177 typei= adns__findtype(type);
178 if (!typei) return adns_s_unknownrrtype;
180 if (rrtname_r) *rrtname_r= typei->rrtname;
181 if (fmtname_r) *fmtname_r= typei->fmtname;
182 if (len_r) *len_r= typei->rrsz;
184 if (!datap) return adns_s_ok;
186 adns__vbuf_init(&vb);
187 st= typei->convstring(&vb,datap);
188 if (st) goto x_freevb;
189 if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nomemory; goto x_freevb; }
190 assert(strlen(vb.buf) == vb.used-1);
191 *data_r= realloc(vb.buf,vb.used);
192 if (!*data_r) *data_r= vb.buf;
196 adns__vbuf_free(&vb);
200 #define SINFO(n,s) { adns_s_##n, s }
202 static const struct sinfo {
208 SINFO( nomemory, "Out of memory" ),
209 SINFO( unknownrrtype, "Query not implemented in DNS library" ),
211 SINFO( timeout, "DNS query timed out" ),
212 SINFO( allservfail, "All nameservers failed" ),
213 SINFO( norecurse, "Recursion denied by nameserver" ),
214 SINFO( invalidresponse, "Nameserver sent bad response" ),
215 SINFO( unknownformat, "Nameserver used unknown format" ),
217 SINFO( rcodeservfail, "Nameserver reports failure" ),
218 SINFO( rcodeformaterror, "Query not understood by nameserver" ),
219 SINFO( rcodenotimplemented, "Query not implemented by nameserver" ),
220 SINFO( rcoderefused, "Query refused by nameserver" ),
221 SINFO( rcodeunknown, "Nameserver sent unknown response code" ),
223 SINFO( inconsistent, "Inconsistent resource records in DNS" ),
224 SINFO( prohibitedcname, "DNS data refers to an alias" ),
225 SINFO( answerdomaininvalid, "Found syntactically invalid domain name" ),
226 SINFO( answerdomaintoolong, "Found overly-long domain name" ),
227 SINFO( invaliddata, "Found invalid DNS data" ),
229 SINFO( querydomainwrong, "Domain invalid for particular DNS query type" ),
230 SINFO( querydomaininvalid, "Domain name is syntactically invalid" ),
231 SINFO( querydomaintoolong, "Domain name is too long" ),
233 SINFO( nxdomain, "No such domain" ),
234 SINFO( nodata, "No such data" ),
237 static int si_compar(const void *key, const void *elem) {
238 const adns_status *st= key;
239 const struct sinfo *si= elem;
241 return *st < si->st ? -1 : *st > si->st ? 1 : 0;
244 const char *adns_strerror(adns_status st) {
245 static char buf[100];
247 const struct sinfo *si;
249 si= bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*si),sizeof(*si),si_compar);
250 if (si) return si->string;
252 snprintf(buf,sizeof(buf),"code %d",st);
256 void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
257 int (*needswap)(void *context, const void *a, const void *b),
262 for (i=0; i<nobjs; i++) {
264 place>0 && needswap(context, data + (place-1)*sz, data + i*sz);
267 memcpy(tempbuf, data + i*sz, sz);
268 memmove(data + (place+1)*sz, data + place*sz, (i-place)*sz);
269 memcpy(data + place*sz, tempbuf, sz);
274 /* SIGPIPE protection. */
276 void adns__sigpipe_protect(adns_state ads) {
281 if (ads->iflags & adns_if_nosigpipe) return;
283 sigfillset(&toblock);
284 sigdelset(&toblock,SIGPIPE);
286 sa.sa_handler= SIG_IGN;
287 sigfillset(&sa.sa_mask);
290 r= sigprocmask(SIG_SETMASK,&toblock,&ads->stdsigmask); assert(!r);
291 r= sigaction(SIGPIPE,&sa,&ads->stdsigpipe); assert(!r);
294 void adns__sigpipe_unprotect(adns_state ads) {
297 if (ads->iflags & adns_if_nosigpipe) return;
299 r= sigaction(SIGPIPE,&ads->stdsigpipe,0); assert(!r);
300 r= sigprocmask(SIG_SETMASK,&ads->stdsigmask,0); assert(!r);