/[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.2.2.4 - (show annotations) (download) (as text)
Sat Apr 19 17:41:59 2014 UTC (5 years, 2 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 /*
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.2.2.3 2012/06/16 15:59:49 thommey 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(&dcc[idx].sockname.addr.sa), 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(sockname_t *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 #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 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 static void dns_dccipbyhost(sockname_t *ip, char *hostn, int ok, void *other)
149 {
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 if (ok) {
157 if (dcc[idx].u.dns->ip)
158 memcpy(dcc[idx].u.dns->ip, ip, sizeof(sockname_t));
159 else
160 memcpy(&dcc[idx].sockname, ip, sizeof(sockname_t));
161 dcc[idx].u.dns->dns_success(idx);
162 } else
163 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 void dcc_dnshostbyip(sockname_t *ip)
216 {
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 static void dns_tcl_iporhostres(sockname_t *ip, char *hostn, int ok, void *other)
249 {
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 Tcl_DStringAppendElement(&list, iptostr(&ip->addr.sa));
256 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 if (Tcl_Eval(interp, output) == TCL_ERROR) {
268 putlog(LOG_MISC, "*", _("Tcl error [%s]: %s"), tclinfo->proc, tcl_resultstring());
269 Tcl_BackgroundError(interp);
270 }
271 Tcl_Free(output);
272 } else if (Tcl_Eval(interp, Tcl_DStringValue(&list)) == TCL_ERROR) {
273 putlog(LOG_MISC, "*", _("Tcl error [%s]: %s"), tclinfo->proc, tcl_resultstring());
274 Tcl_BackgroundError(interp);
275 }
276
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 static void tcl_dnshostbyip(sockname_t *ip, char *proc, char *paras)
345 {
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 memcpy(&tclinfo->sockname, ip, sizeof(sockname_t));
365 de->res_data.ip_addr = &tclinfo->sockname;
366 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 void call_hostbyip(sockname_t *ip, char *hostn, int ok)
398 {
399 devent_t *de = dns_events, *ode = NULL, *nde = NULL;
400
401 while (de) {
402 nde = de->next;
403 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 /* 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 else if (de->type && de->type->name)
422 putlog(LOG_MISC, "*", _("(!) Unknown DNS event type found: %s"),
423 de->type->name);
424 else
425 putlog(LOG_MISC, "*", _("(!) Unknown DNS event type found with no name"));
426 nfree(de);
427 de = ode;
428 }
429 ode = de;
430 de = nde;
431 }
432 }
433
434 void call_ipbyhost(char *hostn, sockname_t *ip, int ok)
435 {
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 else if (de->type && de->type->name)
452 putlog(LOG_MISC, "*", _("(!) Unknown DNS event type found: %s"),
453 de->type->name);
454 else
455 putlog(LOG_MISC, "*", _("(!) Unknown DNS event type found with no name"));
456
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 void block_dns_hostbyip(sockname_t *addr)
472 {
473 struct hostent *hp = 0;
474 static char s[UHOSTLEN];
475
476 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 (void) inet_ntop(AF_INET, &addr->addr.s4.sin_addr.s_addr, s, sizeof s);
485 #ifdef IPV6
486 } else {
487 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 (void) inet_ntop(AF_INET6, &addr->addr.s6.sin6_addr, s, sizeof s);
495 }
496 #else
497 }
498 #endif
499 if (hp)
500 strncpyz(s, hp->h_name, sizeof s);
501 call_hostbyip(addr, s, hp ? 1 : 0);
502 }
503
504 void block_dns_ipbyhost(char *host)
505 {
506 sockname_t name;
507
508 if (setsockname(&name, host, 0, 1) == AF_UNSPEC)
509 call_ipbyhost(host, &name, 0);
510 else
511 call_ipbyhost(host, &name, 1);
512 }
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 sockname_t addr;
532 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 if (setsockname(&addr, argv[1], 0, 0) != AF_UNSPEC)
549 tcl_dnshostbyip(&addr, argv[2], Tcl_DStringValue(&paras));
550 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