Reorder files for best compilation.
[adns] / src / general.c
CommitLineData
e576be50 1/*
2 * general.c
3 * - diagnostic functions
4 * - vbuf handling
5 */
6/*
7 * This file is part of adns, which is Copyright (C) 1997, 1998 Ian Jackson
8 *
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)
12 * any later version.
13 *
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.
18 *
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.
22 */
23
3955725c 24#include <stdlib.h>
88372443 25#include <string.h>
3955725c 26
27#include <arpa/inet.h>
28
e576be50 29#include "internal.h"
30
31/* Core diagnostic functions */
32
33void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
3955725c 34 int serv, adns_query qu, const char *fmt, va_list al) {
e576be50 35 const char *bef, *aft;
36 vbuf vb;
37 if (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))) return;
38
39 fprintf(stderr,"adns%s: ",pfx);
40
41 vfprintf(stderr,fmt,al);
42
43 bef= " (";
44 aft= "\n";
45
46 if (qu && qu->query_dgram) {
47 adns__vbuf_init(&vb);
48 fprintf(stderr,"%sQNAME=%s, QTYPE=%s",
49 bef,
828d89bd 50 adns__diag_domain(qu->ads,-1,0, &vb,
3955725c 51 qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
86e7b8d9 52 qu->typei ? qu->typei->rrtname : "<unknown>");
53 if (qu->typei && qu->typei->fmtname)
54 fprintf(stderr,"(%s)",qu->typei->fmtname);
e576be50 55 bef=", "; aft=")\n";
56 }
57
58 if (serv>=0) {
59 fprintf(stderr,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
60 bef=", "; aft=")\n";
61 }
62
63 fputs(aft,stderr);
64}
65
66void adns__debug(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
67 va_list al;
68
69 va_start(al,fmt);
70 adns__vdiag(ads," debug",0,serv,qu,fmt,al);
71 va_end(al);
72}
73
74void adns__warn(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
75 va_list al;
76
77 va_start(al,fmt);
78 adns__vdiag(ads," warning",adns_if_noerrprint|adns_if_noserverwarn,serv,qu,fmt,al);
79 va_end(al);
80}
81
82void adns__diag(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
83 va_list al;
84
85 va_start(al,fmt);
86 adns__vdiag(ads,"",adns_if_noerrprint,serv,qu,fmt,al);
87 va_end(al);
88}
89
90/* vbuf functions */
91
92void adns__vbuf_init(vbuf *vb) {
93 vb->used= vb->avail= 0; vb->buf= 0;
94}
95
96int adns__vbuf_ensure(vbuf *vb, int want) {
97 void *nb;
98
99 if (vb->avail >= want) return 1;
100 nb= realloc(vb->buf,want); if (!nb) return 0;
101 vb->buf= nb;
102 vb->avail= want;
103 return 1;
104}
105
106void adns__vbuf_appendq(vbuf *vb, const byte *data, int len) {
107 memcpy(vb->buf+vb->used,data,len);
108 vb->used+= len;
109}
110
111int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
112 int newlen;
113 void *nb;
114
115 newlen= vb->used+len;
116 if (vb->avail < newlen) {
a49a6d7b 117 if (newlen<20) newlen= 20;
e576be50 118 newlen <<= 1;
119 nb= realloc(vb->buf,newlen);
a49a6d7b 120 if (!nb) { newlen= vb->used+len; nb= realloc(vb->buf,newlen); }
e576be50 121 if (!nb) return 0;
122 vb->buf= nb;
123 vb->avail= newlen;
124 }
125 adns__vbuf_appendq(vb,data,len);
126 return 1;
127}
128
f759e52e 129int adns__vbuf_appendstr(vbuf *vb, const char *data) {
130 int l;
9557e604 131 l= strlen(data);
f759e52e 132 return adns__vbuf_append(vb,data,l);
133}
134
a49a6d7b 135void adns__vbuf_free(vbuf *vb) {
136 free(vb->buf);
137 adns__vbuf_init(vb);
138}
139
e576be50 140/* Additional diagnostic functions */
141
828d89bd 142const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
143 vbuf *vb, const byte *dgram, int dglen, int cbyte) {
e576be50 144 adns_status st;
145
828d89bd 146 st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen);
ea1e31e3 147 if (st == adns_s_nomemory) {
e576be50 148 return "<cannot report domain... out of memory>";
149 }
150 if (st) {
151 vb->used= 0;
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>";
157 }
158 }
3955725c 159 if (!vb->used) {
e576be50 160 adns__vbuf_appendstr(vb,"<truncated ...>");
161 adns__vbuf_append(vb,"",1);
162 }
163 return vb->buf;
164}
86e7b8d9 165
166adns_status adns_rr_info(adns_rrtype type,
167 const char **rrtname_r, const char **fmtname_r,
168 int *len_r,
169 const void *datap, char **data_r) {
170 const typeinfo *typei;
171 vbuf vb;
172 adns_status st;
173
174 typei= adns__findtype(type);
ea1e31e3 175 if (!typei) return adns_s_unknownrrtype;
86e7b8d9 176
177 if (rrtname_r) *rrtname_r= typei->rrtname;
178 if (fmtname_r) *fmtname_r= typei->fmtname;
179 if (len_r) *len_r= typei->rrsz;
180
181 if (!datap) return adns_s_ok;
182
183 adns__vbuf_init(&vb);
184 st= typei->convstring(&vb,datap);
185 if (st) goto x_freevb;
ea1e31e3 186 if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nomemory; goto x_freevb; }
86e7b8d9 187 assert(strlen(vb.buf) == vb.used-1);
188 *data_r= realloc(vb.buf,vb.used);
189 if (!*data_r) *data_r= vb.buf;
190 return adns_s_ok;
191
192 x_freevb:
193 adns__vbuf_free(&vb);
194 return st;
195}
196
197#define SINFO(n,s) { adns_s_##n, s }
198
199static const struct sinfo {
200 adns_status st;
201 const char *string;
202} sinfos[]= {
ea1e31e3 203 SINFO( ok, "OK" ),
204
205 SINFO( nomemory, "Out of memory" ),
206 SINFO( unknownrrtype, "Query not implemented in DNS library" ),
207
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" ),
213
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" ),
219
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" ),
225
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" ),
229
230 SINFO( nxdomain, "No such domain" ),
231 SINFO( nodata, "No such data" ),
86e7b8d9 232};
233
234static int si_compar(const void *key, const void *elem) {
235 const adns_status *st= key;
236 const struct sinfo *si= elem;
237
238 return *st < si->st ? -1 : *st > si->st ? 1 : 0;
239}
240
e576be50 241const char *adns_strerror(adns_status st) {
242 static char buf[100];
86e7b8d9 243
244 const struct sinfo *si;
245
246 si= bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*si),sizeof(*si),si_compar);
247 if (si) return si->string;
248
e576be50 249 snprintf(buf,sizeof(buf),"code %d",st);
250 return buf;
251}
88372443 252
253void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
254 int (*needswap)(const void *a, const void *b)) {
255 byte *data= array;
256 int i, place;
257
258 for (i=0; i<nobjs; i++) {
259 for (place= i; place>0 && needswap(data + (place-1)*sz, data + i*sz); place--);
260
261 if (place != i) {
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);
265 }
266 }
267}