3 * - diagnostic functions
7 * This file is part of adns, which is Copyright (C) 1997, 1998 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;
37 if (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))) return;
39 fprintf(stderr,"adns%s: ",pfx);
41 vfprintf(stderr,fmt,al);
46 if (qu && qu->query_dgram) {
48 fprintf(stderr,"%sQNAME=%s, QTYPE=%s",
50 adns__diag_domain(qu->ads,-1,0, &vb,
51 qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
52 qu->typei ? qu->typei->rrtname : "<unknown>");
53 if (qu->typei && qu->typei->fmtname)
54 fprintf(stderr,"(%s)",qu->typei->fmtname);
59 fprintf(stderr,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
66 void adns__debug(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
70 adns__vdiag(ads," debug",0,serv,qu,fmt,al);
74 void adns__warn(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
78 adns__vdiag(ads," warning",adns_if_noerrprint|adns_if_noserverwarn,serv,qu,fmt,al);
82 void adns__diag(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
86 adns__vdiag(ads,"",adns_if_noerrprint,serv,qu,fmt,al);
92 void adns__vbuf_init(vbuf *vb) {
93 vb->used= vb->avail= 0; vb->buf= 0;
96 int adns__vbuf_ensure(vbuf *vb, int want) {
99 if (vb->avail >= want) return 1;
100 nb= realloc(vb->buf,want); if (!nb) return 0;
106 void adns__vbuf_appendq(vbuf *vb, const byte *data, int len) {
107 memcpy(vb->buf+vb->used,data,len);
111 int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
115 newlen= vb->used+len;
116 if (vb->avail < newlen) {
117 if (newlen<20) newlen= 20;
119 nb= realloc(vb->buf,newlen);
120 if (!nb) { newlen= vb->used+len; nb= realloc(vb->buf,newlen); }
125 adns__vbuf_appendq(vb,data,len);
129 int adns__vbuf_appendstr(vbuf *vb, const char *data) {
132 return adns__vbuf_append(vb,data,l);
135 void adns__vbuf_free(vbuf *vb) {
140 /* Additional diagnostic functions */
142 const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
143 vbuf *vb, const byte *dgram, int dglen, int cbyte) {
146 st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen);
147 if (st == adns_s_nomemory) {
148 return "<cannot report domain... out of memory>";
152 if (!(adns__vbuf_appendstr(vb,"<bad format... ") &&
153 adns__vbuf_appendstr(vb,adns_strerror(st)) &&
154 adns__vbuf_appendstr(vb,">") &&
155 adns__vbuf_append(vb,"",1))) {
156 return "<cannot report bad format... out of memory>";
160 adns__vbuf_appendstr(vb,"<truncated ...>");
161 adns__vbuf_append(vb,"",1);
166 adns_status adns_rr_info(adns_rrtype type,
167 const char **rrtname_r, const char **fmtname_r,
169 const void *datap, char **data_r) {
170 const typeinfo *typei;
174 typei= adns__findtype(type);
175 if (!typei) return adns_s_unknownrrtype;
177 if (rrtname_r) *rrtname_r= typei->rrtname;
178 if (fmtname_r) *fmtname_r= typei->fmtname;
179 if (len_r) *len_r= typei->rrsz;
181 if (!datap) return adns_s_ok;
183 adns__vbuf_init(&vb);
184 st= typei->convstring(&vb,datap);
185 if (st) goto x_freevb;
186 if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nomemory; goto x_freevb; }
187 assert(strlen(vb.buf) == vb.used-1);
188 *data_r= realloc(vb.buf,vb.used);
189 if (!*data_r) *data_r= vb.buf;
193 adns__vbuf_free(&vb);
197 #define SINFO(n,s) { adns_s_##n, s }
199 static const struct sinfo {
205 SINFO( nomemory, "Out of memory" ),
206 SINFO( unknownrrtype, "Query not implemented in DNS library" ),
208 SINFO( timeout, "DNS query timed out" ),
209 SINFO( allservfail, "All nameservers failed" ),
210 SINFO( norecurse, "Recursion denied by nameserver" ),
211 SINFO( invalidresponse, "Nameserver sent bad response" ),
212 SINFO( unknownformat, "Nameserver used unknown format" ),
214 SINFO( rcodeservfail, "Nameserver reports failure" ),
215 SINFO( rcodeformaterror, "Query not understood by nameserver" ),
216 SINFO( rcodenotimplemented, "Query not implemented by nameserver" ),
217 SINFO( rcoderefused, "Query refused by nameserver" ),
218 SINFO( rcodeunknown, "Nameserver sent unknown response code" ),
220 SINFO( inconsistent, "Inconsistent resource records in DNS" ),
221 SINFO( prohibitedcname, "DNS data refers to an alias" ),
222 SINFO( answerdomaininvalid, "Found syntactically invalid domain name" ),
223 SINFO( answerdomaintoolong, "Found overly-long domain name" ),
224 SINFO( invaliddata, "Found invalid DNS data" ),
226 SINFO( querydomainwrong, "Domain invalid for particular DNS query type" ),
227 SINFO( querydomaininvalid, "Domain name is syntactically invalid" ),
228 SINFO( querydomaintoolong, "Domain name is too long" ),
230 SINFO( nxdomain, "No such domain" ),
231 SINFO( nodata, "No such data" ),
234 static int si_compar(const void *key, const void *elem) {
235 const adns_status *st= key;
236 const struct sinfo *si= elem;
238 return *st < si->st ? -1 : *st > si->st ? 1 : 0;
241 const char *adns_strerror(adns_status st) {
242 static char buf[100];
244 const struct sinfo *si;
246 si= bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*si),sizeof(*si),si_compar);
247 if (si) return si->string;
249 snprintf(buf,sizeof(buf),"code %d",st);
253 void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
254 int (*needswap)(const void *a, const void *b)) {
258 for (i=0; i<nobjs; i++) {
259 for (place= i; place>0 && needswap(data + (place-1)*sz, data + i*sz); place--);
262 memcpy(tempbuf, data + i*sz, sz);
263 memmove(data + (place+1)*sz, data + place*sz, (i-place)*sz);
264 memcpy(data + place*sz, tempbuf, sz);