src/: Pass the wanted query's type code to adns__internal_submit.
[adns] / src / general.c
CommitLineData
e576be50 1/*
2 * general.c
3 * - diagnostic functions
4 * - vbuf handling
5 */
6/*
ae8cc977 7 * This file is part of adns, which is
8 * Copyright (C) 1997-2000,2003,2006 Ian Jackson
9 * Copyright (C) 1999-2000,2003,2006 Tony Finch
10 * Copyright (C) 1991 Massachusetts Institute of Technology
11 * (See the file INSTALL for full details.)
e576be50 12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software Foundation,
25 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
3955725c 28#include <stdlib.h>
5f67bb7b 29#include <unistd.h>
3955725c 30
0f091044 31#include <sys/types.h>
eec1d9c8 32#include <sys/socket.h>
33#include <netinet/in.h>
3955725c 34#include <arpa/inet.h>
35
e576be50 36#include "internal.h"
37
38/* Core diagnostic functions */
39
d3a102c4 40void adns__vlprintf(adns_state ads, const char *fmt, va_list al) {
41 ads->logfn(ads,ads->logfndata,fmt,al);
42}
43
44void adns__lprintf(adns_state ads, const char *fmt, ...) {
45 va_list al;
46 va_start(al,fmt);
47 adns__vlprintf(ads,fmt,al);
48 va_end(al);
49}
50
e576be50 51void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
3955725c 52 int serv, adns_query qu, const char *fmt, va_list al) {
e576be50 53 const char *bef, *aft;
54 vbuf vb;
36369543 55
d3a102c4 56 if (!ads->logfn ||
609133ee 57 (!(ads->iflags & adns_if_debug)
58 && (!prevent || (ads->iflags & prevent))))
36369543 59 return;
e576be50 60
5f67bb7b 61 if (ads->iflags & adns_if_logpid) {
d3a102c4 62 adns__lprintf(ads,"adns%s [%ld]: ",pfx,(long)getpid());
5f67bb7b 63 } else {
d3a102c4 64 adns__lprintf(ads,"adns%s: ",pfx);
5f67bb7b 65 }
e576be50 66
d3a102c4 67 adns__vlprintf(ads,fmt,al);
e576be50 68
69 bef= " (";
70 aft= "\n";
71
72 if (qu && qu->query_dgram) {
73 adns__vbuf_init(&vb);
d3a102c4 74 adns__lprintf(ads,"%sQNAME=%s, QTYPE=%s",
e576be50 75 bef,
828d89bd 76 adns__diag_domain(qu->ads,-1,0, &vb,
3955725c 77 qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
86e7b8d9 78 qu->typei ? qu->typei->rrtname : "<unknown>");
79 if (qu->typei && qu->typei->fmtname)
d3a102c4 80 adns__lprintf(ads,"(%s)",qu->typei->fmtname);
e576be50 81 bef=", "; aft=")\n";
914a5ff5 82 adns__vbuf_free(&vb);
e576be50 83 }
84
85 if (serv>=0) {
d3a102c4 86 adns__lprintf(ads,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
e576be50 87 bef=", "; aft=")\n";
88 }
89
d3a102c4 90 adns__lprintf(ads,"%s",aft);
e576be50 91}
92
609133ee 93void adns__debug(adns_state ads, int serv, adns_query qu,
94 const char *fmt, ...) {
e576be50 95 va_list al;
96
97 va_start(al,fmt);
98 adns__vdiag(ads," debug",0,serv,qu,fmt,al);
99 va_end(al);
100}
101
609133ee 102void adns__warn(adns_state ads, int serv, adns_query qu,
103 const char *fmt, ...) {
e576be50 104 va_list al;
105
106 va_start(al,fmt);
609133ee 107 adns__vdiag(ads," warning",
108 adns_if_noerrprint|adns_if_noserverwarn, serv,qu,fmt,al);
e576be50 109 va_end(al);
110}
111
609133ee 112void adns__diag(adns_state ads, int serv, adns_query qu,
113 const char *fmt, ...) {
e576be50 114 va_list al;
115
116 va_start(al,fmt);
117 adns__vdiag(ads,"",adns_if_noerrprint,serv,qu,fmt,al);
118 va_end(al);
119}
120
121/* vbuf functions */
122
123void adns__vbuf_init(vbuf *vb) {
124 vb->used= vb->avail= 0; vb->buf= 0;
125}
126
127int adns__vbuf_ensure(vbuf *vb, int want) {
128 void *nb;
129
130 if (vb->avail >= want) return 1;
131 nb= realloc(vb->buf,want); if (!nb) return 0;
132 vb->buf= nb;
133 vb->avail= want;
134 return 1;
135}
136
137void adns__vbuf_appendq(vbuf *vb, const byte *data, int len) {
138 memcpy(vb->buf+vb->used,data,len);
139 vb->used+= len;
140}
141
142int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
143 int newlen;
144 void *nb;
145
146 newlen= vb->used+len;
147 if (vb->avail < newlen) {
a49a6d7b 148 if (newlen<20) newlen= 20;
e576be50 149 newlen <<= 1;
150 nb= realloc(vb->buf,newlen);
a49a6d7b 151 if (!nb) { newlen= vb->used+len; nb= realloc(vb->buf,newlen); }
e576be50 152 if (!nb) return 0;
153 vb->buf= nb;
154 vb->avail= newlen;
155 }
156 adns__vbuf_appendq(vb,data,len);
157 return 1;
158}
159
f759e52e 160int adns__vbuf_appendstr(vbuf *vb, const char *data) {
161 int l;
9557e604 162 l= strlen(data);
f759e52e 163 return adns__vbuf_append(vb,data,l);
164}
165
a49a6d7b 166void adns__vbuf_free(vbuf *vb) {
167 free(vb->buf);
168 adns__vbuf_init(vb);
169}
170
e576be50 171/* Additional diagnostic functions */
172
828d89bd 173const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
609133ee 174 vbuf *vb, const byte *dgram,
175 int dglen, int cbyte) {
e576be50 176 adns_status st;
177
609133ee 178 st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok,
179 dgram,dglen,&cbyte,dglen);
ea1e31e3 180 if (st == adns_s_nomemory) {
e576be50 181 return "<cannot report domain... out of memory>";
182 }
183 if (st) {
184 vb->used= 0;
185 if (!(adns__vbuf_appendstr(vb,"<bad format... ") &&
186 adns__vbuf_appendstr(vb,adns_strerror(st)) &&
187 adns__vbuf_appendstr(vb,">") &&
188 adns__vbuf_append(vb,"",1))) {
189 return "<cannot report bad format... out of memory>";
190 }
191 }
3955725c 192 if (!vb->used) {
e576be50 193 adns__vbuf_appendstr(vb,"<truncated ...>");
194 adns__vbuf_append(vb,"",1);
195 }
196 return vb->buf;
197}
86e7b8d9 198
199adns_status adns_rr_info(adns_rrtype type,
200 const char **rrtname_r, const char **fmtname_r,
201 int *len_r,
202 const void *datap, char **data_r) {
203 const typeinfo *typei;
204 vbuf vb;
205 adns_status st;
206
207 typei= adns__findtype(type);
ea1e31e3 208 if (!typei) return adns_s_unknownrrtype;
86e7b8d9 209
210 if (rrtname_r) *rrtname_r= typei->rrtname;
211 if (fmtname_r) *fmtname_r= typei->fmtname;
212 if (len_r) *len_r= typei->rrsz;
213
214 if (!datap) return adns_s_ok;
215
216 adns__vbuf_init(&vb);
217 st= typei->convstring(&vb,datap);
218 if (st) goto x_freevb;
ea1e31e3 219 if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nomemory; goto x_freevb; }
86e7b8d9 220 assert(strlen(vb.buf) == vb.used-1);
221 *data_r= realloc(vb.buf,vb.used);
222 if (!*data_r) *data_r= vb.buf;
223 return adns_s_ok;
224
225 x_freevb:
226 adns__vbuf_free(&vb);
227 return st;
228}
229
ac77ffc1 230
9da4a044 231#define SINFO(n,s) { adns_s_##n, #n, s }
86e7b8d9 232
233static const struct sinfo {
234 adns_status st;
9da4a044 235 const char *abbrev;
86e7b8d9 236 const char *string;
237} sinfos[]= {
609133ee 238 SINFO( ok, "OK" ),
239
240 SINFO( nomemory, "Out of memory" ),
241 SINFO( unknownrrtype, "Query not implemented in DNS library" ),
242 SINFO( systemfail, "General resolver or system failure" ),
243
244 SINFO( timeout, "DNS query timed out" ),
245 SINFO( allservfail, "All nameservers failed" ),
246 SINFO( norecurse, "Recursion denied by nameserver" ),
247 SINFO( invalidresponse, "Nameserver sent bad response" ),
248 SINFO( unknownformat, "Nameserver used unknown format" ),
249
250 SINFO( rcodeservfail, "Nameserver reports failure" ),
251 SINFO( rcodeformaterror, "Query not understood by nameserver" ),
252 SINFO( rcodenotimplemented, "Query not implemented by nameserver" ),
253 SINFO( rcoderefused, "Query refused by nameserver" ),
254 SINFO( rcodeunknown, "Nameserver sent unknown response code" ),
255
256 SINFO( inconsistent, "Inconsistent resource records in DNS" ),
257 SINFO( prohibitedcname, "DNS alias found where canonical name wanted" ),
258 SINFO( answerdomaininvalid, "Found syntactically invalid domain name" ),
259 SINFO( answerdomaintoolong, "Found overly-long domain name" ),
260 SINFO( invaliddata, "Found invalid DNS data" ),
261
262 SINFO( querydomainwrong, "Domain invalid for particular DNS query type" ),
263 SINFO( querydomaininvalid, "Domain name is syntactically invalid" ),
264 SINFO( querydomaintoolong, "Domain name or component is too long" ),
265
266 SINFO( nxdomain, "No such domain" ),
267 SINFO( nodata, "No such data" )
86e7b8d9 268};
269
270static int si_compar(const void *key, const void *elem) {
271 const adns_status *st= key;
272 const struct sinfo *si= elem;
273
274 return *st < si->st ? -1 : *st > si->st ? 1 : 0;
275}
276
9da4a044 277static const struct sinfo *findsinfo(adns_status st) {
609133ee 278 return bsearch(&st,sinfos, sizeof(sinfos)/sizeof(*sinfos),
279 sizeof(*sinfos), si_compar);
9da4a044 280}
281
e576be50 282const char *adns_strerror(adns_status st) {
9da4a044 283 const struct sinfo *si;
86e7b8d9 284
9da4a044 285 si= findsinfo(st);
286 return si->string;
287}
288
289const char *adns_errabbrev(adns_status st) {
86e7b8d9 290 const struct sinfo *si;
291
9da4a044 292 si= findsinfo(st);
293 return si->abbrev;
e576be50 294}
88372443 295
ac77ffc1 296
297#define STINFO(max) { adns_s_max_##max, #max }
298
299static const struct stinfo {
300 adns_status stmax;
301 const char *abbrev;
302} stinfos[]= {
303 { adns_s_ok, "ok" },
304 STINFO( localfail ),
305 STINFO( remotefail ),
306 STINFO( tempfail ),
307 STINFO( misconfig ),
308 STINFO( misquery ),
309 STINFO( permfail )
310};
311
312static int sti_compar(const void *key, const void *elem) {
313 const adns_status *st= key;
314 const struct stinfo *sti= elem;
315
316 adns_status here, min, max;
317
318 here= *st;
319 min= (sti==stinfos) ? 0 : sti[-1].stmax+1;
320 max= sti->stmax;
321
322 return here < min ? -1 : here > max ? 1 : 0;
323}
324
325const char *adns_errtypeabbrev(adns_status st) {
326 const struct stinfo *sti;
327
609133ee 328 sti= bsearch(&st,stinfos, sizeof(stinfos)/sizeof(*stinfos),
329 sizeof(*stinfos), sti_compar);
ac77ffc1 330 return sti->abbrev;
331}
332
333
88372443 334void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
09957b1c 335 int (*needswap)(void *context, const void *a, const void *b),
336 void *context) {
88372443 337 byte *data= array;
338 int i, place;
339
340 for (i=0; i<nobjs; i++) {
09957b1c 341 for (place= i;
342 place>0 && needswap(context, data + (place-1)*sz, data + i*sz);
343 place--);
88372443 344 if (place != i) {
345 memcpy(tempbuf, data + i*sz, sz);
346 memmove(data + (place+1)*sz, data + place*sz, (i-place)*sz);
347 memcpy(data + place*sz, tempbuf, sz);
348 }
349 }
350}
ac868fa8 351
352/* SIGPIPE protection. */
353
354void adns__sigpipe_protect(adns_state ads) {
355 sigset_t toblock;
356 struct sigaction sa;
357 int r;
358
359 if (ads->iflags & adns_if_nosigpipe) return;
360
361 sigfillset(&toblock);
362 sigdelset(&toblock,SIGPIPE);
363
364 sa.sa_handler= SIG_IGN;
365 sigfillset(&sa.sa_mask);
366 sa.sa_flags= 0;
367
368 r= sigprocmask(SIG_SETMASK,&toblock,&ads->stdsigmask); assert(!r);
369 r= sigaction(SIGPIPE,&sa,&ads->stdsigpipe); assert(!r);
370}
371
372void adns__sigpipe_unprotect(adns_state ads) {
373 int r;
374
375 if (ads->iflags & adns_if_nosigpipe) return;
376
377 r= sigaction(SIGPIPE,&ads->stdsigpipe,0); assert(!r);
378 r= sigprocmask(SIG_SETMASK,&ads->stdsigmask,0); assert(!r);
379}