00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #define MODULE_NAME "dns"
00028
00029 #include "src/mod/module.h"
00030 #include "dns.h"
00031
00032 static void dns_event_success(struct resolve *rp, int type);
00033 static void dns_event_failure(struct resolve *rp, int type);
00034
00035 static Function *global = NULL;
00036
00037 static int dns_maxsends = 4;
00038 static int dns_retrydelay = 3;
00039 static int dns_cache = 86400;
00040 static int dns_negcache = 600;
00041
00042 static char dns_servers[121] = "";
00043
00044 #include "coredns.c"
00045
00046
00047
00048
00049
00050 static void dns_event_success(struct resolve *rp, int type)
00051 {
00052 if (!rp)
00053 return;
00054
00055 if (type == T_PTR) {
00056 debug2("DNS resolved %s to %s", iptostr(rp->ip), rp->hostn);
00057 call_hostbyip(ntohl(rp->ip), rp->hostn, 1);
00058 } else if (type == T_A) {
00059 debug2("DNS resolved %s to %s", rp->hostn, iptostr(rp->ip));
00060 call_ipbyhost(rp->hostn, ntohl(rp->ip), 1);
00061 }
00062 }
00063
00064 static void dns_event_failure(struct resolve *rp, int type)
00065 {
00066 if (!rp)
00067 return;
00068
00069 if (type == T_PTR) {
00070 static char s[UHOSTLEN];
00071
00072 debug1("DNS resolve failed for %s", iptostr(rp->ip));
00073 strcpy(s, iptostr(rp->ip));
00074 call_hostbyip(ntohl(rp->ip), s, 0);
00075 } else if (type == T_A) {
00076 debug1("DNS resolve failed for %s", rp->hostn);
00077 call_ipbyhost(rp->hostn, 0, 0);
00078 } else
00079 debug2("DNS resolve failed for unknown %s / %s", iptostr(rp->ip),
00080 nonull(rp->hostn));
00081 return;
00082 }
00083
00084
00085
00086
00087
00088
00089 static void eof_dns_socket(int idx)
00090 {
00091 putlog(LOG_MISC, "*", "DNS Error: socket closed.");
00092 killsock(dcc[idx].sock);
00093
00094 if (init_dns_network()) {
00095 putlog(LOG_MISC, "*", "DNS socket successfully reopened!");
00096 dcc[idx].sock = resfd;
00097 dcc[idx].timeval = now;
00098 } else
00099 lostdcc(idx);
00100 }
00101
00102 static void dns_socket(int idx, char *buf, int len)
00103 {
00104 dns_ack();
00105 }
00106
00107 static void display_dns_socket(int idx, char *buf)
00108 {
00109 strcpy(buf, "dns (ready)");
00110 }
00111
00112 static struct dcc_table DCC_DNS = {
00113 "DNS",
00114 DCT_LISTEN,
00115 eof_dns_socket,
00116 dns_socket,
00117 NULL,
00118 NULL,
00119 display_dns_socket,
00120 NULL,
00121 NULL,
00122 NULL
00123 };
00124
00125 static tcl_ints dnsints[] = {
00126 {"dns-maxsends", &dns_maxsends, 0},
00127 {"dns-retrydelay", &dns_retrydelay, 0},
00128 {"dns-cache", &dns_cache, 0},
00129 {"dns-negcache", &dns_negcache, 0},
00130 {NULL, NULL, 0}
00131 };
00132
00133 static tcl_strings dnsstrings[] = {
00134 {"dns-servers", dns_servers, 120, 0},
00135 {NULL, NULL, 0, 0}
00136 };
00137
00138 static char *dns_change(ClientData cdata, Tcl_Interp *irp,
00139 EGG_CONST char *name1,
00140 EGG_CONST char *name2, int flags)
00141 {
00142 char buf[121], *p;
00143 unsigned short port;
00144 int i, lc, code;
00145 EGG_CONST char **list, *slist;
00146
00147 if (flags & (TCL_TRACE_READS | TCL_TRACE_UNSETS)) {
00148 Tcl_DString ds;
00149
00150 Tcl_DStringInit(&ds);
00151 for (i = 0; i < _res.nscount; i++) {
00152 snprintf(buf, sizeof buf, "%s:%d",
00153 iptostr(_res.nsaddr_list[i].sin_addr.s_addr),
00154 ntohs(_res.nsaddr_list[i].sin_port));
00155 Tcl_DStringAppendElement(&ds, buf);
00156 }
00157 slist = Tcl_DStringValue(&ds);
00158 Tcl_SetVar2(interp, name1, name2, slist, TCL_GLOBAL_ONLY);
00159 Tcl_DStringFree(&ds);
00160 } else {
00161 slist = Tcl_GetVar2(interp, name1, name2, TCL_GLOBAL_ONLY);
00162 code = Tcl_SplitList(interp, slist, &lc, &list);
00163 if (code == TCL_ERROR)
00164 return "variable must be a list";
00165
00166 _res.nscount = 0;
00167 for (i = 0; i < lc; i++) {
00168 if ((p = strchr(list[i], ':'))) {
00169 *p++ = 0;
00170
00171 port = atoi(p);
00172 } else
00173 port = NAMESERVER_PORT;
00174
00175 if (egg_inet_aton(list[i], &_res.nsaddr_list[_res.nscount].sin_addr)) {
00176 _res.nsaddr_list[_res.nscount].sin_port = htons(port);
00177 _res.nsaddr_list[_res.nscount].sin_family = AF_INET;
00178 _res.nscount++;
00179 }
00180 }
00181 Tcl_Free((char *) list);
00182 }
00183 return NULL;
00184 }
00185
00186
00187
00188
00189
00190
00191 static void dns_free_cache(void)
00192 {
00193 struct resolve *rp, *rpnext;
00194
00195 for (rp = expireresolves; rp; rp = rpnext) {
00196 rpnext = rp->next;
00197 if (rp->hostn)
00198 nfree(rp->hostn);
00199 nfree(rp);
00200 }
00201 expireresolves = NULL;
00202 }
00203
00204 static int dns_cache_expmem(void)
00205 {
00206 struct resolve *rp;
00207 int size = 0;
00208
00209 for (rp = expireresolves; rp; rp = rp->next) {
00210 size += sizeof(struct resolve);
00211 if (rp->hostn)
00212 size += strlen(rp->hostn) + 1;
00213 }
00214 return size;
00215 }
00216
00217 static int dns_expmem(void)
00218 {
00219 return dns_cache_expmem();
00220 }
00221
00222 static int dns_report(int idx, int details)
00223 {
00224 if (details) {
00225 int i, size = dns_expmem();
00226
00227 dprintf(idx, " Async DNS resolver is active.\n");
00228 dprintf(idx, " DNS server list:");
00229 for (i = 0; i < _res.nscount; i++)
00230 dprintf(idx, " %s:%d", iptostr(_res.nsaddr_list[i].sin_addr.s_addr),
00231 ntohs(_res.nsaddr_list[i].sin_port));
00232 dprintf(idx, "\n");
00233 dprintf(idx, " Using %d byte%s of memory\n", size,
00234 (size != 1) ? "s" : "");
00235 }
00236 return 0;
00237 }
00238
00239 static char *dns_close()
00240 {
00241 int i;
00242
00243 del_hook(HOOK_DNS_HOSTBYIP, (Function) dns_lookup);
00244 del_hook(HOOK_DNS_IPBYHOST, (Function) dns_forward);
00245 del_hook(HOOK_SECONDLY, (Function) dns_check_expires);
00246 rem_tcl_ints(dnsints);
00247 rem_tcl_strings(dnsstrings);
00248 Tcl_UntraceVar(interp, "dns-servers",
00249 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
00250 dns_change, NULL);
00251
00252 for (i = 0; i < dcc_total; i++) {
00253 if (dcc[i].type == &DCC_DNS && dcc[i].sock == resfd) {
00254 killsock(dcc[i].sock);
00255 lostdcc(i);
00256 break;
00257 }
00258 }
00259
00260 dns_free_cache();
00261 module_undepend(MODULE_NAME);
00262 return NULL;
00263 }
00264
00265 EXPORT_SCOPE char *dns_start();
00266
00267 static Function dns_table[] = {
00268
00269 (Function) dns_start,
00270 (Function) dns_close,
00271 (Function) dns_expmem,
00272 (Function) dns_report,
00273
00274 };
00275
00276 char *dns_start(Function *global_funcs)
00277 {
00278 int idx;
00279
00280 global = global_funcs;
00281
00282 module_register(MODULE_NAME, dns_table, 1, 0);
00283 if (!module_depend(MODULE_NAME, "eggdrop", 106, 0)) {
00284 module_undepend(MODULE_NAME);
00285 return "This module requires Eggdrop 1.6.0 or later.";
00286 }
00287
00288 idx = new_dcc(&DCC_DNS, 0);
00289 if (idx < 0)
00290 return "NO MORE DCC CONNECTIONS -- Can't create DNS socket.";
00291 if (!init_dns_core()) {
00292 lostdcc(idx);
00293 return "DNS initialisation failed.";
00294 }
00295 dcc[idx].sock = resfd;
00296 dcc[idx].timeval = now;
00297 strcpy(dcc[idx].nick, "(dns)");
00298
00299 Tcl_TraceVar(interp, "dns-servers",
00300 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
00301 dns_change, NULL);
00302 add_hook(HOOK_SECONDLY, (Function) dns_check_expires);
00303 add_hook(HOOK_DNS_HOSTBYIP, (Function) dns_lookup);
00304 add_hook(HOOK_DNS_IPBYHOST, (Function) dns_forward);
00305 add_tcl_ints(dnsints);
00306 add_tcl_strings(dnsstrings);
00307 return NULL;
00308 }