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

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

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


Revision 1.1.1.1 - (show annotations) (download) (as text) (vendor branch)
Mon Jul 26 21:11:06 2010 UTC (8 years, 10 months ago) by simple
Branch: eggheads
CVS Tags: v1
Changes since 1.1: +0 -0 lines
File MIME type: text/x-chdr
Imported Eggdrop 1.6.20

1 /*
2 * dns.c -- handles:
3 * DNS resolve calls and events
4 * provides the code used by the bot if the DNS module is not loaded
5 * DNS Tcl commands
6 *
7 * $Id: dns.c,v 1.38 2010/01/03 13:27:32 pseudo Exp $
8 */
9 /*
10 * Written by Fabian Knittel <fknittel@gmx.de>
11 *
12 * Copyright (C) 1999 - 2010 Eggheads Development Team
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) 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
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29 #include "main.h"
30 #include <netdb.h>
31 #include <setjmp.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35
36 #include "dns.h"
37
38 extern struct dcc_t *dcc;
39 extern int dcc_total;
40 extern int resolve_timeout;
41 extern time_t now;
42 extern sigjmp_buf alarmret;
43 extern Tcl_Interp *interp;
44
45 devent_t *dns_events = NULL;
46
47
48 /*
49 * DCC functions
50 */
51
52 void dcc_dnswait(int idx, char *buf, int len)
53 {
54 /* Ignore anything now. */
55 }
56
57 void eof_dcc_dnswait(int idx)
58 {
59 putlog(LOG_MISC, "*", "Lost connection while resolving hostname [%s/%d]",
60 iptostr(htonl(dcc[idx].addr)), dcc[idx].port);
61 killsock(dcc[idx].sock);
62 lostdcc(idx);
63 }
64
65 static void display_dcc_dnswait(int idx, char *buf)
66 {
67 sprintf(buf, "dns waited %lis", (long) now - dcc[idx].timeval);
68 }
69
70 static int expmem_dcc_dnswait(void *x)
71 {
72 register struct dns_info *p = (struct dns_info *) x;
73 int size = 0;
74
75 if (p) {
76 size = sizeof(struct dns_info);
77 if (p->host)
78 size += strlen(p->host) + 1;
79 if (p->cbuf)
80 size += strlen(p->cbuf) + 1;
81 }
82 return size;
83 }
84
85 static void kill_dcc_dnswait(int idx, void *x)
86 {
87 register struct dns_info *p = (struct dns_info *) x;
88
89 if (p) {
90 if (p->host)
91 nfree(p->host);
92 if (p->cbuf)
93 nfree(p->cbuf);
94 nfree(p);
95 }
96 }
97
98 struct dcc_table DCC_DNSWAIT = {
99 "DNSWAIT",
100 DCT_VALIDIDX,
101 eof_dcc_dnswait,
102 dcc_dnswait,
103 0,
104 0,
105 display_dcc_dnswait,
106 expmem_dcc_dnswait,
107 kill_dcc_dnswait,
108 0
109 };
110
111
112 /*
113 * DCC events
114 */
115
116 /* Walk through every dcc entry and look for waiting DNS requests
117 * of RES_HOSTBYIP for our IP address.
118 */
119 static void dns_dcchostbyip(IP ip, char *hostn, int ok, void *other)
120 {
121 int idx;
122
123 for (idx = 0; idx < dcc_total; idx++) {
124 if ((dcc[idx].type == &DCC_DNSWAIT) &&
125 (dcc[idx].u.dns->dns_type == RES_HOSTBYIP) &&
126 (dcc[idx].u.dns->ip == ip)) {
127 if (dcc[idx].u.dns->host)
128 nfree(dcc[idx].u.dns->host);
129 dcc[idx].u.dns->host = get_data_ptr(strlen(hostn) + 1);
130 strcpy(dcc[idx].u.dns->host, hostn);
131 if (ok)
132 dcc[idx].u.dns->dns_success(idx);
133 else
134 dcc[idx].u.dns->dns_failure(idx);
135 }
136 }
137 }
138
139 /* Walk through every dcc entry and look for waiting DNS requests
140 * of RES_IPBYHOST for our hostname.
141 */
142 static void dns_dccipbyhost(IP ip, char *hostn, int ok, void *other)
143 {
144 int idx;
145
146 for (idx = 0; idx < dcc_total; idx++) {
147 if ((dcc[idx].type == &DCC_DNSWAIT) &&
148 (dcc[idx].u.dns->dns_type == RES_IPBYHOST) &&
149 !egg_strcasecmp(dcc[idx].u.dns->host, hostn)) {
150 dcc[idx].u.dns->ip = ip;
151 if (ok)
152 dcc[idx].u.dns->dns_success(idx);
153 else
154 dcc[idx].u.dns->dns_failure(idx);
155 }
156 }
157 }
158
159 static int dns_dccexpmem(void *other)
160 {
161 return 0;
162 }
163
164 devent_type DNS_DCCEVENT_HOSTBYIP = {
165 "DCCEVENT_HOSTBYIP",
166 dns_dccexpmem,
167 dns_dcchostbyip
168 };
169
170 devent_type DNS_DCCEVENT_IPBYHOST = {
171 "DCCEVENT_IPBYHOST",
172 dns_dccexpmem,
173 dns_dccipbyhost
174 };
175
176 void dcc_dnsipbyhost(char *hostn)
177 {
178 devent_t *de;
179
180 for (de = dns_events; de; de = de->next) {
181 if (de->type && (de->type == &DNS_DCCEVENT_IPBYHOST) &&
182 (de->lookup == RES_IPBYHOST)) {
183 if (de->res_data.hostname &&
184 !egg_strcasecmp(de->res_data.hostname, hostn))
185 /* No need to add anymore. */
186 return;
187 }
188 }
189
190 de = nmalloc(sizeof(devent_t));
191 egg_bzero(de, sizeof(devent_t));
192
193 /* Link into list. */
194 de->next = dns_events;
195 dns_events = de;
196
197 de->type = &DNS_DCCEVENT_IPBYHOST;
198 de->lookup = RES_IPBYHOST;
199 de->res_data.hostname = nmalloc(strlen(hostn) + 1);
200 strcpy(de->res_data.hostname, hostn);
201
202 /* Send request. */
203 dns_ipbyhost(hostn);
204 }
205
206 void dcc_dnshostbyip(IP ip)
207 {
208 devent_t *de;
209
210 for (de = dns_events; de; de = de->next) {
211 if (de->type && (de->type == &DNS_DCCEVENT_HOSTBYIP) &&
212 (de->lookup == RES_HOSTBYIP)) {
213 if (de->res_data.ip_addr == ip)
214 /* No need to add anymore. */
215 return;
216 }
217 }
218
219 de = nmalloc(sizeof(devent_t));
220 egg_bzero(de, sizeof(devent_t));
221
222 /* Link into list. */
223 de->next = dns_events;
224 dns_events = de;
225
226 de->type = &DNS_DCCEVENT_HOSTBYIP;
227 de->lookup = RES_HOSTBYIP;
228 de->res_data.ip_addr = ip;
229
230 /* Send request. */
231 dns_hostbyip(ip);
232 }
233
234
235 /*
236 * Tcl events
237 */
238
239 static void dns_tcl_iporhostres(IP ip, char *hostn, int ok, void *other)
240 {
241 devent_tclinfo_t *tclinfo = (devent_tclinfo_t *) other;
242 Tcl_DString list;
243
244 Tcl_DStringInit(&list);
245 Tcl_DStringAppendElement(&list, tclinfo->proc);
246 Tcl_DStringAppendElement(&list, iptostr(htonl(ip)));
247 Tcl_DStringAppendElement(&list, hostn);
248 Tcl_DStringAppendElement(&list, ok ? "1" : "0");
249
250 if (tclinfo->paras) {
251 EGG_CONST char *argv[2];
252 char *output;
253
254 argv[0] = Tcl_DStringValue(&list);
255 argv[1] = tclinfo->paras;
256 output = Tcl_Concat(2, argv);
257
258 if (Tcl_Eval(interp, output) == TCL_ERROR)
259 putlog(LOG_MISC, "*", DCC_TCLERROR, tclinfo->proc, tcl_resultstring());
260 Tcl_Free(output);
261 } else if (Tcl_Eval(interp, Tcl_DStringValue(&list)) == TCL_ERROR)
262 putlog(LOG_MISC, "*", DCC_TCLERROR, tclinfo->proc, tcl_resultstring());
263
264 Tcl_DStringFree(&list);
265
266 nfree(tclinfo->proc);
267 if (tclinfo->paras)
268 nfree(tclinfo->paras);
269 nfree(tclinfo);
270 }
271
272 static int dns_tclexpmem(void *other)
273 {
274 devent_tclinfo_t *tclinfo = (devent_tclinfo_t *) other;
275 int l = 0;
276
277 if (tclinfo) {
278 l = sizeof(devent_tclinfo_t);
279 if (tclinfo->proc)
280 l += strlen(tclinfo->proc) + 1;
281 if (tclinfo->paras)
282 l += strlen(tclinfo->paras) + 1;
283 }
284 return l;
285 }
286
287 devent_type DNS_TCLEVENT_HOSTBYIP = {
288 "TCLEVENT_HOSTBYIP",
289 dns_tclexpmem,
290 dns_tcl_iporhostres
291 };
292
293 devent_type DNS_TCLEVENT_IPBYHOST = {
294 "TCLEVENT_IPBYHOST",
295 dns_tclexpmem,
296 dns_tcl_iporhostres
297 };
298
299 static void tcl_dnsipbyhost(char *hostn, char *proc, char *paras)
300 {
301 devent_t *de;
302 devent_tclinfo_t *tclinfo;
303
304 de = nmalloc(sizeof(devent_t));
305 egg_bzero(de, sizeof(devent_t));
306
307 /* Link into list. */
308 de->next = dns_events;
309 dns_events = de;
310
311 de->type = &DNS_TCLEVENT_IPBYHOST;
312 de->lookup = RES_IPBYHOST;
313 de->res_data.hostname = nmalloc(strlen(hostn) + 1);
314 strcpy(de->res_data.hostname, hostn);
315
316 /* Store additional data. */
317 tclinfo = nmalloc(sizeof(devent_tclinfo_t));
318 tclinfo->proc = nmalloc(strlen(proc) + 1);
319 strcpy(tclinfo->proc, proc);
320 if (paras) {
321 tclinfo->paras = nmalloc(strlen(paras) + 1);
322 strcpy(tclinfo->paras, paras);
323 } else
324 tclinfo->paras = NULL;
325 de->other = tclinfo;
326
327 /* Send request. */
328 dns_ipbyhost(hostn);
329 }
330
331 static void tcl_dnshostbyip(IP ip, char *proc, char *paras)
332 {
333 devent_t *de;
334 devent_tclinfo_t *tclinfo;
335
336 de = nmalloc(sizeof(devent_t));
337 egg_bzero(de, sizeof(devent_t));
338
339 /* Link into list. */
340 de->next = dns_events;
341 dns_events = de;
342
343 de->type = &DNS_TCLEVENT_HOSTBYIP;
344 de->lookup = RES_HOSTBYIP;
345 de->res_data.ip_addr = ip;
346
347 /* Store additional data. */
348 tclinfo = nmalloc(sizeof(devent_tclinfo_t));
349 tclinfo->proc = nmalloc(strlen(proc) + 1);
350 strcpy(tclinfo->proc, proc);
351 if (paras) {
352 tclinfo->paras = nmalloc(strlen(paras) + 1);
353 strcpy(tclinfo->paras, paras);
354 } else
355 tclinfo->paras = NULL;
356 de->other = tclinfo;
357
358 /* Send request. */
359 dns_hostbyip(ip);
360 }
361
362
363 /*
364 * Event functions
365 */
366
367 inline static int dnsevent_expmem(void)
368 {
369 devent_t *de;
370 int tot = 0;
371
372 for (de = dns_events; de; de = de->next) {
373 tot += sizeof(devent_t);
374 if ((de->lookup == RES_IPBYHOST) && de->res_data.hostname)
375 tot += strlen(de->res_data.hostname) + 1;
376 if (de->type && de->type->expmem)
377 tot += de->type->expmem(de->other);
378 }
379 return tot;
380 }
381
382 void call_hostbyip(IP ip, char *hostn, int ok)
383 {
384 devent_t *de = dns_events, *ode = NULL, *nde = NULL;
385
386 while (de) {
387 nde = de->next;
388 if ((de->lookup == RES_HOSTBYIP) &&
389 (!de->res_data.ip_addr || (de->res_data.ip_addr == ip))) {
390 /* Remove the event from the list here, to avoid conflicts if one of
391 * the event handlers re-adds another event. */
392 if (ode)
393 ode->next = de->next;
394 else
395 dns_events = de->next;
396
397 if (de->type && de->type->event)
398 de->type->event(ip, hostn, ok, de->other);
399 else
400 putlog(LOG_MISC, "*", "(!) Unknown DNS event type found: %s",
401 (de->type && de->type->name) ? de->type->name : "<empty>");
402 nfree(de);
403 de = ode;
404 }
405 ode = de;
406 de = nde;
407 }
408 }
409
410 void call_ipbyhost(char *hostn, IP ip, int ok)
411 {
412 devent_t *de = dns_events, *ode = NULL, *nde = NULL;
413
414 while (de) {
415 nde = de->next;
416 if ((de->lookup == RES_IPBYHOST) && (!de->res_data.hostname ||
417 !egg_strcasecmp(de->res_data.hostname, hostn))) {
418 /* Remove the event from the list here, to avoid conflicts if one of
419 * the event handlers re-adds another event. */
420 if (ode)
421 ode->next = de->next;
422 else
423 dns_events = de->next;
424
425 if (de->type && de->type->event)
426 de->type->event(ip, hostn, ok, de->other);
427 else
428 putlog(LOG_MISC, "*", "(!) Unknown DNS event type found: %s",
429 (de->type && de->type->name) ? de->type->name : "<empty>");
430
431 if (de->res_data.hostname)
432 nfree(de->res_data.hostname);
433 nfree(de);
434 de = ode;
435 }
436 ode = de;
437 de = nde;
438 }
439 }
440
441
442 /*
443 * Async DNS emulation functions
444 */
445
446 void block_dns_hostbyip(IP ip)
447 {
448 struct hostent *hp;
449 unsigned long addr = htonl(ip);
450 static char s[UHOSTLEN];
451
452 if (!sigsetjmp(alarmret, 1)) {
453 alarm(resolve_timeout);
454 hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
455 alarm(0);
456 if (hp)
457 strncpyz(s, hp->h_name, sizeof s);
458 else
459 strcpy(s, iptostr(addr));
460 } else {
461 hp = NULL;
462 strcpy(s, iptostr(addr));
463 }
464 /* Call hooks. */
465 call_hostbyip(ip, s, hp ? 1 : 0);
466 }
467
468 void block_dns_ipbyhost(char *host)
469 {
470 struct in_addr inaddr;
471
472 /* Check if someone passed us an IP address as hostname
473 * and return it straight away */
474 if (egg_inet_aton(host, &inaddr)) {
475 call_ipbyhost(host, ntohl(inaddr.s_addr), 1);
476 return;
477 }
478 if (!sigsetjmp(alarmret, 1)) {
479 struct hostent *hp;
480 struct in_addr *in;
481 IP ip = 0;
482
483 alarm(resolve_timeout);
484 hp = gethostbyname(host);
485 alarm(0);
486
487 if (hp) {
488 in = (struct in_addr *) (hp->h_addr_list[0]);
489 ip = (IP) (in->s_addr);
490 call_ipbyhost(host, ntohl(ip), 1);
491 return;
492 }
493 /* Fall through. */
494 }
495 call_ipbyhost(host, 0, 0);
496 }
497
498
499 /*
500 * Misc functions
501 */
502
503 int expmem_dns(void)
504 {
505 return dnsevent_expmem();
506 }
507
508
509 /*
510 * Tcl functions
511 */
512
513 /* dnslookup <ip-address> <proc> */
514 static int tcl_dnslookup STDVAR
515 {
516 struct in_addr inaddr;
517 Tcl_DString paras;
518
519 if (argc < 3) {
520 Tcl_AppendResult(irp, "wrong # args: should be \"", argv[0],
521 " ip-address/hostname proc ?args...?\"", NULL);
522 return TCL_ERROR;
523 }
524
525 Tcl_DStringInit(&paras);
526 if (argc > 3) {
527 int p;
528
529 for (p = 3; p < argc; p++)
530 Tcl_DStringAppendElement(&paras, argv[p]);
531 }
532
533 if (egg_inet_aton(argv[1], &inaddr))
534 tcl_dnshostbyip(ntohl(inaddr.s_addr), argv[2], Tcl_DStringValue(&paras));
535 else
536 tcl_dnsipbyhost(argv[1], argv[2], Tcl_DStringValue(&paras));
537
538 Tcl_DStringFree(&paras);
539 return TCL_OK;
540 }
541
542 tcl_cmds tcldns_cmds[] = {
543 {"dnslookup", tcl_dnslookup},
544 {NULL, NULL}
545 };

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23