ReactOS 0.4.16-dev-340-g0540c21
adnsresfilter.c
Go to the documentation of this file.
1/*
2 * adnsresfilter.c
3 * - filter which does resolving, not part of the library
4 */
5/*
6 * This file is
7 * Copyright (C) 1999-2000 Ian Jackson <ian@davenant.greenend.org.uk>
8 *
9 * It is part of adns, which is
10 * Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk>
11 * Copyright (C) 1999-2000 Tony Finch <dot@dotat.at>
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
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <errno.h>
32#include <search.h>
33#include <assert.h>
34#include <ctype.h>
35
36#include <sys/types.h>
37#include <unistd.h>
38#include <fcntl.h>
39
40#include "config.h"
41#include "adns.h"
42#include "dlist.h"
43#include "tvarith.h"
44#include "client.h"
45
46#ifdef ADNS_REGRESS_TEST
47# include "hredirect.h"
48#endif
49
52 void *buffer;
53 char *textp;
56 struct treething *addr;
57};
58
59static int bracket, forever, address;
60static unsigned long timeout= 1000;
63static const char *config_text;
64
65static int outblocked, inputeof;
66static struct { struct outqueuenode *head, *tail; } outqueue;
68
69static struct sockaddr_in sa;
71
72static char addrtextbuf[14];
73static int cbyte, inbyte, inbuf;
74static unsigned char bytes[4];
75static struct timeval printbefore;
76
77struct treething {
78 unsigned char bytes[4];
81};
82
83static struct treething *newthing;
84static void *treeroot;
85
86static int nonblock(int fd, int isnonblock) {
87 int r;
88
89 r= fcntl(fd,F_GETFL);
90 if (r==-1) return -1;
91 r= fcntl(fd,F_SETFL, isnonblock ? r|O_NONBLOCK : r&~O_NONBLOCK);
92 if (r==-1) return -1;
93 return 0;
94}
95
96void quitnow(int exitstatus) {
97 nonblock(0,0);
98 nonblock(1,0);
99 exit(exitstatus);
100}
101
102static void sysfail(const char *what) NONRETURNING;
103static void sysfail(const char *what) {
104 fprintf(stderr,"adnsresfilter: system call failed: %s: %s\n",what,strerror(errno));
105 quitnow(2);
106}
107
108static void *xmalloc(size_t sz) {
109 void *r;
110 r= malloc(sz); if (r) return r;
111 sysfail("malloc");
112}
113
114static void outputerr(void) NONRETURNING;
115static void outputerr(void) { sysfail("write to stdout"); }
116
117static void usage(void) {
118 if (printf("usage: adnsresfilter [<options ...>]\n"
119 " adnsresfilter -h|--help | --version\n"
120 "options: -t<milliseconds>|--timeout <milliseconds>\n"
121 " -w|--wait (always wait for queries to time out or fail)\n"
122 " -b|--brackets (require [...] around IP addresses)\n"
123 " -a|--address (always include [address] in output)\n"
124 " -u|--unchecked (do not forward map for checking)\n"
125 " --config <text> (use this instead of resolv.conf)\n"
126 " --debug (turn on adns resolver debugging)\n"
127 "Timeout is the maximum amount to delay any particular bit of output for.\n"
128 "Lookups will go on in the background. Default timeout = 1000 (ms).\n")
129 == EOF) outputerr();
130 if (fflush(stdout)) sysfail("flush stdout");
131}
132
133static void usageerr(const char *why) NONRETURNING;
134static void usageerr(const char *why) {
135 fprintf(stderr,"adnsresfilter: bad usage: %s\n",why);
136 usage();
137 quitnow(1);
138}
139
140static void adnsfail(const char *what, int e) NONRETURNING;
141static void adnsfail(const char *what, int e) {
142 fprintf(stderr,"adnsresfilter: adns call failed: %s: %s\n",what,strerror(e));
143 quitnow(2);
144}
145
146static void settimeout(const char *arg) {
147 char *ep;
148 timeout= strtoul(arg,&ep,0);
149 if (*ep) usageerr("invalid timeout");
150}
151
152static void parseargs(const char *const *argv) {
153 const char *arg;
154 int c;
155
156 while ((arg= *++argv)) {
157 if (arg[0] != '-') usageerr("no non-option arguments are allowed");
158 if (arg[1] == '-') {
159 if (!strcmp(arg,"--timeout")) {
160 if (!(arg= *++argv)) usageerr("--timeout needs a value");
162 forever= 0;
163 } else if (!strcmp(arg,"--wait")) {
164 forever= 1;
165 } else if (!strcmp(arg,"--brackets")) {
166 bracket= 1;
167 } else if (!strcmp(arg,"--address")) {
168 address= 1;
169 } else if (!strcmp(arg,"--unchecked")) {
171 } else if (!strcmp(arg,"--config")) {
172 if (!(arg= *++argv)) usageerr("--config needs a value");
174 } else if (!strcmp(arg,"--debug")) {
176 } else if (!strcmp(arg,"--help")) {
177 usage(); quitnow(0);
178 } else if (!strcmp(arg,"--version")) {
179 VERSION_PRINT_QUIT("adnsresfilter"); quitnow(0);
180 } else {
181 usageerr("unknown long option");
182 }
183 } else {
184 while ((c= *++arg)) {
185 switch (c) {
186 case 't':
187 if (*++arg) settimeout(arg);
188 else if ((arg= *++argv)) settimeout(arg);
189 else usageerr("-t needs a value");
190 forever= 0;
191 arg= "\0";
192 break;
193 case 'w':
194 forever= 1;
195 break;
196 case 'b':
197 bracket= 1;
198 break;
199 case 'a':
200 address= 1;
201 break;
202 case 'u':
204 break;
205 case 'h':
206 usage();
207 quitnow(0);
208 default:
209 usageerr("unknown short option");
210 }
211 }
212 }
213 }
214}
215
216static void queueoutchar(int c) {
217 struct outqueuenode *entry;
218
219 entry= outqueue.tail;
220 if (!entry || entry->addr || entry->textlen >= peroutqueuenode) {
221 peroutqueuenode= !peroutqueuenode || !entry || entry->addr ? 128 :
222 peroutqueuenode >= 1024 ? 4096 : peroutqueuenode<<2;
223 entry= xmalloc(sizeof(*entry));
224 entry->buffer= xmalloc(peroutqueuenode);
225 entry->textp= entry->buffer;
226 entry->textlen= 0;
227 entry->addr= 0;
229 outqueuelen++;
230 }
231 entry->textp[entry->textlen++]= c;
232}
233
234static void queueoutstr(const char *str, int len) {
235 while (len-- > 0) queueoutchar(*str++);
236}
237
238static void writestdout(struct outqueuenode *entry) {
239 int r;
240
241 while (entry->textlen) {
242 r= write(1, entry->textp, entry->textlen);
243 if (r < 0) {
244 if (errno == EINTR) continue;
245 if (errno == EAGAIN) { outblocked= 1; break; }
246 sysfail("write stdout");
247 }
248 assert(r <= entry->textlen);
249 entry->textp += r;
250 entry->textlen -= r;
251 }
252 if (!entry->textlen) {
254 free(entry->buffer);
255 free(entry);
256 outqueuelen--;
257 }
258}
259
261 char *name, *newbuf;
262 int namelen, newlen;
263
264 name= entry->addr->ans->rrs.str[0];
266 if (!address) {
267 free(entry->buffer);
268 entry->buffer= 0;
269 entry->textp= name;
270 entry->textlen= namelen;
271 } else {
272 newlen= entry->textlen + namelen + (bracket ? 0 : 2);
273 newbuf= xmalloc(newlen + 1);
274 sprintf(newbuf, bracket ? "%s%.*s" : "%s[%.*s]", name, entry->textlen, entry->textp);
275 free(entry->buffer);
276 entry->buffer= entry->textp= newbuf;
277 entry->textlen= newlen;
278 }
279}
280
281static void checkadnsqueries(void) {
282 adns_query qu;
283 adns_answer *ans;
284 void *context;
285 struct treething *foundthing;
286 int r;
287
288 for (;;) {
289 qu= 0; context= 0; ans= 0;
291 if (r == ESRCH || r == EAGAIN) break;
292 assert(!r);
293 foundthing= context;
294 foundthing->ans= ans;
295 foundthing->qu= 0;
296 }
297}
298
299static void restartbuf(void) {
301 inbuf= 0;
302}
303
304static int comparer(const void *a, const void *b) {
305 return memcmp(a,b,4);
306}
307
308static void procaddr(void) {
309 struct treething *foundthing;
310 void **searchfound;
311 struct outqueuenode *entry;
312 int r;
313
314 if (!newthing) {
315 newthing= xmalloc(sizeof(struct treething));
316 newthing->qu= 0;
317 newthing->ans= 0;
318 }
319
320 memcpy(newthing->bytes,bytes,4);
321 searchfound= tsearch(newthing,&treeroot,comparer);
322 if (!searchfound) sysfail("tsearch");
323 foundthing= *searchfound;
324
325 if (foundthing == newthing) {
326 newthing= 0;
327 memcpy(&sa.sin_addr,bytes,4);
328 r= adns_submit_reverse(ads, (const struct sockaddr*)&sa,
329 rrt,0,foundthing,&foundthing->qu);
330 if (r) adnsfail("submit",r);
331 }
332 entry= xmalloc(sizeof(*entry));
333 entry->buffer= xmalloc(inbuf);
334 entry->textp= entry->buffer;
336 entry->textlen= inbuf;
337 entry->addr= foundthing;
338 entry->printbefore= printbefore;
340 outqueuelen++;
341 inbuf= 0;
342 cbyte= -1;
343}
344
345static void startaddr(void) {
346 bytes[cbyte=0]= 0;
347 inbyte= 0;
348}
349
350static void readstdin(void) {
351 char readbuf[512], *p;
352 int r, c, nbyte;
353
354 while ((r= read(0,readbuf,sizeof(readbuf))) <= 0) {
355 if (r == 0) { inputeof= 1; return; }
356 if (r == EAGAIN) return;
357 if (r != EINTR) sysfail("read stdin");
358 }
359 for (p=readbuf; r>0; r--,p++) {
360 c= *p;
361 if (cbyte==-1 && bracket && c=='[') {
362 addrtextbuf[inbuf++]= c;
363 startaddr();
364 } else if (cbyte==-1 && !bracket && !isalnum(c)) {
366 startaddr();
367 } else if (cbyte>=0 && inbyte<3 && c>='0' && c<='9' &&
368 (nbyte= bytes[cbyte]*10 + (c-'0')) <= 255) {
369 bytes[cbyte]= nbyte;
370 addrtextbuf[inbuf++]= c;
371 inbyte++;
372 } else if (cbyte>=0 && cbyte<3 && inbyte>0 && c=='.') {
373 bytes[++cbyte]= 0;
374 addrtextbuf[inbuf++]= c;
375 inbyte= 0;
376 } else if (cbyte==3 && inbyte>0 && bracket && c==']') {
377 addrtextbuf[inbuf++]= c;
378 procaddr();
379 } else if (cbyte==3 && inbyte>0 && !bracket && !isalnum(c)) {
380 procaddr();
382 startaddr();
383 } else {
384 restartbuf();
386 cbyte= -1;
387 if (!bracket && !isalnum(c)) startaddr();
388 }
389 }
390}
391
392static void startup(void) {
393 int r;
394
395 if (nonblock(0,1)) sysfail("set stdin to nonblocking mode");
396 if (nonblock(1,1)) sysfail("set stdout to nonblocking mode");
397 memset(&sa,0,sizeof(sa));
398 sa.sin_family= AF_INET;
399 if (config_text) {
401 } else {
403 }
404 if (r) adnsfail("init",r);
405 cbyte= -1;
406 inbyte= -1;
407 inbuf= 0;
408 if (!bracket) startaddr();
409}
410
411int main(int argc, const char *const *argv) {
412 int r, maxfd;
413 fd_set readfds, writefds, exceptfds;
414 struct outqueuenode *entry;
415 struct timeval *tv, tvbuf, now;
416
418 startup();
419
420 while (!inputeof || outqueue.head) {
421 maxfd= 2;
422 tv= 0;
423 FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
424 if ((entry= outqueue.head) && !outblocked) {
425 if (!entry->addr) {
427 continue;
428 }
429 if (entry->addr->ans) {
430 if (entry->addr->ans->nrrs)
432 entry->addr= 0;
433 continue;
434 }
435 r= gettimeofday(&now,0); if (r) sysfail("gettimeofday");
436 if (forever) {
437 tv= 0;
438 } else if (!timercmp(&now,&entry->printbefore,<)) {
439 entry->addr= 0;
440 continue;
441 } else {
442 tvbuf.tv_sec= entry->printbefore.tv_sec - now.tv_sec - 1;
443 tvbuf.tv_usec= entry->printbefore.tv_usec - now.tv_usec + 1000000;
444 tvbuf.tv_sec += tvbuf.tv_usec / 1000000;
445 tvbuf.tv_usec %= 1000000;
446 tv= &tvbuf;
447 }
448 adns_beforeselect(ads,&maxfd,&readfds,&writefds,&exceptfds,
449 &tv,&tvbuf,&now);
450 }
451 if (outblocked) FD_SET(1,&writefds);
452 if (!inputeof && outqueuelen<1024) FD_SET(0,&readfds);
453
455 r= select(maxfd,&readfds,&writefds,&exceptfds,tv);
457 if (r < 0) { if (r == EINTR) continue; else sysfail("select"); }
458
459 r= gettimeofday(&now,0); if (r) sysfail("gettimeofday");
460 adns_afterselect(ads,maxfd,&readfds,&writefds,&exceptfds,&now);
462
463 if (FD_ISSET(0,&readfds)) {
464 if (!forever) {
467 }
468 readstdin();
469 } else if (FD_ISSET(1,&writefds)) {
470 outblocked= 0;
471 }
472 }
473 if (nonblock(0,0)) sysfail("un-nonblock stdin");
474 if (nonblock(1,0)) sysfail("un-nonblock stdout");
476 exit(0);
477}
static int argc
Definition: ServiceArgs.c:12
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define EINTR
Definition: acclib.h:80
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define EAGAIN
Definition: acclib.h:83
#define read
Definition: acwin.h:96
#define write
Definition: acwin.h:97
adns_rrtype
Definition: adns.h:113
@ adns_r_ptr_raw
Definition: adns.h:130
@ adns_r_ptr
Definition: adns.h:131
ADNS_API void adns_finish(adns_state ads)
Definition: setup.c:650
ADNS_API void adns_beforeselect(adns_state ads, int *maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval **tv_mod, struct timeval *tv_buf, const struct timeval *now)
Definition: event.c:562
ADNS_API int adns_check(adns_state ads, adns_query *query_io, adns_answer **answer_r, void **context_r)
Definition: event.c:731
ADNS_API int adns_init(adns_state *newstate_r, adns_initflags flags, FILE *diagfile)
Definition: setup.c:568
adns_initflags
Definition: adns.h:87
@ adns_if_debug
Definition: adns.h:91
ADNS_API void adns_afterselect(adns_state ads, int maxfd, const fd_set *readfds, const fd_set *writefds, const fd_set *exceptfds, const struct timeval *now)
Definition: event.c:595
ADNS_API int adns_submit_reverse(adns_state ads, const struct sockaddr *addr, adns_rrtype type, adns_queryflags flags, void *context, adns_query *query_r)
Definition: query.c:304
ADNS_API int adns_init_strcfg(adns_state *newstate_r, adns_initflags flags, FILE *diagfile, const char *configtext)
Definition: setup.c:629
#define ADNS_CLEAR_ERRNO
Definition: adns_win32.h:108
#define gettimeofday(tv, tz)
Definition: adns_win32.h:159
#define ADNS_CAPTURE_ERRNO
Definition: adns_win32.h:107
static void startaddr(void)
static adns_initflags initflags
Definition: adnsresfilter.c:62
static void procaddr(void)
struct outqueuenode * tail
Definition: adnsresfilter.c:66
static void queueoutchar(int c)
static void * xmalloc(size_t sz)
static void writestdout(struct outqueuenode *entry)
static void usageerr(const char *why) NONRETURNING
static void outputerr(void)
static struct treething * newthing
Definition: adnsresfilter.c:83
static int address
Definition: adnsresfilter.c:59
static int nonblock(int fd, int isnonblock)
Definition: adnsresfilter.c:86
static const char * config_text
Definition: adnsresfilter.c:63
static struct timeval printbefore
Definition: adnsresfilter.c:75
static struct @4225 outqueue
static int comparer(const void *a, const void *b)
static void parseargs(const char *const *argv)
static int inbuf
Definition: adnsresfilter.c:73
static void replacetextwithname(struct outqueuenode *entry)
static char addrtextbuf[14]
Definition: adnsresfilter.c:72
static int inputeof
Definition: adnsresfilter.c:65
static int outblocked
Definition: adnsresfilter.c:65
static int bracket
Definition: adnsresfilter.c:59
static void settimeout(const char *arg)
static void queueoutstr(const char *str, int len)
static void sysfail(const char *what) NONRETURNING
static void * treeroot
Definition: adnsresfilter.c:84
static void startup(void)
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
static void readstdin(void)
static int forever
Definition: adnsresfilter.c:59
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
static void adnsfail(const char *what, int e) NONRETURNING
void quitnow(int exitstatus)
Definition: adnsresfilter.c:96
static adns_state ads
Definition: adnsresfilter.c:70
static void checkadnsqueries(void)
static int outqueuelen
Definition: adnsresfilter.c:67
static int peroutqueuenode
Definition: adnsresfilter.c:67
static void usage(void)
struct outqueuenode * head
Definition: adnsresfilter.c:66
static void restartbuf(void)
static int cbyte
Definition: adnsresfilter.c:73
static int inbyte
Definition: adnsresfilter.c:73
static adns_rrtype rrt
Definition: adnsresfilter.c:61
#define timercmp(tvp, uvp, cmp)
Definition: rdesktop.h:184
#define VERSION_PRINT_QUIT(program)
Definition: client.h:42
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
#define assert(x)
Definition: debug.h:53
#define ESRCH
Definition: errno.h:9
int main()
Definition: test.c:6
#define AF_INET
Definition: tcpip.h:117
time_t now
Definition: finger.c:65
#define printf
Definition: freeldr.h:97
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint address
Definition: glext.h:9393
const GLubyte * c
Definition: glext.h:8905
GLint namelen
Definition: glext.h:7232
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
#define stdout
Definition: stdio.h:99
#define EOF
Definition: stdio.h:24
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
uint32_t entry
Definition: isohybrid.c:63
#define e
Definition: ke_i.h:82
#define c
Definition: ke_i.h:80
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define O_NONBLOCK
Definition: port.h:158
const char * strerror(int err)
Definition: compat_str.c:23
#define argv
Definition: mplay32.c:18
const WCHAR * str
#define errno
Definition: errno.h:18
#define NONRETURNING
Definition: acconfig.h:94
#define LIST_UNLINK(list, node)
Definition: dlist.h:50
#define LIST_LINK_TAIL(list, node)
Definition: dlist.h:51
#define exit(n)
Definition: config.h:202
static int fd
Definition: io.c:51
#define memset(x, y, z)
Definition: compat.h:39
Definition: http.c:7252
Definition: winsock.h:66
Definition: name.c:39
struct treething * addr
Definition: adnsresfilter.c:56
struct timeval printbefore
Definition: adnsresfilter.c:55
struct outqueuenode * next
Definition: adnsresfilter.c:51
struct outqueuenode * back
Definition: adnsresfilter.c:51
Definition: dhcpd.h:245
unsigned long tv_sec
Definition: linux.h:1738
unsigned long tv_usec
Definition: linux.h:1739
adns_query qu
Definition: adnsresfilter.c:79
adns_answer * ans
Definition: adnsresfilter.c:80
unsigned char bytes[4]
Definition: adnsresfilter.c:78
static void timevaladd(struct timeval *tv_io, long ms)
Definition: tvarith.h:31
void * arg
Definition: msvc.h:10
#define FD_ISSET(fd, set)
Definition: winsock.h:100
#define FD_ZERO(set)
Definition: winsock.h:96
#define FD_SET(fd, set)
Definition: winsock.h:89