"Fossies" - the Fresh Open Source Software Archive 
Member "udns-0.4/rblcheck.c" (23 Jan 2014, 10173 Bytes) of package /linux/misc/dns/udns-0.4.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "rblcheck.c" see the
Fossies "Dox" file reference documentation.
1 /* rblcheck.c
2 dnsbl (rbl) checker application
3
4 Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
5 This file is part of UDNS library, an async DNS stub resolver.
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library, in file named COPYING.LGPL; if not,
19 write to the Free Software Foundation, Inc., 59 Temple Place,
20 Suite 330, Boston, MA 02111-1307 USA
21
22 */
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #ifdef WINDOWS
31 # include <winsock2.h>
32 #else
33 # include <unistd.h>
34 # include <sys/types.h>
35 # include <sys/socket.h>
36 # include <netinet/in.h>
37 #endif
38 #include <time.h>
39 #include <errno.h>
40 #include <stdarg.h>
41 #include "udns.h"
42
43 #ifndef HAVE_GETOPT
44 # include "getopt.c"
45 #endif
46
47 static const char *version = "udns-rblcheck 0.4";
48 static char *progname;
49
50 static void error(int die, const char *fmt, ...) {
51 va_list ap;
52 fprintf(stderr, "%s: ", progname);
53 va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap);
54 putc('\n', stderr);
55 fflush(stderr);
56 if (die)
57 exit(1);
58 }
59
60 struct rblookup {
61 struct ipcheck *parent;
62 struct in_addr key;
63 const char *zone;
64 struct dns_rr_a4 *addr;
65 struct dns_rr_txt *txt;
66 };
67
68 struct ipcheck {
69 const char *name;
70 int naddr;
71 int listed;
72 struct rblookup *lookup;
73 };
74
75 #define notlisted ((void*)1)
76
77 static int nzones, nzalloc;
78 static const char **zones;
79
80 static int do_txt;
81 static int stopfirst;
82 static int verbose = 1;
83 /* verbosity level:
84 * <0 - only bare As/TXTs
85 * 0 - what RBL result
86 * 1(default) - what is listed by RBL: result
87 * 2 - what is[not ]listed by RBL: result, name lookups
88 */
89
90 static int listed;
91 static int failures;
92
93 static void *ecalloc(int size, int cnt) {
94 void *t = calloc(size, cnt);
95 if (!t)
96 error(1, "out of memory");
97 return t;
98 }
99
100 static void addzone(const char *zone) {
101 if (nzones >= nzalloc) {
102 const char **zs = (const char**)ecalloc(sizeof(char*), (nzalloc += 16));
103 if (zones) {
104 memcpy(zs, zones, nzones * sizeof(char*));
105 free(zones);
106 }
107 zones = zs;
108 }
109 zones[nzones++] = zone;
110 }
111
112 static int addzonefile(const char *fname) {
113 FILE *f = fopen(fname, "r");
114 char linebuf[2048];
115 if (!f)
116 return 0;
117 while(fgets(linebuf, sizeof(linebuf), f)) {
118 char *p = linebuf, *e;
119 while(*p == ' ' || *p == '\t') ++p;
120 if (*p == '#' || *p == '\n') continue;
121 e = p;
122 while(*e && *e != ' ' && *e != '\t' && *e != '\n')
123 ++e;
124 *e++ = '\0';
125 p = memcpy(ecalloc(e - p, 1), p, e - p); // strdup
126 addzone(p);
127 }
128 fclose(f);
129 return 1;
130 }
131
132 static void dnserror(struct rblookup *ipl, const char *what) {
133 char buf[4*4];
134 error(0, "unable to %s for %s (%s): %s",
135 what, dns_ntop(AF_INET, &ipl->key, buf, sizeof(buf)),
136 ipl->zone, dns_strerror(dns_status(0)));
137 ++failures;
138 }
139
140 static void display_result(struct ipcheck *ipc) {
141 int j;
142 struct rblookup *l, *le;
143 char buf[4*4];
144 if (!ipc->naddr) return;
145 for (l = ipc->lookup, le = l + nzones * ipc->naddr; l < le; ++l) {
146 if (!l->addr) continue;
147 if (verbose < 2 && l->addr == notlisted) continue;
148 if (verbose >= 0) {
149 dns_ntop(AF_INET, &l->key, buf, sizeof(buf));
150 if (ipc->name) printf("%s[%s]", ipc->name, buf);
151 else printf("%s", buf);
152 }
153 if (l->addr == notlisted) {
154 printf(" is NOT listed by %s\n", l->zone);
155 continue;
156 }
157 else if (verbose >= 1)
158 printf(" is listed by %s: ", l->zone);
159 else if (verbose >= 0)
160 printf(" %s ", l->zone);
161 if (verbose >= 1 || !do_txt)
162 for (j = 0; j < l->addr->dnsa4_nrr; ++j)
163 printf("%s%s", j ? " " : "",
164 dns_ntop(AF_INET, &l->addr->dnsa4_addr[j], buf, sizeof(buf)));
165 if (!do_txt) ;
166 else if (l->txt) {
167 for(j = 0; j < l->txt->dnstxt_nrr; ++j) {
168 unsigned char *t = l->txt->dnstxt_txt[j].txt;
169 unsigned char *e = t + l->txt->dnstxt_txt[j].len;
170 printf("%s\"", verbose > 0 ? "\n\t" : j ? " " : "");
171 while(t < e) {
172 if (*t < ' ' || *t >= 127) printf("\\x%02x", *t);
173 else if (*t == '\\' || *t == '"') printf("\\%c", *t);
174 else putchar(*t);
175 ++t;
176 }
177 putchar('"');
178 }
179 free(l->txt);
180 }
181 else
182 printf("%s<no text available>", verbose > 0 ? "\n\t" : "");
183 free(l->addr);
184 putchar('\n');
185 }
186 free(ipc->lookup);
187 }
188
189 static void txtcb(struct dns_ctx *ctx, struct dns_rr_txt *r, void *data) {
190 struct rblookup *ipl = data;
191 if (r) {
192 ipl->txt = r;
193 ++ipl->parent->listed;
194 }
195 else if (dns_status(ctx) != DNS_E_NXDOMAIN)
196 dnserror(ipl, "lookup DNSBL TXT record");
197 }
198
199 static void a4cb(struct dns_ctx *ctx, struct dns_rr_a4 *r, void *data) {
200 struct rblookup *ipl = data;
201 if (r) {
202 ipl->addr = r;
203 ++listed;
204 if (do_txt) {
205 if (dns_submit_a4dnsbl_txt(0, &ipl->key, ipl->zone, txtcb, ipl))
206 return;
207 dnserror(ipl, "submit DNSBL TXT record");
208 }
209 ++ipl->parent->listed;
210 }
211 else if (dns_status(ctx) != DNS_E_NXDOMAIN)
212 dnserror(ipl, "lookup DNSBL A record");
213 else
214 ipl->addr = notlisted;
215 }
216
217 static int
218 submit_a_queries(struct ipcheck *ipc,
219 int naddr, const struct in_addr *addr) {
220 int z, a;
221 struct rblookup *rl = ecalloc(sizeof(*rl), nzones * naddr);
222 ipc->lookup = rl;
223 ipc->naddr = naddr;
224 for(a = 0; a < naddr; ++a) {
225 for(z = 0; z < nzones; ++z) {
226 rl->key = addr[a];
227 rl->zone = zones[z];
228 rl->parent = ipc;
229 if (!dns_submit_a4dnsbl(0, &rl->key, rl->zone, a4cb, rl))
230 dnserror(rl, "submit DNSBL A query");
231 ++rl;
232 }
233 }
234 return 0;
235 }
236
237 static void namecb(struct dns_ctx *ctx, struct dns_rr_a4 *rr, void *data) {
238 struct ipcheck *ipc = data;
239 if (rr) {
240 submit_a_queries(ipc, rr->dnsa4_nrr, rr->dnsa4_addr);
241 free(rr);
242 }
243 else {
244 error(0, "unable to lookup `%s': %s",
245 ipc->name, dns_strerror(dns_status(ctx)));
246 ++failures;
247 }
248 }
249
250 static int submit(struct ipcheck *ipc) {
251 struct in_addr addr;
252 if (dns_pton(AF_INET, ipc->name, &addr) > 0) {
253 submit_a_queries(ipc, 1, &addr);
254 ipc->name = NULL;
255 }
256 else if (!dns_submit_a4(0, ipc->name, 0, namecb, ipc)) {
257 error(0, "unable to submit name query for %s: %s\n",
258 ipc->name, dns_strerror(dns_status(0)));
259 ++failures;
260 }
261 return 0;
262 }
263
264 static void waitdns(struct ipcheck *ipc) {
265 struct timeval tv;
266 fd_set fds;
267 int c;
268 int fd = dns_sock(NULL);
269 time_t now = 0;
270 FD_ZERO(&fds);
271 while((c = dns_timeouts(NULL, -1, now)) > 0) {
272 FD_SET(fd, &fds);
273 tv.tv_sec = c;
274 tv.tv_usec = 0;
275 c = select(fd+1, &fds, NULL, NULL, &tv);
276 now = time(NULL);
277 if (c > 0)
278 dns_ioevent(NULL, now);
279 if (stopfirst && ipc->listed)
280 break;
281 }
282 }
283
284 int main(int argc, char **argv) {
285 int c;
286 struct ipcheck ipc;
287 char *nameserver = NULL;
288 int zgiven = 0;
289
290 if (!(progname = strrchr(argv[0], '/'))) progname = argv[0];
291 else argv[0] = ++progname;
292
293 while((c = getopt(argc, argv, "hqtvms:S:cn:")) != EOF) switch(c) {
294 case 's': ++zgiven; addzone(optarg); break;
295 case 'S':
296 ++zgiven;
297 if (addzonefile(optarg)) break;
298 error(1, "unable to read zonefile `%s'", optarg);
299 case 'c': ++zgiven; nzones = 0; break;
300 case 'q': --verbose; break;
301 case 'v': ++verbose; break;
302 case 't': do_txt = 1; break;
303 case 'n': nameserver = optarg; break;
304 case 'm': ++stopfirst; break;
305 case 'h':
306 printf("%s: %s (udns library version %s).\n",
307 progname, version, dns_version());
308 printf("Usage is: %s [options] address..\n", progname);
309 printf(
310 "Where options are:\n"
311 " -h - print this help and exit\n"
312 " -s service - add the service (DNSBL zone) to the serice list\n"
313 " -S service-file - add the DNSBL zone(s) read from the given file\n"
314 " -c - clear service list\n"
315 " -v - increase verbosity level (more -vs => more verbose)\n"
316 " -q - decrease verbosity level (opposite of -v)\n"
317 " -t - obtain and print TXT records if any\n"
318 " -m - stop checking after first address match in any list\n"
319 " -n ipaddr - use the given nameserver instead of the default\n"
320 "(if no -s or -S option is given, use $RBLCHECK_ZONES, ~/.rblcheckrc\n"
321 "or /etc/rblcheckrc in that order)\n"
322 );
323 return 0;
324 default:
325 error(1, "use `%s -h' for help", progname);
326 }
327
328 if (!zgiven) {
329 char *s = getenv("RBLCHECK_ZONES");
330 if (s) {
331 char *k;
332 s = strdup(s);
333 for(k = strtok(s, " \t"); k; k = strtok(NULL, " \t"))
334 addzone(k);
335 free(s);
336 }
337 else { /* probably worthless on windows? */
338 char *path;
339 char *home = getenv("HOME");
340 if (!home) home = ".";
341 path = malloc(strlen(home) + 1 + sizeof(".rblcheckrc"));
342 sprintf(path, "%s/.rblcheckrc", home);
343 if (!addzonefile(path))
344 addzonefile("/etc/rblcheckrc");
345 free(path);
346 }
347 }
348 if (!nzones)
349 error(1, "no service (zone) list specified (-s or -S option)");
350
351 argv += optind;
352 argc -= optind;
353
354 if (!argc)
355 return 0;
356
357 if (dns_init(NULL, 0) < 0)
358 error(1, "unable to initialize DNS library: %s", strerror(errno));
359 if (nameserver) {
360 dns_add_serv(NULL, NULL);
361 if (dns_add_serv(NULL, nameserver) < 0)
362 error(1, "wrong IP address for a nameserver: `%s'", nameserver);
363 }
364 if (dns_open(NULL) < 0)
365 error(1, "unable to initialize DNS library: %s", strerror(errno));
366
367 for (c = 0; c < argc; ++c) {
368 if (c && (verbose > 1 || (verbose == 1 && do_txt))) putchar('\n');
369 memset(&ipc, 0, sizeof(ipc));
370 ipc.name = argv[c];
371 submit(&ipc);
372 waitdns(&ipc);
373 display_result(&ipc);
374 if (stopfirst > 1 && listed) break;
375 }
376
377 return listed ? 100 : failures ? 2 : 0;
378 }