Reorganise types.c
[adns] / src / general.c
CommitLineData
98db6da3 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
11c8bf9b 24#include <stdlib.h>
f318f883 25#include <string.h>
11c8bf9b 26
27#include <arpa/inet.h>
28
98db6da3 29#include "internal.h"
30
31/* Core diagnostic functions */
32
33void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
11c8bf9b 34 int serv, adns_query qu, const char *fmt, va_list al) {
98db6da3 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,
cd363ffd 50 adns__diag_domain(qu->ads,-1,0, &vb,
11c8bf9b 51 qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
1e9efa71 52 qu->typei ? qu->typei->rrtname : "<unknown>");
53 if (qu->typei && qu->typei->fmtname)
54 fprintf(stderr,"(%s)",qu->typei->fmtname);
98db6da3 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) {
f47cdeec 117 if (newlen<20) newlen= 20;
98db6da3 118 newlen <<= 1;
119 nb= realloc(vb->buf,newlen);
f47cdeec 120 if (!nb) { newlen= vb->used+len; nb= realloc(vb->buf,newlen); }
98db6da3 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
c9afe7bb 129int adns__vbuf_appendstr(vbuf *vb, const char *data) {
130 int l;
9a2b67d4 131 l= strlen(data);
c9afe7bb 132 return adns__vbuf_append(vb,data,l);
133}
134
f47cdeec 135void adns__vbuf_free(vbuf *vb) {
136 free(vb->buf);
137 adns__vbuf_init(vb);
138}
139
98db6da3 140/* Additional diagnostic functions */
141
cd363ffd 142const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
143 vbuf *vb, const byte *dgram, int dglen, int cbyte) {
98db6da3 144 adns_status st;
145
cd363ffd 146 st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen);
11c8bf9b 147 if (st == adns_s_nolocalmem) {
98db6da3 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 }
11c8bf9b 159 if (!vb->used) {
98db6da3 160 adns__vbuf_appendstr(vb,"<truncated ...>");
161 adns__vbuf_append(vb,"",1);
162 }
163 return vb->buf;
164}
1e9efa71 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);
175 if (!typei) return adns_s_notimplemented;
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;
186 if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nolocalmem; 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;
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[]= {
cfdca685 203 SINFO( ok, "OK" ),
204 SINFO( timeout, "Timed out" ),
205 SINFO( nolocalmem, "Out of memory" ),
206 SINFO( allservfail, "No working nameservers" ),
207 SINFO( servfail, "Nameserver failure" ),
208 SINFO( notimplemented, "Query not implemented" ),
209 SINFO( refused, "Refused by nameserver" ),
210 SINFO( reasonunknown, "Reason unknown" ),
211 SINFO( norecurse, "Recursion denied by nameserver" ),
212 SINFO( serverfaulty, "Nameserver sent bad data" ),
213 SINFO( unknownreply, "Reply from nameserver not understood" ),
214 SINFO( invaliddata, "Invalid data" ),
215 SINFO( inconsistent, "Inconsistent data" ),
216 SINFO( cname, "RR refers to an alias" ),
217 SINFO( invalidanswerdomain, "Received syntactically invalid domain" ),
218 SINFO( nxdomain, "No such domain" ),
219 SINFO( nodata, "No such data" ),
220 SINFO( invalidquerydomain, "Domain syntactically invalid" ),
221 SINFO( domaintoolong, "Domain name too long" )
1e9efa71 222};
223
224static int si_compar(const void *key, const void *elem) {
225 const adns_status *st= key;
226 const struct sinfo *si= elem;
227
228 return *st < si->st ? -1 : *st > si->st ? 1 : 0;
229}
230
98db6da3 231const char *adns_strerror(adns_status st) {
232 static char buf[100];
1e9efa71 233
234 const struct sinfo *si;
235
236 si= bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*si),sizeof(*si),si_compar);
237 if (si) return si->string;
238
98db6da3 239 snprintf(buf,sizeof(buf),"code %d",st);
240 return buf;
241}
f318f883 242
243void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
244 int (*needswap)(const void *a, const void *b)) {
245 byte *data= array;
246 int i, place;
247
248 for (i=0; i<nobjs; i++) {
249 for (place= i; place>0 && needswap(data + (place-1)*sz, data + i*sz); place--);
250
251 if (place != i) {
252 memcpy(tempbuf, data + i*sz, sz);
253 memmove(data + (place+1)*sz, data + place*sz, (i-place)*sz);
254 memcpy(data + place*sz, tempbuf, sz);
255 }
256 }
257}