ReactOS  0.4.14-dev-317-g96040ec
adnslogres.c
Go to the documentation of this file.
1 /*
2  * adnslogres.c
3  * - a replacement for the Apache logresolve program using adns
4  */
5 /*
6  * This file is
7  * Copyright (C) 1999-2000 Tony Finch <dot@dotat.at>
8  * Copyright (C) 1999-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  * This version was originally supplied by Tony Finch, but has been
29  * modified by Ian Jackson as it was incorporated into adns and
30  * subsequently.
31  */
32 
33 #ifdef ADNS_JGAA_WIN32
34 # include "adns_win32.h"
35 # include "getopt.h"
36 #else
37 # include <sys/types.h>
38 # include <sys/time.h>
39 # include <unistd.h>
40 # include <string.h>
41 # include <stdlib.h>
42 # include <stdio.h>
43 # include <ctype.h>
44 # include <errno.h>
45 # include <stdarg.h>
46 #endif
47 
48 #include "config.h"
49 #include "adns.h"
50 #include "client.h"
51 
52 #ifdef ADNS_REGRESS_TEST
53 # include "hredirect.h"
54 #endif
55 
56 /* maximum number of concurrent DNS queries */
57 #define MAXMAXPENDING 64000
58 #define DEFMAXPENDING 2000
59 
60 /* maximum length of a line */
61 #define MAXLINE 1024
62 
63 /* option flags */
64 #define OPT_DEBUG 1
65 
66 #ifdef HAVE_POLL
67 # define OPT_POLL 2
68 #endif
69 
70 static const char *const progname= "adnslogres";
71 static const char *config_text;
72 
73 #define guard_null(str) ((str) ? (str) : "")
74 
75 #define sensible_ctype(type,ch) (type((unsigned char)(ch)))
76  /* isfoo() functions from ctype.h can't safely be fed char - blech ! */
77 
78 static void msg(const char *fmt, ...) {
79  va_list al;
80 
81  fprintf(stderr, "%s: ", progname);
82  va_start(al,fmt);
83  vfprintf(stderr, fmt, al);
84  va_end(al);
85  fputc('\n',stderr);
86 }
87 
88 static void aargh(const char *cause) {
89  const char *why = strerror(errno);
90  if (!why) why = "Unknown error";
91  msg("%s: %s (%d)", cause, why, errno);
92  exit(1);
93 }
94 
95 /*
96  * Parse the IP address and convert to a reverse domain name.
97  */
98 static char *ipaddr2domain(char *start, char **addr, char **rest) {
99  static char buf[30]; /* "123.123.123.123.in-addr.arpa.\0" */
100  char *ptrs[5];
101  int i;
102 
103  ptrs[0]= start;
104 retry:
105  while (!sensible_ctype(isdigit,*ptrs[0]))
106  if (!*ptrs[0]++) {
107  strcpy(buf, "invalid.");
108  *addr= *rest= NULL;
109  return buf;
110  }
111  for (i= 1; i < 5; i++) {
112  ptrs[i]= ptrs[i-1];
113  while (sensible_ctype(isdigit,*ptrs[i]++));
114  if ((i == 4 && !sensible_ctype(isspace,ptrs[i][-1])) ||
115  (i != 4 && ptrs[i][-1] != '.') ||
116  (ptrs[i]-ptrs[i-1] > 4)) {
117  ptrs[0]= ptrs[i]-1;
118  goto retry;
119  }
120  }
121  sprintf(buf, "%.*s.%.*s.%.*s.%.*s.in-addr.arpa.",
122  ptrs[4]-ptrs[3]-1, ptrs[3],
123  ptrs[3]-ptrs[2]-1, ptrs[2],
124  ptrs[2]-ptrs[1]-1, ptrs[1],
125  ptrs[1]-ptrs[0]-1, ptrs[0]);
126  *addr= ptrs[0];
127  *rest= ptrs[4]-1;
128  return buf;
129 }
130 
131 static void printline(FILE *outf, char *start, char *addr, char *rest, char *domain) {
132  if (domain)
133  fprintf(outf, "%.*s%s%s", addr - start, start, domain, rest);
134  else
135  fputs(start, outf);
136  if (ferror(outf)) aargh("write output");
137 }
138 
139 typedef struct logline {
140  struct logline *next;
141  char *start, *addr, *rest;
143 } logline;
144 
145 static logline *readline(FILE *inf, adns_state adns, int opts) {
146  static char buf[MAXLINE];
147  char *str;
148  logline *line;
149 
150  if (fgets(buf, MAXLINE, inf)) {
151  str= malloc(sizeof(*line) + strlen(buf) + 1);
152  if (!str) aargh("malloc");
153  line= (logline*)str;
154  line->next= NULL;
155  line->start= str+sizeof(logline);
156  strcpy(line->start, buf);
157  str= ipaddr2domain(line->start, &line->addr, &line->rest);
158  if (opts & OPT_DEBUG)
159  msg("submitting %.*s -> %s", line->rest-line->addr, guard_null(line->addr), str);
160  if (adns_submit(adns, str, adns_r_ptr,
162  NULL, &line->query))
163  aargh("adns_submit");
164  return line;
165  }
166  if (!feof(inf))
167  aargh("fgets");
168  return NULL;
169 }
170 
171 static void proclog(FILE *inf, FILE *outf, int maxpending, int opts) {
172  int eof, err, len;
173  adns_state adns;
174  adns_answer *answer;
175  logline *head, *tail, *line;
177 
178  initflags= (opts & OPT_DEBUG) ? adns_if_debug : 0;
179  if (config_text) {
181  } else {
182  errno= adns_init(&adns, initflags, 0);
183  }
184  if (errno) aargh("adns_init");
185  head= tail= readline(inf, adns, opts);
186  len= 1; eof= 0;
187  while (head) {
188  while (head) {
189  if (opts & OPT_DEBUG)
190  msg("%d in queue; checking %.*s", len,
191  head->rest-head->addr, guard_null(head->addr));
192  if (eof || len >= maxpending) {
193 #ifdef HAVE_POLL
194  if (opts & OPT_POLL)
195  err= adns_wait_poll(adns, &head->query, &answer, NULL);
196  else
197 #endif
198  err= adns_wait(adns, &head->query, &answer, NULL);
199  } else {
200  err= adns_check(adns, &head->query, &answer, NULL);
201  }
202  if ((err == EAGAIN) || (EWOULDBLOCK == err)) break;
203  if (err) {
204  fprintf(stderr, "%s: adns_wait/check: %s", progname, strerror(err));
205  exit(1);
206  }
207  printline(outf, head->start, head->addr, head->rest,
208  answer->status == adns_s_ok ? *answer->rrs.str : NULL);
209  line= head; head= head->next;
210  free(line);
211  free(answer);
212  len--;
213  }
214  if (!eof) {
215  line= readline(inf, adns, opts);
216  if (line) {
217  if (!head) head= line;
218  else tail->next= line;
219  tail= line; len++;
220  } else {
221  eof= 1;
222  }
223  }
224  }
225  adns_finish(adns);
226 }
227 
228 static void printhelp(FILE *file) {
229  fputs("usage: adnslogres [<options>] [<logfile>]\n"
230  " adnslogres --version|--help\n"
231  "options: -c <concurrency> set max number of outstanding queries\n"
232 #ifdef HAVE_POLL
233  " -p use poll(2) instead of select(2)\n"
234 #endif
235  " -d turn on debugging\n"
236  " -C <config> use instead of contents of resolv.conf\n",
237  stdout);
238 }
239 
240 static void usage(void) {
241  printhelp(stderr);
242  exit(1);
243 }
244 
245 int main(int argc, char *argv[]) {
246  int c, opts, maxpending;
247  extern char *optarg;
248  FILE *inf;
249 
250  if (argv[1] && !strncmp(argv[1],"--",2)) {
251  if (!strcmp(argv[1],"--help")) {
252  printhelp(stdout);
253  } else if (!strcmp(argv[1],"--version")) {
254  fputs(VERSION_MESSAGE("adnslogres"),stdout);
255  } else {
256  usage();
257  }
258  if (ferror(stdout) || fclose(stdout)) { perror("stdout"); exit(1); }
259  exit(0);
260  }
261 
262  maxpending= DEFMAXPENDING;
263  opts= 0;
264  while ((c= getopt(argc, argv, "c:C:dp")) != -1)
265  switch (c) {
266  case 'c':
267  maxpending= atoi(optarg);
268  if (maxpending < 1 || maxpending > MAXMAXPENDING) {
269  fprintf(stderr, "%s: unfeasible concurrency %d\n", progname, maxpending);
270  exit(1);
271  }
272  break;
273  case 'C':
275  break;
276  case 'd':
277  opts|= OPT_DEBUG;
278  break;
279 #ifdef HAVE_POLL
280  case 'p':
281  opts|= OPT_POLL;
282  break;
283 #endif
284  default:
285  usage();
286  }
287 
288  argc-= optind;
289  argv+= optind;
290 
291  inf= NULL;
292  if (argc == 0)
293  inf= stdin;
294  else if (argc == 1)
295  inf= fopen(*argv, "r");
296  else
297  usage();
298 
299  if (!inf)
300  aargh("couldn't open input");
301 
302  proclog(inf, stdout, maxpending, opts);
303 
304  if (fclose(inf))
305  aargh("fclose input");
306  if (fclose(stdout))
307  aargh("fclose output");
308 
309  return 0;
310 }
adns_initflags
Definition: adns.h:87
static int argc
Definition: ServiceArgs.c:12
#define isspace(c)
Definition: acclib.h:69
_Check_return_ _CRTIMP int __cdecl ferror(_In_ FILE *_File)
_Check_return_opt_ _CRTIMP int __cdecl fputc(_In_ int _Ch, _Inout_ FILE *_File)
#define MAXLINE
Definition: adnslogres.c:61
struct outqueuenode * tail
Definition: adnsresfilter.c:66
#define sensible_ctype(type, ch)
Definition: adnslogres.c:75
struct outqueuenode * head
Definition: adnsresfilter.c:66
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static void msg(const char *fmt,...)
Definition: adnslogres.c:78
ADNS_API void adns_finish(adns_state ads)
Definition: setup.c:650
int optind
Definition: getopt.c:47
#define free
Definition: debug_ros.c:5
FILE * stdin
int errno
static logline * readline(FILE *inf, adns_state adns, int opts)
Definition: adnslogres.c:145
#define argv
Definition: mplay32.c:18
const char * strerror(int err)
Definition: compat_str.c:23
int main(int argc, char *argv[])
Definition: adnslogres.c:245
FILE * stdout
#define sprintf(buf, format,...)
Definition: sprintf.c:55
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ADNS_API int adns_wait_poll(adns_state ads, adns_query *query_io, adns_answer **answer_r, void **context_r)
#define va_end(ap)
Definition: acmsvcex.h:90
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
#define EWOULDBLOCK
Definition: errno.h:42
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
static void aargh(const char *cause)
Definition: adnslogres.c:88
Definition: parser.c:48
char * va_list
Definition: acmsvcex.h:78
Definition: arc.h:35
struct logline logline
#define guard_null(str)
Definition: adnslogres.c:73
#define isdigit(c)
Definition: acclib.h:68
ADNS_API int adns_init_strcfg(adns_state *newstate_r, adns_initflags flags, FILE *diagfile, const char *configtext)
Definition: setup.c:629
char ** str
Definition: adns.h:320
_Check_return_ _CRTIMP int __cdecl feof(_In_ FILE *_File)
static void printhelp(FILE *file)
Definition: adnslogres.c:228
char * start
Definition: adnslogres.c:141
adns_query query
Definition: adnslogres.c:142
#define MAXMAXPENDING
Definition: adnslogres.c:57
const GLubyte * c
Definition: glext.h:8905
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define VERSION_MESSAGE(program)
Definition: client.h:39
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: getopt.c:55
static const char * config_text
Definition: adnslogres.c:71
adns_status status
Definition: adns.h:311
char line[200]
Definition: main.c:97
GLenum const GLvoid * addr
Definition: glext.h:9621
GLenum GLsizei len
Definition: glext.h:6722
#define DEFMAXPENDING
Definition: adnslogres.c:58
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
#define err(...)
_Check_return_ _CRTIMP int __cdecl __cdecl eof(_In_ int _FileHandle)
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
struct logline * next
Definition: adnslogres.c:140
ADNS_API int adns_init(adns_state *newstate_r, adns_initflags flags, FILE *diagfile)
Definition: setup.c:568
ADNS_API int adns_submit(adns_state ads, const char *owner, adns_rrtype type, adns_queryflags flags, void *context, adns_query *query_r)
Definition: query.c:204
GLuint start
Definition: gl.h:1545
const char * optarg
Definition: getopt.c:49
static void usage(void)
Definition: adnslogres.c:240
#define va_start(ap, A)
Definition: acmsvcex.h:91
char * addr
Definition: adnslogres.c:141
static adns_initflags initflags
Definition: adnsresfilter.c:62
ADNS_API int adns_check(adns_state ads, adns_query *query_io, adns_answer **answer_r, void **context_r)
Definition: event.c:731
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * rest
Definition: adnslogres.c:141
#define c
Definition: ke_i.h:80
FILE * stderr
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
static void proclog(FILE *inf, FILE *outf, int maxpending, int opts)
Definition: adnslogres.c:171
#define malloc
Definition: debug_ros.c:4
static const char *const progname
Definition: adnslogres.c:70
void exit(int exitcode)
Definition: _exit.c:33
_Check_return_opt_ _CRTIMP int __cdecl vfprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format, va_list _ArgList)
ADNS_API int adns_wait(adns_state ads, adns_query *query_io, adns_answer **answer_r, void **context_r)
Definition: event.c:696
static char * ipaddr2domain(char *start, char **addr, char **rest)
Definition: adnslogres.c:98
#define OPT_DEBUG
Definition: adnslogres.c:64
fa outf
Definition: format.c:301
union adns_answer::@3855 rrs
Definition: dsound.c:943
_Check_return_opt_ _CRTIMP int __cdecl fputs(_In_z_ const char *_Str, _Inout_ FILE *_File)
static void printline(FILE *outf, char *start, char *addr, char *rest, char *domain)
Definition: adnslogres.c:131
Definition: fci.c:126