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/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
33 /* Core diagnostic functions */
35 void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
36 int serv, adns_query qu, const char *fmt, va_list al) {
37 const char *bef, *aft;
41 (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))))
44 fprintf(ads->diagfile,"adns%s: ",pfx);
46 vfprintf(ads->diagfile,fmt,al);
51 if (qu && qu->query_dgram) {
53 fprintf(ads->diagfile,"%sQNAME=%s, QTYPE=%s",
55 adns__diag_domain(qu->ads,-1,0, &vb,
56 qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
57 qu->typei ? qu->typei->rrtname : "<unknown>");
58 if (qu->typei && qu->typei->fmtname)
59 fprintf(ads->diagfile,"(%s)",qu->typei->fmtname);
64 fprintf(ads->diagfile,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
68 fputs(aft,ads->diagfile);
71 void adns__debug(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
75 adns__vdiag(ads," debug",0,serv,qu,fmt,al);
79 void adns__warn(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
83 adns__vdiag(ads," warning",adns_if_noerrprint|adns_if_noserverwarn,serv,qu,fmt,al);
87 void adns__diag(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
91 adns__vdiag(ads,"",adns_if_noerrprint,serv,qu,fmt,al);
97 void adns__vbuf_init(vbuf *vb) {
98 vb->used= vb->avail= 0; vb->buf= 0;
101 int adns__vbuf_ensure(vbuf *vb, int want) {
104 if (vb->avail >= want) return 1;
105 nb= realloc(vb->buf,want); if (!nb) return 0;
111 void adns__vbuf_appendq(vbuf *vb, const byte *data, int len) {
112 memcpy(vb->buf+vb->used,data,len);
116 int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
120 newlen= vb->used+len;
121 if (vb->avail < newlen) {
122 if (newlen<20) newlen= 20;
124 nb= realloc(vb->buf,newlen);
125 if (!nb) { newlen= vb->used+len; nb= realloc(vb->buf,newlen); }
130 adns__vbuf_appendq(vb,data,len);
134 int adns__vbuf_appendstr(vbuf *vb, const char *data) {
137 return adns__vbuf_append(vb,data,l);
140 void adns__vbuf_free(vbuf *vb) {
145 /* Additional diagnostic functions */
147 const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
148 vbuf *vb, const byte *dgram, int dglen, int cbyte) {
151 st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen);
152 if (st == adns_s_nomemory) {
153 return "<cannot report domain... out of memory>";
157 if (!(adns__vbuf_appendstr(vb,"<bad format... ") &&
158 adns__vbuf_appendstr(vb,adns_strerror(st)) &&
159 adns__vbuf_appendstr(vb,">") &&
160 adns__vbuf_append(vb,"",1))) {
161 return "<cannot report bad format... out of memory>";
165 adns__vbuf_appendstr(vb,"<truncated ...>");
166 adns__vbuf_append(vb,"",1);
171 adns_status adns_rr_info(adns_rrtype type,
172 const char **rrtname_r, const char **fmtname_r,
174 const void *datap, char **data_r) {
175 const typeinfo *typei;
179 typei= adns__findtype(type);
180 if (!typei) return adns_s_unknownrrtype;
182 if (rrtname_r) *rrtname_r= typei->rrtname;
183 if (fmtname_r) *fmtname_r= typei->fmtname;
184 if (len_r) *len_r= typei->rrsz;
186 if (!datap) return adns_s_ok;
188 adns__vbuf_init(&vb);
189 st= typei->convstring(&vb,datap);
190 if (st) goto x_freevb;
191 if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nomemory; goto x_freevb; }
192 assert(strlen(vb.buf) == vb.used-1);
193 *data_r= realloc(vb.buf,vb.used);
194 if (!*data_r) *data_r= vb.buf;
198 adns__vbuf_free(&vb);
202 #define SINFO(n,s) { adns_s_##n, s }
204 static const struct sinfo {
210 SINFO( nomemory, "Out of memory" ),
211 SINFO( unknownrrtype, "Query not implemented in DNS library" ),
213 SINFO( timeout, "DNS query timed out" ),
214 SINFO( allservfail, "All nameservers failed" ),
215 SINFO( norecurse, "Recursion denied by nameserver" ),
216 SINFO( invalidresponse, "Nameserver sent bad response" ),
217 SINFO( unknownformat, "Nameserver used unknown format" ),
219 SINFO( rcodeservfail, "Nameserver reports failure" ),
220 SINFO( rcodeformaterror, "Query not understood by nameserver" ),
221 SINFO( rcodenotimplemented, "Query not implemented by nameserver" ),
222 SINFO( rcoderefused, "Query refused by nameserver" ),
223 SINFO( rcodeunknown, "Nameserver sent unknown response code" ),
225 SINFO( inconsistent, "Inconsistent resource records in DNS" ),
226 SINFO( prohibitedcname, "DNS data refers to an alias" ),
227 SINFO( answerdomaininvalid, "Found syntactically invalid domain name" ),
228 SINFO( answerdomaintoolong, "Found overly-long domain name" ),
229 SINFO( invaliddata, "Found invalid DNS data" ),
231 SINFO( querydomainwrong, "Domain invalid for particular DNS query type" ),
232 SINFO( querydomaininvalid, "Domain name is syntactically invalid" ),
233 SINFO( querydomaintoolong, "Domain name is too long" ),
235 SINFO( nxdomain, "No such domain" ),
236 SINFO( nodata, "No such data" ),
239 static int si_compar(const void *key, const void *elem) {
240 const adns_status *st= key;
241 const struct sinfo *si= elem;
243 return *st < si->st ? -1 : *st > si->st ? 1 : 0;
246 const char *adns_strerror(adns_status st) {
247 static char buf[100];
249 const struct sinfo *si;
251 si= bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*si),sizeof(*si),si_compar);
252 if (si) return si->string;
254 snprintf(buf,sizeof(buf),"code %d",st);
258 void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
259 int (*needswap)(void *context, const void *a, const void *b),
264 for (i=0; i<nobjs; i++) {
266 place>0 && needswap(context, data + (place-1)*sz, data + i*sz);
269 memcpy(tempbuf, data + i*sz, sz);
270 memmove(data + (place+1)*sz, data + place*sz, (i-place)*sz);
271 memcpy(data + place*sz, tempbuf, sz);
276 /* SIGPIPE protection. */
278 void adns__sigpipe_protect(adns_state ads) {
283 if (ads->iflags & adns_if_nosigpipe) return;
285 sigfillset(&toblock);
286 sigdelset(&toblock,SIGPIPE);
288 sa.sa_handler= SIG_IGN;
289 sigfillset(&sa.sa_mask);
292 r= sigprocmask(SIG_SETMASK,&toblock,&ads->stdsigmask); assert(!r);
293 r= sigaction(SIGPIPE,&sa,&ads->stdsigpipe); assert(!r);
296 void adns__sigpipe_unprotect(adns_state ads) {
299 if (ads->iflags & adns_if_nosigpipe) return;
301 r= sigaction(SIGPIPE,&ads->stdsigpipe,0); assert(!r);
302 r= sigprocmask(SIG_SETMASK,&ads->stdsigmask,0); assert(!r);