1 /*
2 * dns.c -- part of dns.mod
3 * domain lookup glue code for Evangeline
4 *
5 * Written by Fabian Knittel <fknittel@gmx.de>
6 *
7 * $Id: dns.c,v 1.35 (2.0.0) 2004/09/28 21:41:38 Arcain Exp $
8 */
9 /*
10 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Eggheads Development Team
11 * Copyright (C) 2001, 2002, 2003, 2004 Arcain/[Xp-AvR]
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 #define MODULE_NAME "dns"
29
30 #include "modules/module.h"
31 #include "dns.h"
32
33 static void dns_event_success(struct resolve *rp, int type);
34 static void dns_event_failure(struct resolve *rp, int type);
35
36 static Function *global = NULL;
37
38 #include "coredns.c"
39
40
41 /*
42 * DNS event related code
43 */
dns_event_success(struct resolve * rp,int type)44 static void dns_event_success(struct resolve *rp, int type)
45 {
46 if (!rp)
47 return;
48
49 if (type == T_PTR) {
50 debug2("DNS resolved %s to %s", iptostr(rp->ip), rp->hostn);
51 call_hostbyip(ntohl(rp->ip), rp->hostn, 1);
52 } else if (type == T_A) {
53 debug2("DNS resolved %s to %s", rp->hostn, iptostr(rp->ip));
54 call_ipbyhost(rp->hostn, ntohl(rp->ip), 1);
55 }
56 }
57
dns_event_failure(struct resolve * rp,int type)58 static void dns_event_failure(struct resolve *rp, int type)
59 {
60 if (!rp)
61 return;
62
63 if (type == T_PTR) {
64 static char s[UHOSTLEN];
65
66 debug1("DNS resolve failed for %s", iptostr(rp->ip));
67 strcpy(s, iptostr(rp->ip));
68 call_hostbyip(ntohl(rp->ip), s, 0);
69 } else if (type == T_A) {
70 debug1("DNS resolve failed for %s", rp->hostn);
71 call_ipbyhost(rp->hostn, 0, 0);
72 } else
73 debug2("DNS resolve failed for unknown %s / %s", iptostr(rp->ip),
74 nonull(rp->hostn));
75 return;
76 }
77
78
79 /*
80 * DNS Socket related code
81 */
82
eof_dns_socket(int idx)83 static void eof_dns_socket(int idx)
84 {
85 putlog(LOG_MISC, "*", "DNS Error: socket closed.");
86 killsock(dcc[idx].sock);
87 /* Try to reopen socket */
88 if (init_dns_network()) {
89 putlog(LOG_MISC, "*", "DNS socket successfully reopened!");
90 dcc[idx].sock = resfd;
91 dcc[idx].timeval = now;
92 } else
93 lostdcc(idx);
94 }
95
dns_socket(int idx,char * buf,int len)96 static void dns_socket(int idx, char *buf, int len)
97 {
98 dns_ack();
99 }
100
display_dns_socket(int idx,char * buf)101 static void display_dns_socket(int idx, char *buf)
102 {
103 strcpy(buf, "dns (ready)");
104 }
105
106 static struct dcc_table DCC_DNS = {
107 "DNS",
108 DCT_LISTEN,
109 eof_dns_socket,
110 dns_socket,
111 NULL,
112 NULL,
113 display_dns_socket,
114 NULL,
115 NULL,
116 NULL
117 };
118
119
120 /*
121 * DNS module related code
122 */
123
dns_free_cache(void)124 static void dns_free_cache(void)
125 {
126 struct resolve *rp, *rpnext;
127
128 for (rp = expireresolves; rp; rp = rpnext) {
129 rpnext = rp->next;
130 if (rp->hostn)
131 nfree(rp->hostn);
132 nfree(rp);
133 }
134 expireresolves = NULL;
135 }
136
dns_cache_expmem(void)137 static int dns_cache_expmem(void)
138 {
139 struct resolve *rp;
140 int size = 0;
141
142 for (rp = expireresolves; rp; rp = rp->next) {
143 size += sizeof(struct resolve);
144 if (rp->hostn)
145 size += strlen(rp->hostn) + 1;
146 }
147 return size;
148 }
149
dns_expmem(void)150 static int dns_expmem(void)
151 {
152 return dns_cache_expmem();
153 }
154
dns_report(int idx,int details)155 static int dns_report(int idx, int details)
156 {
157 if (details) {
158 int size = dns_expmem();
159
160 dprintf(idx, " Async DNS resolver is active.\n");
161 dprintf(idx, " Using %d byte%s of memory\n", size,
162 (size != 1) ? "s" : "");
163 }
164 return 0;
165 }
166
dns_close()167 static char *dns_close()
168 {
169 int i;
170
171 del_hook(HOOK_DNS_HOSTBYIP, (Function) dns_lookup);
172 del_hook(HOOK_DNS_IPBYHOST, (Function) dns_forward);
173 del_hook(HOOK_SECONDLY, (Function) dns_check_expires);
174
175 for (i = 0; i < dcc_total; i++) {
176 if (dcc[i].type == &DCC_DNS && dcc[i].sock == resfd) {
177 killsock(dcc[i].sock);
178 lostdcc(i);
179 break;
180 }
181 }
182
183 dns_free_cache();
184 module_undepend(MODULE_NAME);
185 return NULL;
186 }
187
188 EXPORT_SCOPE char *dns_start();
189
190 static Function dns_table[] = {
191 /* 0 - 3 */
192 (Function) dns_start,
193 (Function) dns_close,
194 (Function) dns_expmem,
195 (Function) dns_report,
196 /* 4 - 7 */
197 };
198
dns_start(Function * global_funcs)199 char *dns_start(Function *global_funcs)
200 {
201 int idx;
202
203 global = global_funcs;
204
205 module_register(MODULE_NAME, dns_table, 1, 0);
206 if (!module_depend(MODULE_NAME, "evangeline", 106, 7)) {
207 module_undepend(MODULE_NAME);
208 return "This module requires Evangeline 1.0 or later.";
209 }
210
211 idx = new_dcc(&DCC_DNS, 0);
212 if (idx < 0)
213 return "NO MORE DCC CONNECTIONS -- Can't create DNS socket.";
214 if (!init_dns_core()) {
215 lostdcc(idx);
216 return "DNS initialisation failed.";
217 }
218 dcc[idx].sock = resfd;
219 dcc[idx].timeval = now;
220 strcpy(dcc[idx].nick, "(dns)");
221
222 add_hook(HOOK_SECONDLY, (Function) dns_check_expires);
223 add_hook(HOOK_DNS_HOSTBYIP, (Function) dns_lookup);
224 add_hook(HOOK_DNS_IPBYHOST, (Function) dns_forward);
225 return NULL;
226 }
227