/[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.2.2.4 - (hide annotations) (download) (as text)
Sat Apr 19 17:41:59 2014 UTC (5 years, 6 months ago) by pseudo
Branch: gettext
Changes since 1.2.2.3: +3 -4 lines
File MIME type: text/x-chdr
Changed FILE * to gzFile when calling zlib funcs in compress.mod.

Fixed some compile time warnings.

Patch by: pseudo

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 pseudo 1.2.2.4 * $Id: dns.c,v 1.2.2.4 2014/04/19 17:41:59 pseudo Exp $
8 simple 1.1 */
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 pseudo 1.2.2.1 putlog(LOG_MISC, "*", _("Lost connection while resolving hostname [%s/%d])"),
60 pseudo 1.2 iptostr(&dcc[idx].sockname.addr.sa), dcc[idx].port);
61 simple 1.1 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 pseudo 1.2 static void dns_dcchostbyip(sockname_t *ip, char *hostn, int ok, void *other)
120 simple 1.1 {
121     int idx;
122    
123     for (idx = 0; idx < dcc_total; idx++) {
124     if ((dcc[idx].type == &DCC_DNSWAIT) &&
125 pseudo 1.2 (dcc[idx].u.dns->dns_type == RES_HOSTBYIP) && (
126     #ifdef IPV6
127     (ip->family == AF_INET6 &&
128     IN6_ARE_ADDR_EQUAL(&dcc[idx].u.dns->ip->addr.s6.sin6_addr,
129     &ip->addr.s6.sin6_addr)) ||
130     #endif
131     (dcc[idx].u.dns->ip->addr.s4.sin_addr.s_addr ==
132     ip->addr.s4.sin_addr.s_addr))) {
133 simple 1.1 if (dcc[idx].u.dns->host)
134     nfree(dcc[idx].u.dns->host);
135     dcc[idx].u.dns->host = get_data_ptr(strlen(hostn) + 1);
136     strcpy(dcc[idx].u.dns->host, hostn);
137     if (ok)
138     dcc[idx].u.dns->dns_success(idx);
139     else
140     dcc[idx].u.dns->dns_failure(idx);
141     }
142     }
143     }
144    
145     /* Walk through every dcc entry and look for waiting DNS requests
146     * of RES_IPBYHOST for our hostname.
147     */
148 pseudo 1.2 static void dns_dccipbyhost(sockname_t *ip, char *hostn, int ok, void *other)
149 simple 1.1 {
150     int idx;
151    
152     for (idx = 0; idx < dcc_total; idx++) {
153     if ((dcc[idx].type == &DCC_DNSWAIT) &&
154     (dcc[idx].u.dns->dns_type == RES_IPBYHOST) &&
155     !egg_strcasecmp(dcc[idx].u.dns->host, hostn)) {
156 pseudo 1.2 if (ok) {
157     if (dcc[idx].u.dns->ip)
158 pseudo 1.2.2.2 memcpy(dcc[idx].u.dns->ip, ip, sizeof(sockname_t));
159 pseudo 1.2 else
160 pseudo 1.2.2.2 memcpy(&dcc[idx].sockname, ip, sizeof(sockname_t));
161 simple 1.1 dcc[idx].u.dns->dns_success(idx);
162 pseudo 1.2 } else
163 simple 1.1 dcc[idx].u.dns->dns_failure(idx);
164     }
165     }
166     }
167    
168     static int dns_dccexpmem(void *other)
169     {
170     return 0;
171     }
172    
173     devent_type DNS_DCCEVENT_HOSTBYIP = {
174     "DCCEVENT_HOSTBYIP",
175     dns_dccexpmem,
176     dns_dcchostbyip
177     };
178    
179     devent_type DNS_DCCEVENT_IPBYHOST = {
180     "DCCEVENT_IPBYHOST",
181     dns_dccexpmem,
182     dns_dccipbyhost
183     };
184    
185     void dcc_dnsipbyhost(char *hostn)
186     {
187     devent_t *de;
188    
189     for (de = dns_events; de; de = de->next) {
190     if (de->type && (de->type == &DNS_DCCEVENT_IPBYHOST) &&
191     (de->lookup == RES_IPBYHOST)) {
192     if (de->res_data.hostname &&
193     !egg_strcasecmp(de->res_data.hostname, hostn))
194     /* No need to add anymore. */
195     return;
196     }
197     }
198    
199     de = nmalloc(sizeof(devent_t));
200     egg_bzero(de, sizeof(devent_t));
201    
202     /* Link into list. */
203     de->next = dns_events;
204     dns_events = de;
205    
206     de->type = &DNS_DCCEVENT_IPBYHOST;
207     de->lookup = RES_IPBYHOST;
208     de->res_data.hostname = nmalloc(strlen(hostn) + 1);
209     strcpy(de->res_data.hostname, hostn);
210    
211     /* Send request. */
212     dns_ipbyhost(hostn);
213     }
214    
215 pseudo 1.2 void dcc_dnshostbyip(sockname_t *ip)
216 simple 1.1 {
217     devent_t *de;
218    
219     for (de = dns_events; de; de = de->next) {
220     if (de->type && (de->type == &DNS_DCCEVENT_HOSTBYIP) &&
221     (de->lookup == RES_HOSTBYIP)) {
222     if (de->res_data.ip_addr == ip)
223     /* No need to add anymore. */
224     return;
225     }
226     }
227    
228     de = nmalloc(sizeof(devent_t));
229     egg_bzero(de, sizeof(devent_t));
230    
231     /* Link into list. */
232     de->next = dns_events;
233     dns_events = de;
234    
235     de->type = &DNS_DCCEVENT_HOSTBYIP;
236     de->lookup = RES_HOSTBYIP;
237     de->res_data.ip_addr = ip;
238    
239     /* Send request. */
240     dns_hostbyip(ip);
241     }
242    
243    
244     /*
245     * Tcl events
246     */
247    
248 pseudo 1.2 static void dns_tcl_iporhostres(sockname_t *ip, char *hostn, int ok, void *other)
249 simple 1.1 {
250     devent_tclinfo_t *tclinfo = (devent_tclinfo_t *) other;
251     Tcl_DString list;
252    
253     Tcl_DStringInit(&list);
254     Tcl_DStringAppendElement(&list, tclinfo->proc);
255 pseudo 1.2 Tcl_DStringAppendElement(&list, iptostr(&ip->addr.sa));
256 simple 1.1 Tcl_DStringAppendElement(&list, hostn);
257     Tcl_DStringAppendElement(&list, ok ? "1" : "0");
258    
259     if (tclinfo->paras) {
260     EGG_CONST char *argv[2];
261     char *output;
262    
263     argv[0] = Tcl_DStringValue(&list);
264     argv[1] = tclinfo->paras;
265     output = Tcl_Concat(2, argv);
266    
267 thommey 1.2.2.3 if (Tcl_Eval(interp, output) == TCL_ERROR) {
268 pseudo 1.2.2.1 putlog(LOG_MISC, "*", _("Tcl error [%s]: %s"), tclinfo->proc, tcl_resultstring());
269 thommey 1.2.2.3 Tcl_BackgroundError(interp);
270     }
271 simple 1.1 Tcl_Free(output);
272 thommey 1.2.2.3 } else if (Tcl_Eval(interp, Tcl_DStringValue(&list)) == TCL_ERROR) {
273 pseudo 1.2.2.1 putlog(LOG_MISC, "*", _("Tcl error [%s]: %s"), tclinfo->proc, tcl_resultstring());
274 thommey 1.2.2.3 Tcl_BackgroundError(interp);
275     }
276 simple 1.1
277     Tcl_DStringFree(&list);
278    
279     nfree(tclinfo->proc);
280     if (tclinfo->paras)
281     nfree(tclinfo->paras);
282     nfree(tclinfo);
283     }
284    
285     static int dns_tclexpmem(void *other)
286     {
287     devent_tclinfo_t *tclinfo = (devent_tclinfo_t *) other;
288     int l = 0;
289    
290     if (tclinfo) {
291     l = sizeof(devent_tclinfo_t);
292     if (tclinfo->proc)
293     l += strlen(tclinfo->proc) + 1;
294     if (tclinfo->paras)
295     l += strlen(tclinfo->paras) + 1;
296     }
297     return l;
298     }
299    
300     devent_type DNS_TCLEVENT_HOSTBYIP = {
301     "TCLEVENT_HOSTBYIP",
302     dns_tclexpmem,
303     dns_tcl_iporhostres
304     };
305    
306     devent_type DNS_TCLEVENT_IPBYHOST = {
307     "TCLEVENT_IPBYHOST",
308     dns_tclexpmem,
309     dns_tcl_iporhostres
310     };
311    
312     static void tcl_dnsipbyhost(char *hostn, char *proc, char *paras)
313     {
314     devent_t *de;
315     devent_tclinfo_t *tclinfo;
316    
317     de = nmalloc(sizeof(devent_t));
318     egg_bzero(de, sizeof(devent_t));
319    
320     /* Link into list. */
321     de->next = dns_events;
322     dns_events = de;
323    
324     de->type = &DNS_TCLEVENT_IPBYHOST;
325     de->lookup = RES_IPBYHOST;
326     de->res_data.hostname = nmalloc(strlen(hostn) + 1);
327     strcpy(de->res_data.hostname, hostn);
328    
329     /* Store additional data. */
330     tclinfo = nmalloc(sizeof(devent_tclinfo_t));
331     tclinfo->proc = nmalloc(strlen(proc) + 1);
332     strcpy(tclinfo->proc, proc);
333     if (paras) {
334     tclinfo->paras = nmalloc(strlen(paras) + 1);
335     strcpy(tclinfo->paras, paras);
336     } else
337     tclinfo->paras = NULL;
338     de->other = tclinfo;
339    
340     /* Send request. */
341     dns_ipbyhost(hostn);
342     }
343    
344 pseudo 1.2 static void tcl_dnshostbyip(sockname_t *ip, char *proc, char *paras)
345 simple 1.1 {
346     devent_t *de;
347     devent_tclinfo_t *tclinfo;
348    
349     de = nmalloc(sizeof(devent_t));
350     egg_bzero(de, sizeof(devent_t));
351    
352     /* Link into list. */
353     de->next = dns_events;
354     dns_events = de;
355    
356     de->type = &DNS_TCLEVENT_HOSTBYIP;
357     de->lookup = RES_HOSTBYIP;
358     de->res_data.ip_addr = ip;
359    
360     /* Store additional data. */
361     tclinfo = nmalloc(sizeof(devent_tclinfo_t));
362     tclinfo->proc = nmalloc(strlen(proc) + 1);
363     strcpy(tclinfo->proc, proc);
364 pseudo 1.2 memcpy(&tclinfo->sockname, ip, sizeof(sockname_t));
365     de->res_data.ip_addr = &tclinfo->sockname;
366 simple 1.1 if (paras) {
367     tclinfo->paras = nmalloc(strlen(paras) + 1);
368     strcpy(tclinfo->paras, paras);
369     } else
370     tclinfo->paras = NULL;
371     de->other = tclinfo;
372    
373     /* Send request. */
374     dns_hostbyip(ip);
375     }
376    
377    
378     /*
379     * Event functions
380     */
381    
382     inline static int dnsevent_expmem(void)
383     {
384     devent_t *de;
385     int tot = 0;
386    
387     for (de = dns_events; de; de = de->next) {
388     tot += sizeof(devent_t);
389     if ((de->lookup == RES_IPBYHOST) && de->res_data.hostname)
390     tot += strlen(de->res_data.hostname) + 1;
391     if (de->type && de->type->expmem)
392     tot += de->type->expmem(de->other);
393     }
394     return tot;
395     }
396    
397 pseudo 1.2 void call_hostbyip(sockname_t *ip, char *hostn, int ok)
398 simple 1.1 {
399     devent_t *de = dns_events, *ode = NULL, *nde = NULL;
400    
401     while (de) {
402     nde = de->next;
403 pseudo 1.2 if ((de->lookup == RES_HOSTBYIP) && (
404     #ifdef IPV6
405     (ip->family == AF_INET6 &&
406     IN6_ARE_ADDR_EQUAL(&de->res_data.ip_addr->addr.s6.sin6_addr,
407     &ip->addr.s6.sin6_addr)) ||
408     #endif
409     (de->res_data.ip_addr->addr.s4.sin_addr.s_addr ==
410     ip->addr.s4.sin_addr.s_addr))) {
411     /* A memcmp() could have perfectly done it .. */
412 simple 1.1 /* Remove the event from the list here, to avoid conflicts if one of
413     * the event handlers re-adds another event. */
414     if (ode)
415     ode->next = de->next;
416     else
417     dns_events = de->next;
418    
419     if (de->type && de->type->event)
420     de->type->event(ip, hostn, ok, de->other);
421 pseudo 1.2.2.1 else if (de->type && de->type->name)
422     putlog(LOG_MISC, "*", _("(!) Unknown DNS event type found: %s"),
423     de->type->name);
424 simple 1.1 else
425 pseudo 1.2.2.1 putlog(LOG_MISC, "*", _("(!) Unknown DNS event type found with no name"));
426 simple 1.1 nfree(de);
427     de = ode;
428     }
429     ode = de;
430     de = nde;
431     }
432     }
433    
434 pseudo 1.2 void call_ipbyhost(char *hostn, sockname_t *ip, int ok)
435 simple 1.1 {
436     devent_t *de = dns_events, *ode = NULL, *nde = NULL;
437    
438     while (de) {
439     nde = de->next;
440     if ((de->lookup == RES_IPBYHOST) && (!de->res_data.hostname ||
441     !egg_strcasecmp(de->res_data.hostname, hostn))) {
442     /* Remove the event from the list here, to avoid conflicts if one of
443     * the event handlers re-adds another event. */
444     if (ode)
445     ode->next = de->next;
446     else
447     dns_events = de->next;
448    
449     if (de->type && de->type->event)
450     de->type->event(ip, hostn, ok, de->other);
451 pseudo 1.2.2.1 else if (de->type && de->type->name)
452     putlog(LOG_MISC, "*", _("(!) Unknown DNS event type found: %s"),
453     de->type->name);
454 simple 1.1 else
455 pseudo 1.2.2.1 putlog(LOG_MISC, "*", _("(!) Unknown DNS event type found with no name"));
456 simple 1.1
457     if (de->res_data.hostname)
458     nfree(de->res_data.hostname);
459     nfree(de);
460     de = ode;
461     }
462     ode = de;
463     de = nde;
464     }
465     }
466    
467    
468     /*
469     * Async DNS emulation functions
470     */
471 pseudo 1.2 void block_dns_hostbyip(sockname_t *addr)
472 simple 1.1 {
473 pseudo 1.2 struct hostent *hp = 0;
474 simple 1.1 static char s[UHOSTLEN];
475    
476 pseudo 1.2 if (addr->family == AF_INET) {
477     if (!sigsetjmp(alarmret, 1)) {
478     alarm(resolve_timeout);
479     hp = gethostbyaddr(&addr->addr.s4.sin_addr,
480     sizeof (struct in_addr), AF_INET);
481     alarm(0);
482     }
483     if (!hp)
484 pseudo 1.2.2.4 (void) inet_ntop(AF_INET, &addr->addr.s4.sin_addr.s_addr, s, sizeof s);
485 pseudo 1.2 #ifdef IPV6
486 simple 1.1 } else {
487 pseudo 1.2 if (!sigsetjmp(alarmret, 1)) {
488     alarm(resolve_timeout);
489     hp = gethostbyaddr((char *) &addr->addr.s6.sin6_addr,
490     sizeof (struct in6_addr), AF_INET6);
491     alarm(0);
492     }
493     if (!hp)
494 pseudo 1.2.2.4 (void) inet_ntop(AF_INET6, &addr->addr.s6.sin6_addr, s, sizeof s);
495 pseudo 1.2 }
496     #else
497 simple 1.1 }
498 pseudo 1.2 #endif
499     if (hp)
500     strncpyz(s, hp->h_name, sizeof s);
501     call_hostbyip(addr, s, hp ? 1 : 0);
502     }
503 simple 1.1
504     void block_dns_ipbyhost(char *host)
505     {
506 pseudo 1.2 sockname_t name;
507 simple 1.1
508 pseudo 1.2 if (setsockname(&name, host, 0, 1) == AF_UNSPEC)
509     call_ipbyhost(host, &name, 0);
510     else
511     call_ipbyhost(host, &name, 1);
512 simple 1.1 }
513    
514     /*
515     * Misc functions
516     */
517    
518     int expmem_dns(void)
519     {
520     return dnsevent_expmem();
521     }
522    
523    
524     /*
525     * Tcl functions
526     */
527    
528     /* dnslookup <ip-address> <proc> */
529     static int tcl_dnslookup STDVAR
530     {
531 pseudo 1.2 sockname_t addr;
532 simple 1.1 Tcl_DString paras;
533    
534     if (argc < 3) {
535     Tcl_AppendResult(irp, "wrong # args: should be \"", argv[0],
536     " ip-address/hostname proc ?args...?\"", NULL);
537     return TCL_ERROR;
538     }
539    
540     Tcl_DStringInit(&paras);
541     if (argc > 3) {
542     int p;
543    
544     for (p = 3; p < argc; p++)
545     Tcl_DStringAppendElement(&paras, argv[p]);
546     }
547    
548 pseudo 1.2 if (setsockname(&addr, argv[1], 0, 0) != AF_UNSPEC)
549     tcl_dnshostbyip(&addr, argv[2], Tcl_DStringValue(&paras));
550 simple 1.1 else
551     tcl_dnsipbyhost(argv[1], argv[2], Tcl_DStringValue(&paras));
552    
553     Tcl_DStringFree(&paras);
554     return TCL_OK;
555     }
556    
557     tcl_cmds tcldns_cmds[] = {
558     {"dnslookup", tcl_dnslookup},
559     {NULL, NULL}
560     };

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23