Use struct sockaddr in several places; distinguish various places where
[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>
25
26#include <arpa/inet.h>
27
e576be50 28#include "internal.h"
29
30/* Core diagnostic functions */
31
32void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
3955725c 33 int serv, adns_query qu, const char *fmt, va_list al) {
e576be50 34 const char *bef, *aft;
35 vbuf vb;
36 if (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))) return;
37
38 fprintf(stderr,"adns%s: ",pfx);
39
40 vfprintf(stderr,fmt,al);
41
42 bef= " (";
43 aft= "\n";
44
45 if (qu && qu->query_dgram) {
46 adns__vbuf_init(&vb);
47 fprintf(stderr,"%sQNAME=%s, QTYPE=%s",
48 bef,
828d89bd 49 adns__diag_domain(qu->ads,-1,0, &vb,
3955725c 50 qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
86e7b8d9 51 qu->typei ? qu->typei->rrtname : "<unknown>");
52 if (qu->typei && qu->typei->fmtname)
53 fprintf(stderr,"(%s)",qu->typei->fmtname);
e576be50 54 bef=", "; aft=")\n";
55 }
56
57 if (serv>=0) {
58 fprintf(stderr,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
59 bef=", "; aft=")\n";
60 }
61
62 fputs(aft,stderr);
63}
64
65void adns__debug(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
66 va_list al;
67
68 va_start(al,fmt);
69 adns__vdiag(ads," debug",0,serv,qu,fmt,al);
70 va_end(al);
71}
72
73void adns__warn(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
74 va_list al;
75
76 va_start(al,fmt);
77 adns__vdiag(ads," warning",adns_if_noerrprint|adns_if_noserverwarn,serv,qu,fmt,al);
78 va_end(al);
79}
80
81void adns__diag(adns_state ads, int serv, adns_query qu, const char *fmt, ...) {
82 va_list al;
83
84 va_start(al,fmt);
85 adns__vdiag(ads,"",adns_if_noerrprint,serv,qu,fmt,al);
86 va_end(al);
87}
88
89/* vbuf functions */
90
91void adns__vbuf_init(vbuf *vb) {
92 vb->used= vb->avail= 0; vb->buf= 0;
93}
94
95int adns__vbuf_ensure(vbuf *vb, int want) {
96 void *nb;
97
98 if (vb->avail >= want) return 1;
99 nb= realloc(vb->buf,want); if (!nb) return 0;
100 vb->buf= nb;
101 vb->avail= want;
102 return 1;
103}
104
105void adns__vbuf_appendq(vbuf *vb, const byte *data, int len) {
106 memcpy(vb->buf+vb->used,data,len);
107 vb->used+= len;
108}
109
110int adns__vbuf_append(vbuf *vb, const byte *data, int len) {
111 int newlen;
112 void *nb;
113
114 newlen= vb->used+len;
115 if (vb->avail < newlen) {
a49a6d7b 116 if (newlen<20) newlen= 20;
e576be50 117 newlen <<= 1;
118 nb= realloc(vb->buf,newlen);
a49a6d7b 119 if (!nb) { newlen= vb->used+len; nb= realloc(vb->buf,newlen); }
e576be50 120 if (!nb) return 0;
121 vb->buf= nb;
122 vb->avail= newlen;
123 }
124 adns__vbuf_appendq(vb,data,len);
125 return 1;
126}
127
f759e52e 128int adns__vbuf_appendstr(vbuf *vb, const char *data) {
129 int l;
9557e604 130 l= strlen(data);
f759e52e 131 return adns__vbuf_append(vb,data,l);
132}
133
a49a6d7b 134void adns__vbuf_free(vbuf *vb) {
135 free(vb->buf);
136 adns__vbuf_init(vb);
137}
138
e576be50 139/* Additional diagnostic functions */
140
828d89bd 141const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
142 vbuf *vb, const byte *dgram, int dglen, int cbyte) {
e576be50 143 adns_status st;
144
828d89bd 145 st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen);
3955725c 146 if (st == adns_s_nolocalmem) {
e576be50 147 return "<cannot report domain... out of memory>";
148 }
149 if (st) {
150 vb->used= 0;
151 if (!(adns__vbuf_appendstr(vb,"<bad format... ") &&
152 adns__vbuf_appendstr(vb,adns_strerror(st)) &&
153 adns__vbuf_appendstr(vb,">") &&
154 adns__vbuf_append(vb,"",1))) {
155 return "<cannot report bad format... out of memory>";
156 }
157 }
3955725c 158 if (!vb->used) {
e576be50 159 adns__vbuf_appendstr(vb,"<truncated ...>");
160 adns__vbuf_append(vb,"",1);
161 }
162 return vb->buf;
163}
86e7b8d9 164
165adns_status adns_rr_info(adns_rrtype type,
166 const char **rrtname_r, const char **fmtname_r,
167 int *len_r,
168 const void *datap, char **data_r) {
169 const typeinfo *typei;
170 vbuf vb;
171 adns_status st;
172
173 typei= adns__findtype(type);
174 if (!typei) return adns_s_notimplemented;
175
176 if (rrtname_r) *rrtname_r= typei->rrtname;
177 if (fmtname_r) *fmtname_r= typei->fmtname;
178 if (len_r) *len_r= typei->rrsz;
179
180 if (!datap) return adns_s_ok;
181
182 adns__vbuf_init(&vb);
183 st= typei->convstring(&vb,datap);
184 if (st) goto x_freevb;
185 if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nolocalmem; goto x_freevb; }
186 assert(strlen(vb.buf) == vb.used-1);
187 *data_r= realloc(vb.buf,vb.used);
188 if (!*data_r) *data_r= vb.buf;
189 return adns_s_ok;
190
191 x_freevb:
192 adns__vbuf_free(&vb);
193 return st;
194}
195
196#define SINFO(n,s) { adns_s_##n, s }
197
198static const struct sinfo {
199 adns_status st;
200 const char *string;
201} sinfos[]= {
ffbda80c 202 SINFO( ok, "OK" ),
203 SINFO( timeout, "Timed out" ),
204 SINFO( nolocalmem, "Out of memory" ),
205 SINFO( allservfail, "No working nameservers" ),
206 SINFO( servfail, "Nameserver failure" ),
207 SINFO( notimplemented, "Query not implemented" ),
208 SINFO( refused, "Refused by nameserver" ),
209 SINFO( reasonunknown, "Reason unknown" ),
210 SINFO( norecurse, "Recursion denied by nameserver" ),
211 SINFO( serverfaulty, "Nameserver sent bad data" ),
212 SINFO( unknownreply, "Reply from nameserver not understood" ),
213 SINFO( invaliddata, "Invalid data" ),
214 SINFO( inconsistent, "Inconsistent data" ),
215 SINFO( cname, "RR refers to an alias" ),
216 SINFO( invalidanswerdomain, "Received syntactically invalid domain" ),
217 SINFO( nxdomain, "No such domain" ),
218 SINFO( nodata, "No such data" ),
219 SINFO( invalidquerydomain, "Domain syntactically invalid" ),
220 SINFO( domaintoolong, "Domain name too long" )
86e7b8d9 221};
222
223static int si_compar(const void *key, const void *elem) {
224 const adns_status *st= key;
225 const struct sinfo *si= elem;
226
227 return *st < si->st ? -1 : *st > si->st ? 1 : 0;
228}
229
e576be50 230const char *adns_strerror(adns_status st) {
231 static char buf[100];
86e7b8d9 232
233 const struct sinfo *si;
234
235 si= bsearch(&st,sinfos,sizeof(sinfos)/sizeof(*si),sizeof(*si),si_compar);
236 if (si) return si->string;
237
e576be50 238 snprintf(buf,sizeof(buf),"code %d",st);
239 return buf;
240}