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

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

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


Revision 1.1 - (hide annotations) (download) (as text)
Mon Jul 26 21:11:06 2010 UTC (9 years, 2 months ago) by simple
Branch: MAIN
Branch point for: eggheads
File MIME type: text/x-chdr
Initial revision

1 simple 1.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