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