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 <sys/types.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
34 /* Core diagnostic functions */
36 void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
37 int serv, adns_query qu, const char *fmt, va_list al) {
38 const char *bef, *aft;
42 (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))))
45 fprintf(ads->diagfile,"adns%s: ",pfx);
47 vfprintf(ads->diagfile,fmt,al);
52 if (qu && qu->query_dgram) {
54 fprintf(ads->diagfile,"%sQNAME=%s, QTYPE=%s",
56 adns__diag_domain(qu->ads,-1,0, &vb,
57 qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
58 qu->typei ? qu->typei->rrtname : "<unknown>");
59 if (qu->typei && qu->typei->fmtname)
60 fprintf(ads->diagfile,"(%s)",qu->typei->fmtname);
65 fprintf(ads->diagfile,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
69 fputs(aft,ads->diagfile);
72 void adns__debug(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
76 adns__vdiag(ads," debug",0,serv,qu,fmt,al);
80 void adns__warn(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
84 adns__vdiag(ads," warning",adns_if_noerrprint|adns_if_noserverwarn,serv,qu,fmt,al);
88 void adns__diag(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
92 adns__vdiag(ads,"",adns_if_noerrprint,serv,qu,fmt,al);
98 void adns__vbuf_init(vbuf *vb) {
99 vb->used= vb->avail= 0; vb->buf= 0;
102 int adns__vbuf_ensure(vbuf *vb, int want) {
105 if (vb->avail >= want) return 1;
106 nb= realloc(vb->buf,want); if (!nb) return 0;
112 void adns__vbuf_appendq(vbuf *vb, const byte *data, int len) {
113 memcpy(vb->buf+vb->used,data,len);
117 int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
121 newlen= vb->used+len;
122 if (vb->avail < newlen) {
123 if (newlen<20) newlen= 20;
125 nb= realloc(vb->buf,newlen);
126 if (!nb) { newlen= vb->used+len; nb= realloc(vb->buf,newlen); }
131 adns__vbuf_appendq(vb,data,len);
135 int adns__vbuf_appendstr(vbuf *vb, const char *data) {
138 return adns__vbuf_append(vb,data,l);
141 void adns__vbuf_free(vbuf *vb) {
146 /* Additional diagnostic functions */
148 const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
149 vbuf *vb, const byte *dgram, int dglen, int cbyte) {
152 st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen);
153 if (st == adns_s_nomemory) {
154 return "<cannot report domain... out of memory>";
158 if (!(adns__vbuf_appendstr(vb,"<bad format... ") &&
159 adns__vbuf_appendstr(vb,adns_strerror(st)) &&
160 adns__vbuf_appendstr(vb,">") &&
161 adns__vbuf_append(vb,"",1))) {
162 return "<cannot report bad format... out of memory>";
166 adns__vbuf_appendstr(vb,"<truncated ...>");
167 adns__vbuf_append(vb,"",1);
172 adns_status adns_rr_info(adns_rrtype type,
173 const char **rrtname_r, const char **fmtname_r,
175 const void *datap, char **data_r) {
176 const typeinfo *typei;
180 typei= adns__findtype(type);
181 if (!typei) return adns_s_unknownrrtype;
183 if (rrtname_r) *rrtname_r= typei->rrtname;
184 if (fmtname_r) *fmtname_r= typei->fmtname;
185 if (len_r) *len_r= typei->rrsz;
187 if (!datap) return adns_s_ok;
189 adns__vbuf_init(&vb);
190 st= typei->convstring(&vb,datap);
191 if (st) goto x_freevb;
192 if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nomemory; goto x_freevb; }
193 assert(strlen(vb.buf) == vb.used-1);
194 *data_r= realloc(vb.buf,vb.used);
195 if (!*data_r) *data_r= vb.buf;
199 adns__vbuf_free(&vb);
203 #define SINFO(n,s) { adns_s_##n, #n, s }
205 static const struct sinfo {
212 SINFO( nomemory, "Out of memory" ),
213 SINFO( unknownrrtype, "Query not implemented in DNS library" ),
214 SINFO( systemfail, "General resolver or system failure" ),
216 SINFO( timeout, "DNS query timed out" ),
217 SINFO( allservfail, "All nameservers failed" ),
218 SINFO( norecurse, "Recursion denied by nameserver" ),
219 SINFO( invalidresponse, "Nameserver sent bad response" ),
220 SINFO( unknownformat, "Nameserver used unknown format" ),
222 SINFO( rcodeservfail, "Nameserver reports failure" ),
223 SINFO( rcodeformaterror, "Query not understood by nameserver" ),
224 SINFO( rcodenotimplemented, "Query not implemented by nameserver" ),
225 SINFO( rcoderefused, "Query refused by nameserver" ),
226 SINFO( rcodeunknown, "Nameserver sent unknown response code" ),
228 SINFO( inconsistent, "Inconsistent resource records in DNS" ),
229 SINFO( prohibitedcname, "DNS data refers to an alias" ),
230 SINFO( answerdomaininvalid, "Found syntactically invalid domain name" ),
231 SINFO( answerdomaintoolong, "Found overly-long domain name" ),
232 SINFO( invaliddata, "Found invalid DNS data" ),
234 SINFO( querydomainwrong, "Domain invalid for particular DNS query type" ),
235 SINFO( querydomaininvalid, "Domain name is syntactically invalid" ),
236 SINFO( querydomaintoolong, "Domain name is too long" ),
238 SINFO( nxdomain, "No such domain" ),
239 SINFO( nodata, "No such data" ),
242 static int si_compar(const void *key, const void *elem) {
243 const adns_status *st= key;
244 const struct sinfo *si= elem;
246 return *st < si->st ? -1 : *st > si->st ? 1 : 0;
249 static const struct sinfo *findsinfo(adns_status st) {
250 return bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*sinfos),sizeof(*sinfos),si_compar);
253 const char *adns_strerror(adns_status st) {
254 const struct sinfo *si;
260 const char *adns_errabbrev(adns_status st) {
261 const struct sinfo *si;
267 void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
268 int (*needswap)(void *context, const void *a, const void *b),
273 for (i=0; i<nobjs; i++) {
275 place>0 && needswap(context, data + (place-1)*sz, data + i*sz);
278 memcpy(tempbuf, data + i*sz, sz);
279 memmove(data + (place+1)*sz, data + place*sz, (i-place)*sz);
280 memcpy(data + place*sz, tempbuf, sz);
285 /* SIGPIPE protection. */
287 void adns__sigpipe_protect(adns_state ads) {
292 if (ads->iflags & adns_if_nosigpipe) return;
294 sigfillset(&toblock);
295 sigdelset(&toblock,SIGPIPE);
297 sa.sa_handler= SIG_IGN;
298 sigfillset(&sa.sa_mask);
301 r= sigprocmask(SIG_SETMASK,&toblock,&ads->stdsigmask); assert(!r);
302 r= sigaction(SIGPIPE,&sa,&ads->stdsigpipe); assert(!r);
305 void adns__sigpipe_unprotect(adns_state ads) {
308 if (ads->iflags & adns_if_nosigpipe) return;
310 r= sigaction(SIGPIPE,&ads->stdsigpipe,0); assert(!r);
311 r= sigprocmask(SIG_SETMASK,&ads->stdsigmask,0); assert(!r);