/[cvs]/eggdrop1.9/src/dns.c
ViewVC logotype

Contents of /eggdrop1.9/src/dns.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.42 - (show annotations) (download) (as text)
Tue Feb 25 10:28:22 2003 UTC (16 years, 7 months ago) by stdarg
Branch: MAIN
CVS Tags: HEAD
Changes since 1.41: +1 -1 lines
File MIME type: text/x-chdr
FILE REMOVED
* Cleanups

1 /*
2 * dns.c --
3 *
4 * DNS resolve calls and events
5 * provides the code used by the bot if the DNS module is not loaded
6 * DNS script commands
7 *
8 * Written by Fabian Knittel <fknittel@gmx.de>
9 */
10 /*
11 * Copyright (C) 1999, 2000, 2001, 2002, 2003 Eggheads Development Team
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) 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
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #ifndef lint
29 static const char rcsid[] = "$Id: dns.c,v 1.41 2003/01/02 21:33:16 wcc Exp $";
30 #endif
31
32 #include "main.h"
33 #include <netdb.h>
34 #include <setjmp.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38
39 #include "dns.h"
40 #include "lib/adns/adns.h"
41 #include "logfile.h"
42 #include "net.h" /* killsock */
43 #include "dccutil.h" /* lostdcc */
44 #include "dns.h" /* prototypes */
45
46 typedef struct {
47 char *name;
48 void (*event)(char *, char *, int, void *);
49 } devent_type;
50
51 typedef struct devent_str {
52 struct devent_str *next; /* Pointer to next dns_event */
53 devent_type *type;
54 u_8bit_t lookup; /* RES_IPBYHOST or RES_HOSTBYIP */
55 char *hostname; /* Hostname or IP address (as string) */
56 void *other; /* Data specific to the event type */
57 } devent_t;
58
59 extern struct dcc_t *dcc;
60 extern int dcc_total;
61 extern int resolve_timeout;
62 extern time_t now;
63 extern jmp_buf alarmret;
64
65 static devent_t *dns_events = NULL;
66
67 extern adns_state ads;
68 extern int af_preferred;
69
70 /*
71 * DCC functions
72 */
73
74 static int script_dnslookup(char *iporhost, script_callback_t *callback);
75
76 static script_command_t scriptdns_cmds[] = {
77 {"", "dnslookup", script_dnslookup, NULL, 2, "sc", "ip-address/hostname callback", SCRIPT_INTEGER, 0},
78 {0}
79 };
80
81 void dns_init()
82 {
83 script_create_commands(scriptdns_cmds);
84 }
85
86 void dcc_dnswait(int idx, char *buf, int len)
87 {
88 /* Ignore anything now. */
89 }
90
91 void eof_dcc_dnswait(int idx)
92 {
93 putlog(LOG_MISC, "*", "Lost connection while resolving hostname [%s/%d]",
94 dcc[idx].addr, dcc[idx].port);
95 killsock(dcc[idx].sock);
96 lostdcc(idx);
97 }
98
99 static void display_dcc_dnswait(int idx, char *buf)
100 {
101 sprintf(buf, "dns waited %lus", now - dcc[idx].timeval);
102 }
103
104 static void kill_dcc_dnswait(int idx, void *x)
105 {
106 register struct dns_info *p = (struct dns_info *) x;
107
108 if (p) {
109 if (p->host)
110 free(p->host);
111 if (p->cbuf)
112 free(p->cbuf);
113 free(p);
114 }
115 }
116
117 struct dcc_table DCC_DNSWAIT =
118 {
119 "DNSWAIT",
120 DCT_VALIDIDX,
121 eof_dcc_dnswait,
122 dcc_dnswait,
123 0,
124 0,
125 display_dcc_dnswait,
126 kill_dcc_dnswait,
127 0
128 };
129
130
131 /*
132 * DCC events
133 */
134
135 /* Walk through every dcc entry and look for waiting DNS requests
136 * of RES_HOSTBYIP for our IP address.
137 */
138 static void dns_dcchostbyip(char *ip, char *hostn, int ok, void *other)
139 {
140 int idx;
141
142 for (idx = 0; idx < dcc_total; idx++) {
143 if ((dcc[idx].type == &DCC_DNSWAIT) &&
144 (dcc[idx].u.dns->dns_type == RES_HOSTBYIP) &&
145 (!strcasecmp(dcc[idx].u.dns->host, ip))) {
146 debug3("|DNS| idx: %d, dcchostbyip: %s is %s", idx, ip, hostn);
147 free(dcc[idx].u.dns->host);
148 dcc[idx].u.dns->host = calloc(1, strlen(hostn) + 1);
149 strcpy(dcc[idx].u.dns->host, hostn);
150 if (ok)
151 dcc[idx].u.dns->dns_success(idx);
152 else
153 dcc[idx].u.dns->dns_failure(idx);
154 }
155 }
156 }
157
158 /* Walk through every dcc entry and look for waiting DNS requests
159 * of RES_IPBYHOST for our hostname.
160 */
161 static void dns_dccipbyhost(char *ip, char *hostn, int ok, void *other)
162 {
163 int idx;
164
165 for (idx = 0; idx < dcc_total; idx++) {
166 if ((dcc[idx].type == &DCC_DNSWAIT) &&
167 (dcc[idx].u.dns->dns_type == RES_IPBYHOST) &&
168 !strcasecmp(dcc[idx].u.dns->host, hostn)) {
169 debug3("|DNS| idx: %d, dccipbyhost: %s is %s", idx, ip, hostn);
170 free(dcc[idx].u.dns->host);
171 dcc[idx].u.dns->host = calloc(1, strlen(ip) + 1);
172 strcpy(dcc[idx].u.dns->host, ip);
173 if (ok)
174 dcc[idx].u.dns->dns_success(idx);
175 else
176 dcc[idx].u.dns->dns_failure(idx);
177 }
178 }
179 }
180
181 devent_type DNS_DCCEVENT_HOSTBYIP = {
182 "DCCEVENT_HOSTBYIP",
183 dns_dcchostbyip
184 };
185
186 devent_type DNS_DCCEVENT_IPBYHOST = {
187 "DCCEVENT_IPBYHOST",
188 dns_dccipbyhost
189 };
190
191 void dcc_dnsipbyhost(char *hostn)
192 {
193 devent_t *de;
194
195 for (de = dns_events; de; de = de->next) {
196 if (de->type && (de->type == &DNS_DCCEVENT_IPBYHOST) &&
197 (de->lookup == RES_IPBYHOST)) {
198 if (de->hostname &&
199 !strcasecmp(de->hostname, hostn))
200 /* No need to add anymore. */
201 return;
202 }
203 }
204
205 de = calloc(1, sizeof(devent_t));
206
207 /* Link into list. */
208 de->next = dns_events;
209 dns_events = de;
210
211 de->type = &DNS_DCCEVENT_IPBYHOST;
212 de->lookup = RES_IPBYHOST;
213 de->hostname = strdup(hostn);
214
215 /* Send request. */
216 dns_ipbyhost(hostn);
217 }
218
219 void dcc_dnshostbyip(char *ip)
220 {
221 devent_t *de;
222
223 for (de = dns_events; de; de = de->next) {
224 if (de->type && (de->type == &DNS_DCCEVENT_HOSTBYIP) &&
225 (de->lookup == RES_HOSTBYIP)) {
226 if (!strcasecmp(de->hostname, ip))
227 /* No need to add anymore. */
228 return;
229 }
230 }
231
232 de = calloc(1, sizeof(devent_t));
233
234 /* Link into list. */
235 de->next = dns_events;
236 dns_events = de;
237
238 de->type = &DNS_DCCEVENT_HOSTBYIP;
239 de->lookup = RES_HOSTBYIP;
240 de->hostname = strdup(ip);
241
242 /* Send request. */
243 dns_hostbyip(ip);
244 }
245
246
247 /*
248 * Script events
249 */
250
251 static void dns_script_iporhostres(char *ip, char *hostn, int ok, void *other)
252 {
253 script_callback_t *callback = (script_callback_t *)other;
254
255 callback->callback(callback, ip, hostn, ok);
256 callback->del(callback);
257 }
258
259 devent_type DNS_SCRIPTEVENT_HOSTBYIP = {
260 "SCRIPTEVENT_HOSTBYIP",
261 dns_script_iporhostres
262 };
263
264 devent_type DNS_SCRIPTEVENT_IPBYHOST = {
265 "SCRIPTEVENT_IPBYHOST",
266 dns_script_iporhostres
267 };
268
269 static void script_dnsipbyhost(char *hostn, script_callback_t *callback)
270 {
271 devent_t *de;
272
273 de = calloc(1, sizeof(devent_t));
274
275 /* Link into list. */
276 de->next = dns_events;
277 dns_events = de;
278
279 de->type = &DNS_SCRIPTEVENT_IPBYHOST;
280 de->lookup = RES_IPBYHOST;
281 de->hostname = strdup(hostn);
282 callback->syntax = strdup("ssi");
283 de->other = callback;
284
285 /* Send request. */
286 dns_ipbyhost(hostn);
287 }
288
289 static void script_dnshostbyip(char *ip, script_callback_t *callback)
290 {
291 devent_t *de;
292
293 de = calloc(1, sizeof(devent_t));
294
295 /* Link into list. */
296 de->next = dns_events;
297 dns_events = de;
298
299 de->type = &DNS_SCRIPTEVENT_HOSTBYIP;
300 de->lookup = RES_HOSTBYIP;
301 de->hostname = strdup(ip);
302 callback->syntax = strdup("ssi");
303 de->other = callback;
304
305 /* Send request. */
306 dns_hostbyip(ip);
307 }
308
309
310 /*
311 * Event functions
312 */
313
314 void call_hostbyip(char *ip, char *hostn, int ok)
315 {
316 devent_t *de = dns_events, *ode = NULL, *nde = NULL;
317
318 while (de) {
319 nde = de->next;
320 if ((de->lookup == RES_HOSTBYIP) &&
321 (!de->hostname || !(de->hostname[0]) ||
322 (!strcasecmp(de->hostname, ip)))) {
323 /* Remove the event from the list here, to avoid conflicts if one of
324 * the event handlers re-adds another event. */
325 if (ode)
326 ode->next = de->next;
327 else
328 dns_events = de->next;
329 debug3("|DNS| call_hostbyip: ip: %s host: %s ok: %d", ip, hostn, ok);
330 if (de->type && de->type->event)
331 de->type->event(ip, hostn, ok, de->other);
332 else
333 putlog(LOG_MISC, "*", "(!) Unknown DNS event type found: %s",
334 (de->type && de->type->name) ? de->type->name : "<empty>");
335 if (de->hostname)
336 free(de->hostname);
337 free(de);
338 de = ode;
339 }
340 ode = de;
341 de = nde;
342 }
343 }
344
345 void call_ipbyhost(char *hostn, char *ip, int ok)
346 {
347 devent_t *de = dns_events, *ode = NULL, *nde = NULL;
348
349 while (de) {
350 nde = de->next;
351 if ((de->lookup == RES_IPBYHOST) &&
352 (!de->hostname || !(de->hostname[0]) ||
353 !strcasecmp(de->hostname, hostn))) {
354 /* Remove the event from the list here, to avoid conflicts if one of
355 * the event handlers re-adds another event. */
356 if (ode)
357 ode->next = de->next;
358 else
359 dns_events = de->next;
360
361 if (de->type && de->type->event)
362 de->type->event(ip, hostn, ok, de->other);
363 else
364 putlog(LOG_MISC, "*", "(!) Unknown DNS event type found: %s",
365 (de->type && de->type->name) ? de->type->name : "<empty>");
366
367 if (de->hostname)
368 free(de->hostname);
369 free(de);
370 de = ode;
371 }
372 ode = de;
373 de = nde;
374 }
375 }
376
377 #ifdef DISABLE_ADNS
378 /*
379 * Async DNS emulation functions
380 */
381
382 void dns_hostbyip(char *ip)
383 {
384 struct hostent *hp = 0;
385 struct in_addr addr;
386 #ifdef IPV6
387 struct in6_addr addr6;
388 #endif
389 static char s[UHOSTLEN];
390
391 if (!setjmp(alarmret)) {
392 alarm(resolve_timeout);
393 if (inet_pton(AF_INET, ip, &addr))
394 hp = gethostbyaddr((char *) &addr, sizeof addr, AF_INET);
395 #ifdef IPV6
396 else if (inet_pton(AF_INET6, ip, &addr6))
397 hp = gethostbyaddr((char *) &addr6, sizeof addr6, AF_INET6);
398 #endif
399 else
400 hp = 0;
401 alarm(0);
402 if (hp)
403 strlcpy(s, hp->h_name, sizeof s);
404 } else
405 hp = 0;
406 if (!hp)
407 strlcpy(s, ip, sizeof s);
408 debug2("|DNS| block_dns_hostbyip: ip: %s -> host: %s", ip, s);
409 /* Call hooks. */
410 call_hostbyip(ip, s, hp ? 1 : 0);
411 }
412
413 void block_dns_ipbyhost(char *host)
414 {
415 struct in_addr inaddr;
416 #ifdef IPV6
417 struct in6_addr in6addr;
418 #endif
419
420 /* Check if someone passed us an IPv4 address as hostname
421 * and return it straight away */
422 if (inet_pton(AF_INET, host, &inaddr)) {
423 call_ipbyhost(host, host, 1);
424 return;
425 }
426 #ifdef IPV6
427 /* Check if someone passed us an IPv6 address as hostname... */
428 if (inet_pton(AF_INET6, host, &in6addr)) {
429 call_ipbyhost(host, host, 1);
430 return;
431 }
432 #endif
433 if (!setjmp(alarmret)) {
434 struct hostent *hp;
435 char *p;
436 int type;
437
438 if (!strncasecmp("ipv6%", host, 5)) {
439 type = AF_INET6;
440 p = host + 5;
441 debug1("|DNS| checking only AAAA record for %s", p);
442 } else if (!strncasecmp("ipv4%", host, 5)) {
443 type = AF_INET;
444 p = host + 5;
445 debug1("|DNS| checking only A record for %s", p);
446 } else {
447 type = AF_INET; /* af_preferred */
448 p = host;
449 }
450
451 alarm(resolve_timeout);
452 #ifndef IPV6
453 hp = gethostbyname(p);
454 #else
455 hp = gethostbyname2(p, type);
456 if (!hp && (p == host))
457 hp = gethostbyname2(p, (type == AF_INET6 ? AF_INET : AF_INET6));
458 #endif
459 alarm(0);
460
461 if (hp) {
462 char tmp[ADDRLEN];
463 inet_ntop(hp->h_addrtype, hp->h_addr_list[0], tmp, ADDRLEN-1);
464 call_ipbyhost(host, tmp, 1);
465 return;
466 }
467 /* Fall through. */
468 }
469 call_ipbyhost(host, "0.0.0.0", 0);
470 }
471
472 #endif
473
474 /*
475 * Script functions
476 */
477
478 /* dnslookup <ip-address> <proc> */
479 static int script_dnslookup(char *iporhost, script_callback_t *callback)
480 {
481 struct in_addr inaddr;
482 #ifdef IPV6
483 struct in6_addr inaddr6;
484 #endif
485
486 if (inet_pton(AF_INET, iporhost, &inaddr)
487 #ifdef IPV6
488 || inet_pton(AF_INET6, iporhost, &inaddr6)
489 #endif
490 )
491 script_dnshostbyip(iporhost, callback);
492 else
493 script_dnsipbyhost(iporhost, callback);
494 return(0);
495 }
496
497
498 /*********** ADNS support ***********/
499
500 #ifndef DISABLE_ADNS
501
502 void dns_hostbyip(char *ip)
503 {
504 adns_query q;
505 int r;
506 struct sockaddr_in in;
507 #ifdef IPV6
508 struct sockaddr_in6 in6;
509 #endif
510 char *origname;
511
512 if (inet_pton(AF_INET, ip, &in.sin_addr)) {
513 debug1("|DNS| adns_dns_hostbyip(\"%s\") (IPv4)", ip);
514 origname = strdup(ip);
515 in.sin_family = AF_INET;
516 in.sin_port = 0;
517 r = adns_submit_reverse(ads, (struct sockaddr *) &in,
518 adns_r_ptr, 0, origname, &q);
519 if (r) {
520 debug1("|DNS| adns_submit_reverse failed, errno: %d", r);
521 call_hostbyip(ip, ip, 0);
522 }
523 #ifdef IPV6
524 } else if (inet_pton(AF_INET6, ip, &in6.sin6_addr)) {
525 debug1("|DNS| adns_dns_hostbyip(\"%s\") (IPv6)", ip);
526 origname = strdup(ip);
527 in6.sin6_family = AF_INET6;
528 in6.sin6_port = 0;
529 r = adns_submit_reverse(ads, (struct sockaddr *) &in6,
530 adns_r_ptr_ip6, 0, origname, &q);
531 if (r) {
532 debug1("|DNS| adns_submit_reverse failed, errno: %d", r);
533 call_hostbyip(ip, ip, 0);
534 }
535 #endif
536 } else {
537 debug1("|DNS| adns_dns_hostbyip: got invalid ip: %s", ip);
538 call_hostbyip(ip, ip, 0);
539 }
540 }
541
542 void dns_ipbyhost(char *host)
543 {
544 adns_query q4;
545 struct sockaddr_in in;
546 #ifdef IPV6
547 struct sockaddr_in6 in6;
548 #endif
549
550 debug1("|DNS| adns_dns_ipbyhost(\"%s\");", host);
551
552 if (inet_pton(AF_INET, host, &in.sin_addr)
553 #ifdef IPV6
554 || inet_pton(AF_INET6, host, &in6.sin6_addr)
555 #endif
556 ) {
557 /* It's an IP! */
558 call_ipbyhost(host, host, 1);
559 } else {
560 char *p;
561 char *origname;
562 int type, r;
563 origname = strdup(host);
564 if (!strncasecmp("ipv6%", host, 5)) {
565 #ifdef IPV6
566 type = adns_r_addr6;
567 p = host + 5;
568 debug1("|DNS| checking only AAAA record for %s", p);
569 #else
570 debug1("|DNS| compiled without IPv6 support, can't resolv %s", host);
571 call_ipbyhost(host, "0.0.0.0", 0);
572 return;
573 #endif
574 } else if (!strncasecmp("ipv4%", host, 5)) {
575 type = adns_r_addr;
576 p = host + 5;
577 debug1("|DNS| checking only A record for %s", p);
578 } else {
579 type = adns_r_addr; /* af_preferred */
580 p = host;
581 }
582 r = adns_submit(ads, p, type, 0, origname, &q4);
583 if (r) {
584 debug1("|DNS| adns_submit failed, errno: %d", r);
585 call_ipbyhost(host, "0.0.0.0", 0);
586 }
587 }
588 }
589
590 #endif

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23