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
00028
00029 #include "main.h"
00030 #include <netdb.h>
00031 #include <setjmp.h>
00032 #include <sys/socket.h>
00033 #include <netinet/in.h>
00034 #include <arpa/inet.h>
00035
00036 #include "dns.h"
00037
00038 extern struct dcc_t *dcc;
00039 extern int dcc_total;
00040 extern int resolve_timeout;
00041 extern time_t now;
00042 extern sigjmp_buf alarmret;
00043 extern Tcl_Interp *interp;
00044
00045 devent_t *dns_events = NULL;
00046
00047
00048
00049
00050
00051
00052 void dcc_dnswait(int idx, char *buf, int len)
00053 {
00054
00055 }
00056
00057 void eof_dcc_dnswait(int idx)
00058 {
00059 putlog(LOG_MISC, "*", "Lost connection while resolving hostname [%s/%d]",
00060 iptostr(htonl(dcc[idx].addr)), dcc[idx].port);
00061 killsock(dcc[idx].sock);
00062 lostdcc(idx);
00063 }
00064
00065 static void display_dcc_dnswait(int idx, char *buf)
00066 {
00067 sprintf(buf, "dns waited %lis", (long) now - dcc[idx].timeval);
00068 }
00069
00070 static int expmem_dcc_dnswait(void *x)
00071 {
00072 register struct dns_info *p = (struct dns_info *) x;
00073 int size = 0;
00074
00075 if (p) {
00076 size = sizeof(struct dns_info);
00077 if (p->host)
00078 size += strlen(p->host) + 1;
00079 if (p->cbuf)
00080 size += strlen(p->cbuf) + 1;
00081 }
00082 return size;
00083 }
00084
00085 static void kill_dcc_dnswait(int idx, void *x)
00086 {
00087 register struct dns_info *p = (struct dns_info *) x;
00088
00089 if (p) {
00090 if (p->host)
00091 nfree(p->host);
00092 if (p->cbuf)
00093 nfree(p->cbuf);
00094 nfree(p);
00095 }
00096 }
00097
00098 struct dcc_table DCC_DNSWAIT = {
00099 "DNSWAIT",
00100 DCT_VALIDIDX,
00101 eof_dcc_dnswait,
00102 dcc_dnswait,
00103 0,
00104 0,
00105 display_dcc_dnswait,
00106 expmem_dcc_dnswait,
00107 kill_dcc_dnswait,
00108 0
00109 };
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 static void dns_dcchostbyip(IP ip, char *hostn, int ok, void *other)
00120 {
00121 int idx;
00122
00123 for (idx = 0; idx < dcc_total; idx++) {
00124 if ((dcc[idx].type == &DCC_DNSWAIT) &&
00125 (dcc[idx].u.dns->dns_type == RES_HOSTBYIP) &&
00126 (dcc[idx].u.dns->ip == ip)) {
00127 if (dcc[idx].u.dns->host)
00128 nfree(dcc[idx].u.dns->host);
00129 dcc[idx].u.dns->host = get_data_ptr(strlen(hostn) + 1);
00130 strcpy(dcc[idx].u.dns->host, hostn);
00131 if (ok)
00132 dcc[idx].u.dns->dns_success(idx);
00133 else
00134 dcc[idx].u.dns->dns_failure(idx);
00135 }
00136 }
00137 }
00138
00139
00140
00141
00142 static void dns_dccipbyhost(IP ip, char *hostn, int ok, void *other)
00143 {
00144 int idx;
00145
00146 for (idx = 0; idx < dcc_total; idx++) {
00147 if ((dcc[idx].type == &DCC_DNSWAIT) &&
00148 (dcc[idx].u.dns->dns_type == RES_IPBYHOST) &&
00149 !egg_strcasecmp(dcc[idx].u.dns->host, hostn)) {
00150 dcc[idx].u.dns->ip = ip;
00151 if (ok)
00152 dcc[idx].u.dns->dns_success(idx);
00153 else
00154 dcc[idx].u.dns->dns_failure(idx);
00155 }
00156 }
00157 }
00158
00159 static int dns_dccexpmem(void *other)
00160 {
00161 return 0;
00162 }
00163
00164 devent_type DNS_DCCEVENT_HOSTBYIP = {
00165 "DCCEVENT_HOSTBYIP",
00166 dns_dccexpmem,
00167 dns_dcchostbyip
00168 };
00169
00170 devent_type DNS_DCCEVENT_IPBYHOST = {
00171 "DCCEVENT_IPBYHOST",
00172 dns_dccexpmem,
00173 dns_dccipbyhost
00174 };
00175
00176 void dcc_dnsipbyhost(char *hostn)
00177 {
00178 devent_t *de;
00179
00180 for (de = dns_events; de; de = de->next) {
00181 if (de->type && (de->type == &DNS_DCCEVENT_IPBYHOST) &&
00182 (de->lookup == RES_IPBYHOST)) {
00183 if (de->res_data.hostname &&
00184 !egg_strcasecmp(de->res_data.hostname, hostn))
00185
00186 return;
00187 }
00188 }
00189
00190 de = nmalloc(sizeof(devent_t));
00191 egg_bzero(de, sizeof(devent_t));
00192
00193
00194 de->next = dns_events;
00195 dns_events = de;
00196
00197 de->type = &DNS_DCCEVENT_IPBYHOST;
00198 de->lookup = RES_IPBYHOST;
00199 de->res_data.hostname = nmalloc(strlen(hostn) + 1);
00200 strcpy(de->res_data.hostname, hostn);
00201
00202
00203 dns_ipbyhost(hostn);
00204 }
00205
00206 void dcc_dnshostbyip(IP ip)
00207 {
00208 devent_t *de;
00209
00210 for (de = dns_events; de; de = de->next) {
00211 if (de->type && (de->type == &DNS_DCCEVENT_HOSTBYIP) &&
00212 (de->lookup == RES_HOSTBYIP)) {
00213 if (de->res_data.ip_addr == ip)
00214
00215 return;
00216 }
00217 }
00218
00219 de = nmalloc(sizeof(devent_t));
00220 egg_bzero(de, sizeof(devent_t));
00221
00222
00223 de->next = dns_events;
00224 dns_events = de;
00225
00226 de->type = &DNS_DCCEVENT_HOSTBYIP;
00227 de->lookup = RES_HOSTBYIP;
00228 de->res_data.ip_addr = ip;
00229
00230
00231 dns_hostbyip(ip);
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241 void dnstclcallback(char *context, char *script, int code,
00242 const char *result, int dofree) {
00243 if (code == TCL_ERROR)
00244 putlog(LOG_MISC, "*", DCC_TCLERROR, context, result);
00245 if (dofree) {
00246 nfree(context);
00247 nfree(script);
00248 }
00249 }
00250
00251
00252 static void dns_tcl_iporhostres(IP ip, char *hostn, int ok, void *other)
00253 {
00254 devent_tclinfo_t *tclinfo = (devent_tclinfo_t *) other;
00255 Tcl_DString list;
00256
00257 Tcl_DStringInit(&list);
00258 Tcl_DStringAppendElement(&list, tclinfo->proc);
00259 Tcl_DStringAppendElement(&list, iptostr(htonl(ip)));
00260 Tcl_DStringAppendElement(&list, hostn);
00261 Tcl_DStringAppendElement(&list, ok ? "1" : "0");
00262
00263 if (tclinfo->paras) {
00264 EGG_CONST char *argv[2];
00265 char *output;
00266
00267 argv[0] = Tcl_DStringValue(&list);
00268 argv[1] = tclinfo->paras;
00269 output = Tcl_Concat(2, argv);
00270
00271 do_tcl_async(tclinfo->proc, output, dnstclcallback);
00272 Tcl_Free(output);
00273 } else
00274 do_tcl_async(tclinfo->proc, Tcl_DStringValue(&list), dnstclcallback);
00275
00276 Tcl_DStringFree(&list);
00277
00278 nfree(tclinfo->proc);
00279 if (tclinfo->paras)
00280 nfree(tclinfo->paras);
00281 nfree(tclinfo);
00282 }
00283
00284 static int dns_tclexpmem(void *other)
00285 {
00286 devent_tclinfo_t *tclinfo = (devent_tclinfo_t *) other;
00287 int l = 0;
00288
00289 if (tclinfo) {
00290 l = sizeof(devent_tclinfo_t);
00291 if (tclinfo->proc)
00292 l += strlen(tclinfo->proc) + 1;
00293 if (tclinfo->paras)
00294 l += strlen(tclinfo->paras) + 1;
00295 }
00296 return l;
00297 }
00298
00299 devent_type DNS_TCLEVENT_HOSTBYIP = {
00300 "TCLEVENT_HOSTBYIP",
00301 dns_tclexpmem,
00302 dns_tcl_iporhostres
00303 };
00304
00305 devent_type DNS_TCLEVENT_IPBYHOST = {
00306 "TCLEVENT_IPBYHOST",
00307 dns_tclexpmem,
00308 dns_tcl_iporhostres
00309 };
00310
00311 static void tcl_dnsipbyhost(char *hostn, char *proc, char *paras)
00312 {
00313 devent_t *de;
00314 devent_tclinfo_t *tclinfo;
00315
00316 de = nmalloc(sizeof(devent_t));
00317 egg_bzero(de, sizeof(devent_t));
00318
00319
00320 de->next = dns_events;
00321 dns_events = de;
00322
00323 de->type = &DNS_TCLEVENT_IPBYHOST;
00324 de->lookup = RES_IPBYHOST;
00325 de->res_data.hostname = nmalloc(strlen(hostn) + 1);
00326 strcpy(de->res_data.hostname, hostn);
00327
00328
00329 tclinfo = nmalloc(sizeof(devent_tclinfo_t));
00330 tclinfo->proc = nmalloc(strlen(proc) + 1);
00331 strcpy(tclinfo->proc, proc);
00332 if (paras) {
00333 tclinfo->paras = nmalloc(strlen(paras) + 1);
00334 strcpy(tclinfo->paras, paras);
00335 } else
00336 tclinfo->paras = NULL;
00337 de->other = tclinfo;
00338
00339
00340 dns_ipbyhost(hostn);
00341 }
00342
00343 static void tcl_dnshostbyip(IP ip, char *proc, char *paras)
00344 {
00345 devent_t *de;
00346 devent_tclinfo_t *tclinfo;
00347
00348 de = nmalloc(sizeof(devent_t));
00349 egg_bzero(de, sizeof(devent_t));
00350
00351
00352 de->next = dns_events;
00353 dns_events = de;
00354
00355 de->type = &DNS_TCLEVENT_HOSTBYIP;
00356 de->lookup = RES_HOSTBYIP;
00357 de->res_data.ip_addr = ip;
00358
00359
00360 tclinfo = nmalloc(sizeof(devent_tclinfo_t));
00361 tclinfo->proc = nmalloc(strlen(proc) + 1);
00362 strcpy(tclinfo->proc, proc);
00363 if (paras) {
00364 tclinfo->paras = nmalloc(strlen(paras) + 1);
00365 strcpy(tclinfo->paras, paras);
00366 } else
00367 tclinfo->paras = NULL;
00368 de->other = tclinfo;
00369
00370
00371 dns_hostbyip(ip);
00372 }
00373
00374
00375
00376
00377
00378
00379 inline static int dnsevent_expmem(void)
00380 {
00381 devent_t *de;
00382 int tot = 0;
00383
00384 for (de = dns_events; de; de = de->next) {
00385 tot += sizeof(devent_t);
00386 if ((de->lookup == RES_IPBYHOST) && de->res_data.hostname)
00387 tot += strlen(de->res_data.hostname) + 1;
00388 if (de->type && de->type->expmem)
00389 tot += de->type->expmem(de->other);
00390 }
00391 return tot;
00392 }
00393
00394 void call_hostbyip(IP ip, char *hostn, int ok)
00395 {
00396 devent_t *de = dns_events, *ode = NULL, *nde = NULL;
00397
00398 while (de) {
00399 nde = de->next;
00400 if ((de->lookup == RES_HOSTBYIP) &&
00401 (!de->res_data.ip_addr || (de->res_data.ip_addr == ip))) {
00402
00403
00404 if (ode)
00405 ode->next = de->next;
00406 else
00407 dns_events = de->next;
00408
00409 if (de->type && de->type->event)
00410 de->type->event(ip, hostn, ok, de->other);
00411 else
00412 putlog(LOG_MISC, "*", "(!) Unknown DNS event type found: %s",
00413 (de->type && de->type->name) ? de->type->name : "<empty>");
00414 nfree(de);
00415 de = ode;
00416 }
00417 ode = de;
00418 de = nde;
00419 }
00420 }
00421
00422 void call_ipbyhost(char *hostn, IP ip, int ok)
00423 {
00424 devent_t *de = dns_events, *ode = NULL, *nde = NULL;
00425
00426 while (de) {
00427 nde = de->next;
00428 if ((de->lookup == RES_IPBYHOST) && (!de->res_data.hostname ||
00429 !egg_strcasecmp(de->res_data.hostname, hostn))) {
00430
00431
00432 if (ode)
00433 ode->next = de->next;
00434 else
00435 dns_events = de->next;
00436
00437 if (de->type && de->type->event)
00438 de->type->event(ip, hostn, ok, de->other);
00439 else
00440 putlog(LOG_MISC, "*", "(!) Unknown DNS event type found: %s",
00441 (de->type && de->type->name) ? de->type->name : "<empty>");
00442
00443 if (de->res_data.hostname)
00444 nfree(de->res_data.hostname);
00445 nfree(de);
00446 de = ode;
00447 }
00448 ode = de;
00449 de = nde;
00450 }
00451 }
00452
00453
00454
00455
00456
00457
00458 void block_dns_hostbyip(IP ip)
00459 {
00460 struct hostent *hp;
00461 unsigned long addr = htonl(ip);
00462 static char s[UHOSTLEN];
00463
00464 if (!sigsetjmp(alarmret, 1)) {
00465 alarm(resolve_timeout);
00466 hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
00467 alarm(0);
00468 if (hp)
00469 strncpyz(s, hp->h_name, sizeof s);
00470 else
00471 strcpy(s, iptostr(addr));
00472 } else {
00473 hp = NULL;
00474 strcpy(s, iptostr(addr));
00475 }
00476
00477 call_hostbyip(ip, s, hp ? 1 : 0);
00478 }
00479
00480 void block_dns_ipbyhost(char *host)
00481 {
00482 struct in_addr inaddr;
00483
00484
00485
00486 if (egg_inet_aton(host, &inaddr)) {
00487 call_ipbyhost(host, ntohl(inaddr.s_addr), 1);
00488 return;
00489 }
00490 if (!sigsetjmp(alarmret, 1)) {
00491 struct hostent *hp;
00492 struct in_addr *in;
00493 IP ip = 0;
00494
00495 alarm(resolve_timeout);
00496 hp = gethostbyname(host);
00497 alarm(0);
00498
00499 if (hp) {
00500 in = (struct in_addr *) (hp->h_addr_list[0]);
00501 ip = (IP) (in->s_addr);
00502 call_ipbyhost(host, ntohl(ip), 1);
00503 return;
00504 }
00505
00506 }
00507 call_ipbyhost(host, 0, 0);
00508 }
00509
00510
00511
00512
00513
00514
00515 int expmem_dns(void)
00516 {
00517 return dnsevent_expmem();
00518 }
00519
00520
00521
00522
00523
00524
00525
00526 static int tcl_dnslookup STDVAR
00527 {
00528 struct in_addr inaddr;
00529 Tcl_DString paras;
00530
00531 if (argc < 3) {
00532 Tcl_AppendResult(irp, "wrong # args: should be \"", argv[0],
00533 " ip-address/hostname proc ?args...?\"", NULL);
00534 return TCL_ERROR;
00535 }
00536
00537 Tcl_DStringInit(¶s);
00538 if (argc > 3) {
00539 int p;
00540
00541 for (p = 3; p < argc; p++)
00542 Tcl_DStringAppendElement(¶s, argv[p]);
00543 }
00544
00545 if (egg_inet_aton(argv[1], &inaddr))
00546 tcl_dnshostbyip(ntohl(inaddr.s_addr), argv[2], Tcl_DStringValue(¶s));
00547 else
00548 tcl_dnsipbyhost(argv[1], argv[2], Tcl_DStringValue(¶s));
00549
00550 Tcl_DStringFree(¶s);
00551 return TCL_OK;
00552 }
00553
00554 tcl_cmds tcldns_cmds[] = {
00555 {"dnslookup", tcl_dnslookup},
00556 {NULL, NULL}
00557 };