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