* - vbuf handling
*/
/*
- * This file is part of adns, which is Copyright (C) 1997, 1998 Ian Jackson
+ * This file is part of adns, which is Copyright (C) 1997-1999 Ian Jackson
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
#include <arpa/inet.h>
#include "internal.h"
int serv, adns_query qu, const char *fmt, va_list al) {
const char *bef, *aft;
vbuf vb;
- if (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))) return;
+
+ if (!ads->diagfile ||
+ (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))))
+ return;
- fprintf(stderr,"adns%s: ",pfx);
+ fprintf(ads->diagfile,"adns%s: ",pfx);
- vfprintf(stderr,fmt,al);
+ vfprintf(ads->diagfile,fmt,al);
bef= " (";
aft= "\n";
if (qu && qu->query_dgram) {
adns__vbuf_init(&vb);
- fprintf(stderr,"%sQNAME=%s, QTYPE=%s",
+ fprintf(ads->diagfile,"%sQNAME=%s, QTYPE=%s",
bef,
- adns__diag_domain(qu->ads,-1,0, &vb,qu->flags,
+ adns__diag_domain(qu->ads,-1,0, &vb,
qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
qu->typei ? qu->typei->rrtname : "<unknown>");
if (qu->typei && qu->typei->fmtname)
- fprintf(stderr,"(%s)",qu->typei->fmtname);
+ fprintf(ads->diagfile,"(%s)",qu->typei->fmtname);
bef=", "; aft=")\n";
}
if (serv>=0) {
- fprintf(stderr,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
+ fprintf(ads->diagfile,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
bef=", "; aft=")\n";
}
- fputs(aft,stderr);
+ fputs(aft,ads->diagfile);
}
void adns__debug(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
/* Additional diagnostic functions */
-const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, vbuf *vb,
- int flags, const byte *dgram, int dglen, int cbyte) {
+const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
+ vbuf *vb, const byte *dgram, int dglen, int cbyte) {
adns_status st;
- st= adns__parse_domain(ads,serv,qu,vb, flags,dgram,dglen,&cbyte,dglen);
- if (st == adns_s_nolocalmem) {
+ st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen);
+ if (st == adns_s_nomemory) {
return "<cannot report domain... out of memory>";
}
if (st) {
adns_status st;
typei= adns__findtype(type);
- if (!typei) return adns_s_notimplemented;
+ if (!typei) return adns_s_unknownrrtype;
if (rrtname_r) *rrtname_r= typei->rrtname;
if (fmtname_r) *fmtname_r= typei->fmtname;
adns__vbuf_init(&vb);
st= typei->convstring(&vb,datap);
if (st) goto x_freevb;
- if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nolocalmem; goto x_freevb; }
+ if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nomemory; goto x_freevb; }
assert(strlen(vb.buf) == vb.used-1);
*data_r= realloc(vb.buf,vb.used);
if (!*data_r) *data_r= vb.buf;
return st;
}
-#define SINFO(n,s) { adns_s_##n, s }
+#define SINFO(n,s) { adns_s_##n, #n, s }
static const struct sinfo {
adns_status st;
+ const char *abbrev;
const char *string;
} sinfos[]= {
- SINFO( ok, "OK" ),
- SINFO( timeout, "Timed out" ),
- SINFO( nolocalmem, "Out of memory" ),
- SINFO( allservfail, "No working nameservers" ),
- SINFO( servfail, "Nameserver failure" ),
- SINFO( notimplemented, "Query not implemented" ),
- SINFO( refused, "Refused by nameserver" ),
- SINFO( reasonunknown, "Reason unknown" ),
- SINFO( norecurse, "Recursion denied by nameserver" ),
- SINFO( serverfaulty, "Nameserver sent bad data" ),
- SINFO( unknownreply, "Reply from nameserver not understood" ),
- SINFO( invaliddata, "Invalid data" ),
- SINFO( inconsistent, "Inconsistent data" ),
- SINFO( cname, "RR refers to an alias" ),
- SINFO( nxdomain, "No such domain" ),
- SINFO( nodata, "No such data" ),
- SINFO( invaliddomain, "Domain syntactically invalid" ),
- SINFO( domaintoolong, "Domain name too long" )
+ SINFO( ok, "OK" ),
+
+ SINFO( nomemory, "Out of memory" ),
+ SINFO( unknownrrtype, "Query not implemented in DNS library" ),
+ SINFO( systemfail, "General resolver or system failure" ),
+
+ SINFO( timeout, "DNS query timed out" ),
+ SINFO( allservfail, "All nameservers failed" ),
+ SINFO( norecurse, "Recursion denied by nameserver" ),
+ SINFO( invalidresponse, "Nameserver sent bad response" ),
+ SINFO( unknownformat, "Nameserver used unknown format" ),
+
+ SINFO( rcodeservfail, "Nameserver reports failure" ),
+ SINFO( rcodeformaterror, "Query not understood by nameserver" ),
+ SINFO( rcodenotimplemented, "Query not implemented by nameserver" ),
+ SINFO( rcoderefused, "Query refused by nameserver" ),
+ SINFO( rcodeunknown, "Nameserver sent unknown response code" ),
+
+ SINFO( inconsistent, "Inconsistent resource records in DNS" ),
+ SINFO( prohibitedcname, "DNS data refers to an alias" ),
+ SINFO( answerdomaininvalid, "Found syntactically invalid domain name" ),
+ SINFO( answerdomaintoolong, "Found overly-long domain name" ),
+ SINFO( invaliddata, "Found invalid DNS data" ),
+
+ SINFO( querydomainwrong, "Domain invalid for particular DNS query type" ),
+ SINFO( querydomaininvalid, "Domain name is syntactically invalid" ),
+ SINFO( querydomaintoolong, "Domain name is too long" ),
+
+ SINFO( nxdomain, "No such domain" ),
+ SINFO( nodata, "No such data" ),
};
static int si_compar(const void *key, const void *elem) {
return *st < si->st ? -1 : *st > si->st ? 1 : 0;
}
+static const struct sinfo *findsinfo(adns_status st) {
+ return bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*sinfos),sizeof(*sinfos),si_compar);
+}
+
const char *adns_strerror(adns_status st) {
- static char buf[100];
+ const struct sinfo *si;
+ si= findsinfo(st);
+ return si->string;
+}
+
+const char *adns_errabbrev(adns_status st) {
const struct sinfo *si;
- si= bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*si),sizeof(*si),si_compar);
- if (si) return si->string;
+ si= findsinfo(st);
+ return si->abbrev;
+}
+
+void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
+ int (*needswap)(void *context, const void *a, const void *b),
+ void *context) {
+ byte *data= array;
+ int i, place;
+
+ for (i=0; i<nobjs; i++) {
+ for (place= i;
+ place>0 && needswap(context, data + (place-1)*sz, data + i*sz);
+ place--);
+ if (place != i) {
+ memcpy(tempbuf, data + i*sz, sz);
+ memmove(data + (place+1)*sz, data + place*sz, (i-place)*sz);
+ memcpy(data + place*sz, tempbuf, sz);
+ }
+ }
+}
+
+/* SIGPIPE protection. */
+
+void adns__sigpipe_protect(adns_state ads) {
+ sigset_t toblock;
+ struct sigaction sa;
+ int r;
+
+ if (ads->iflags & adns_if_nosigpipe) return;
+
+ sigfillset(&toblock);
+ sigdelset(&toblock,SIGPIPE);
+
+ sa.sa_handler= SIG_IGN;
+ sigfillset(&sa.sa_mask);
+ sa.sa_flags= 0;
- snprintf(buf,sizeof(buf),"code %d",st);
- return buf;
+ r= sigprocmask(SIG_SETMASK,&toblock,&ads->stdsigmask); assert(!r);
+ r= sigaction(SIGPIPE,&sa,&ads->stdsigpipe); assert(!r);
+}
+
+void adns__sigpipe_unprotect(adns_state ads) {
+ int r;
+
+ if (ads->iflags & adns_if_nosigpipe) return;
+
+ r= sigaction(SIGPIPE,&ads->stdsigpipe,0); assert(!r);
+ r= sigprocmask(SIG_SETMASK,&ads->stdsigmask,0); assert(!r);
}