dns.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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. */
  8. #include "common.h"
  9. #include "dccutil.h"
  10. #include "net.h"
  11. #include "misc.h"
  12. #include "src/mod/dns.mod/dns.h"
  13. #include <netdb.h>
  14. #include <setjmp.h>
  15. #include <sys/socket.h>
  16. #include <netinet/in.h>
  17. #include <arpa/inet.h>
  18. #include "dns.h"
  19. extern struct dcc_t *dcc;
  20. extern int dcc_total;
  21. extern int resolve_timeout;
  22. extern time_t now;
  23. extern jmp_buf alarmret;
  24. devent_t *dns_events = NULL;
  25. /*
  26. * DCC functions
  27. */
  28. void dcc_dnswait(int idx, char *buf, int len)
  29. {
  30. /* Ignore anything now. */
  31. }
  32. void eof_dcc_dnswait(int idx)
  33. {
  34. putlog(LOG_MISC, "*", "Lost connection while resolving hostname [%s/%d]",
  35. iptostr(htonl(dcc[idx].addr)), dcc[idx].port);
  36. killsock(dcc[idx].sock);
  37. lostdcc(idx);
  38. }
  39. static void display_dcc_dnswait(int idx, char *buf)
  40. {
  41. sprintf(buf, "dns waited %lus", now - dcc[idx].timeval);
  42. }
  43. static void kill_dcc_dnswait(int idx, void *x)
  44. {
  45. register struct dns_info *p = (struct dns_info *) x;
  46. if (p) {
  47. if (p->host)
  48. free(p->host);
  49. if (p->cbuf)
  50. free(p->cbuf);
  51. free(p);
  52. }
  53. }
  54. struct dcc_table DCC_DNSWAIT =
  55. {
  56. "DNSWAIT",
  57. DCT_VALIDIDX,
  58. eof_dcc_dnswait,
  59. dcc_dnswait,
  60. 0,
  61. 0,
  62. display_dcc_dnswait,
  63. kill_dcc_dnswait,
  64. 0
  65. };
  66. /*
  67. * DCC events
  68. */
  69. /* Walk through every dcc entry and look for waiting DNS requests
  70. * of RES_HOSTBYIP for our IP address.
  71. */
  72. static void dns_dcchostbyip(IP ip, char *hostn, int ok, void *other)
  73. {
  74. int idx;
  75. for (idx = 0; idx < dcc_total; idx++) {
  76. if ((dcc[idx].type == &DCC_DNSWAIT) &&
  77. (dcc[idx].u.dns->dns_type == RES_HOSTBYIP) &&
  78. (dcc[idx].u.dns->ip == ip)) {
  79. if (dcc[idx].u.dns->host)
  80. free(dcc[idx].u.dns->host);
  81. dcc[idx].u.dns->host = calloc(1, strlen(hostn) + 1);
  82. strcpy(dcc[idx].u.dns->host, hostn);
  83. if (ok)
  84. dcc[idx].u.dns->dns_success(idx);
  85. else
  86. dcc[idx].u.dns->dns_failure(idx);
  87. }
  88. }
  89. }
  90. /* Walk through every dcc entry and look for waiting DNS requests
  91. * of RES_IPBYHOST for our hostname.
  92. */
  93. static void dns_dccipbyhost(IP ip, char *hostn, int ok, void *other)
  94. {
  95. int idx;
  96. for (idx = 0; idx < dcc_total; idx++) {
  97. if ((dcc[idx].type == &DCC_DNSWAIT) &&
  98. (dcc[idx].u.dns->dns_type == RES_IPBYHOST) &&
  99. !egg_strcasecmp(dcc[idx].u.dns->host, hostn)) {
  100. dcc[idx].u.dns->ip = ip;
  101. if (ok)
  102. dcc[idx].u.dns->dns_success(idx);
  103. else
  104. dcc[idx].u.dns->dns_failure(idx);
  105. }
  106. }
  107. }
  108. devent_type DNS_DCCEVENT_HOSTBYIP = {
  109. "DCCEVENT_HOSTBYIP",
  110. dns_dcchostbyip
  111. };
  112. devent_type DNS_DCCEVENT_IPBYHOST = {
  113. "DCCEVENT_IPBYHOST",
  114. dns_dccipbyhost
  115. };
  116. void dcc_dnsipbyhost(char *hostn)
  117. {
  118. devent_t *de = NULL;
  119. for (de = dns_events; de; de = de->next) {
  120. if (de->type && (de->type == &DNS_DCCEVENT_IPBYHOST) &&
  121. (de->lookup == RES_IPBYHOST)) {
  122. if (de->res_data.hostname &&
  123. !egg_strcasecmp(de->res_data.hostname, hostn))
  124. /* No need to add anymore. */
  125. return;
  126. }
  127. }
  128. de = calloc(1, sizeof(devent_t));
  129. /* Link into list. */
  130. de->next = dns_events;
  131. dns_events = de;
  132. de->type = &DNS_DCCEVENT_IPBYHOST;
  133. de->lookup = RES_IPBYHOST;
  134. de->res_data.hostname = strdup(hostn);
  135. /* Send request. */
  136. dns_ipbyhost(hostn);
  137. }
  138. void dcc_dnshostbyip(IP ip)
  139. {
  140. devent_t *de = NULL;
  141. for (de = dns_events; de; de = de->next) {
  142. if (de->type && (de->type == &DNS_DCCEVENT_HOSTBYIP) &&
  143. (de->lookup == RES_HOSTBYIP)) {
  144. if (de->res_data.ip_addr == ip)
  145. /* No need to add anymore. */
  146. return;
  147. }
  148. }
  149. de = calloc(1, sizeof(devent_t));
  150. /* Link into list. */
  151. de->next = dns_events;
  152. dns_events = de;
  153. de->type = &DNS_DCCEVENT_HOSTBYIP;
  154. de->lookup = RES_HOSTBYIP;
  155. de->res_data.ip_addr = ip;
  156. /* Send request. */
  157. dns_hostbyip(ip);
  158. }
  159. /*
  160. * Event functions
  161. */
  162. void call_hostbyip(IP ip, char *hostn, int ok)
  163. {
  164. devent_t *de = dns_events, *ode = NULL, *nde = NULL;
  165. while (de) {
  166. nde = de->next;
  167. if ((de->lookup == RES_HOSTBYIP) &&
  168. (!de->res_data.ip_addr || (de->res_data.ip_addr == ip))) {
  169. /* Remove the event from the list here, to avoid conflicts if one of
  170. * the event handlers re-adds another event. */
  171. if (ode)
  172. ode->next = de->next;
  173. else
  174. dns_events = de->next;
  175. if (de->type && de->type->event)
  176. de->type->event(ip, hostn, ok, de->other);
  177. else
  178. putlog(LOG_MISC, "*", "(!) Unknown DNS event type found: %s",
  179. (de->type && de->type->name) ? de->type->name : "<empty>");
  180. free(de);
  181. de = ode;
  182. }
  183. ode = de;
  184. de = nde;
  185. }
  186. }
  187. void call_ipbyhost(char *hostn, IP ip, int ok)
  188. {
  189. devent_t *de = dns_events, *ode = NULL, *nde = NULL;
  190. while (de) {
  191. nde = de->next;
  192. if ((de->lookup == RES_IPBYHOST) &&
  193. (!de->res_data.hostname ||
  194. !egg_strcasecmp(de->res_data.hostname, hostn))) {
  195. /* Remove the event from the list here, to avoid conflicts if one of
  196. * the event handlers re-adds another event. */
  197. if (ode)
  198. ode->next = de->next;
  199. else
  200. dns_events = de->next;
  201. if (de->type && de->type->event)
  202. de->type->event(ip, hostn, ok, de->other);
  203. else
  204. putlog(LOG_MISC, "*", "(!) Unknown DNS event type found: %s",
  205. (de->type && de->type->name) ? de->type->name : "<empty>");
  206. if (de->res_data.hostname)
  207. free(de->res_data.hostname);
  208. free(de);
  209. de = ode;
  210. }
  211. ode = de;
  212. de = nde;
  213. }
  214. }
  215. /*
  216. * Async DNS emulation functions
  217. */
  218. void block_dns_hostbyip(IP ip)
  219. {
  220. struct hostent *hp = NULL;
  221. unsigned long addr = htonl(ip);
  222. static char s[UHOSTLEN] = "";
  223. if (!setjmp(alarmret)) {
  224. alarm(resolve_timeout);
  225. hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
  226. alarm(0);
  227. if (hp) {
  228. strncpyz(s, hp->h_name, sizeof s);
  229. } else
  230. strcpy(s, iptostr(addr));
  231. } else {
  232. hp = NULL;
  233. strcpy(s, iptostr(addr));
  234. }
  235. /* Call hooks. */
  236. call_hostbyip(ip, s, hp ? 1 : 0);
  237. }
  238. void block_dns_ipbyhost(char *host)
  239. {
  240. struct in_addr inaddr;
  241. /* Check if someone passed us an IP address as hostname
  242. * and return it straight away */
  243. if (egg_inet_aton(host, &inaddr)) {
  244. call_ipbyhost(host, ntohl(inaddr.s_addr), 1);
  245. return;
  246. }
  247. if (!setjmp(alarmret)) {
  248. struct hostent *hp = NULL;
  249. struct in_addr *in = NULL;
  250. IP ip = 0;
  251. alarm(resolve_timeout);
  252. hp = gethostbyname(host);
  253. alarm(0);
  254. if (hp) {
  255. in = (struct in_addr *) (hp->h_addr_list[0]);
  256. ip = (IP) (in->s_addr);
  257. call_ipbyhost(host, ntohl(ip), 1);
  258. return;
  259. }
  260. /* Fall through. */
  261. }
  262. call_ipbyhost(host, 0, 0);
  263. }