dns.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. /* Copyright 2003 Roger Dingledine. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #include "or.h"
  5. #define MAX_ADDRESSLEN 256
  6. #define MAX_DNSSLAVES 50
  7. #define MIN_DNSSLAVES 3 /* 1 for the tor process, 3 slaves */
  8. struct slave_data_t {
  9. int fd; /* socket to talk on */
  10. int num_processed; /* number of times we've used this slave */
  11. char busy; /* whether this slave currently has a task */
  12. char question[MAX_ADDRESSLEN]; /* the hostname that we're resolving */
  13. unsigned char question_len; /* how many bytes in question */
  14. char answer[MAX_ADDRESSLEN]; /* the answer to the question */
  15. unsigned char answer_len; /* how many bytes in answer */
  16. };
  17. struct slave_data_t slave_data[MAX_DNSSLAVES+1];
  18. struct pollfd poll_data[MAX_DNSSLAVES+1];
  19. static int dns_spawn_slave(void);
  20. static int dns_read_block(int fd, char *string, unsigned char *len);
  21. static int dns_write_block(int fd, char *string, unsigned char len);
  22. static int dns_read_tor_question(int index);
  23. static int dns_read_slave_response(int index);
  24. static int dns_find_idle_slave(int max);
  25. static int dns_assign_to_slave(int from, int to);
  26. static int dns_master_to_tor(int from, int to);
  27. static void dns_master_main(int fd);
  28. static int dns_tor_to_master(connection_t *exitconn);
  29. static int dns_found_answer(char *question, uint32_t answer, uint32_t valid);
  30. int connection_dns_finished_flushing(connection_t *conn) {
  31. assert(conn && conn->type == CONN_TYPE_DNSMASTER);
  32. connection_stop_writing(conn);
  33. return 0;
  34. }
  35. int connection_dns_process_inbuf(connection_t *conn) {
  36. unsigned char length;
  37. char buf[MAX_ADDRESSLEN];
  38. char *question;
  39. uint32_t answer;
  40. assert(conn && conn->type == CONN_TYPE_DNSMASTER);
  41. assert(conn->state == DNSMASTER_STATE_OPEN);
  42. if(conn->inbuf_reached_eof) {
  43. log(LOG_ERR,"connection_dns_process_inbuf(): Read eof. No more dnsmaster!");
  44. return -1;
  45. }
  46. assert(conn->inbuf);
  47. if(conn->inbuf_datalen <= 0)
  48. return 0;
  49. /* peek into the inbuf, so we can check if it's all here */
  50. length = *conn->inbuf; /* warning: abstraction violation :( */
  51. assert(length < 240);
  52. if(conn->inbuf_datalen < 1+length) { /* entire answer available? */
  53. log(LOG_INFO,"connection_dns_process_inbuf(): %d available, waiting for %d.", conn->inbuf_datalen, length+1);
  54. return 0; /* not yet */
  55. }
  56. if(connection_fetch_from_buf(buf,1+length,conn) < 0) {
  57. log(LOG_ERR,"connection_dns_process_inbuf(): Broken inbuf. No more dnsmaster!");
  58. return -1;
  59. }
  60. question = buf+1;
  61. log(LOG_DEBUG,"connection_dns_process_inbuf(): length %d, question '%s', strlen question %d", length, question, strlen(question));
  62. assert(length == 4 + strlen(question) + 1);
  63. answer = *(uint32_t *)(buf+1+length-4);
  64. dns_found_answer(question, answer, (answer != 0));
  65. return connection_process_inbuf(conn); /* process the remainder of the buffer */
  66. }
  67. /* return -1 if error, else the fd that can talk to the dns master */
  68. int dns_master_start(void) {
  69. connection_t *conn;
  70. pid_t pid;
  71. int fd[2];
  72. if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) {
  73. log(LOG_ERR,"dns_master_start(): socketpair failed.");
  74. return -1;
  75. }
  76. pid = fork();
  77. if(pid < 0) {
  78. log(LOG_ERR,"dns_master_start(): fork failed.");
  79. return -1;
  80. }
  81. if(pid == 0) { /* i'm the child */
  82. log(LOG_DEBUG,"dns_master_start(): child says fd0 %d, fd1 %d.", fd[0], fd[1]);
  83. close(fd[0]);
  84. dns_master_main(fd[1]);
  85. assert(0); /* never gets here */
  86. }
  87. /* i'm the parent */
  88. close(fd[1]);
  89. fcntl(fd[0], F_SETFL, O_NONBLOCK); /* set s to non-blocking */
  90. conn = connection_new(CONN_TYPE_DNSMASTER);
  91. if(!conn) {
  92. log(LOG_INFO,"dns_master_start(): connection_new failed. Giving up.");
  93. /* XXX tell the dnsmaster to die */
  94. return -1;
  95. }
  96. conn->s = fd[0];
  97. conn->address = strdup("localhost");
  98. conn->receiver_bucket = -1; /* edge connections don't do receiver buckets */
  99. conn->bandwidth = -1;
  100. if(connection_add(conn) < 0) { /* no space, forget it */
  101. log(LOG_INFO,"dns_master_start(): connection_add failed. Giving up.");
  102. connection_free(conn);
  103. /* XXX tell the dnsmaster to die */
  104. return -1;
  105. }
  106. conn->state = DNSMASTER_STATE_OPEN;
  107. connection_start_reading(conn);
  108. log(LOG_INFO,"dns_master_start(): dns handler is spawned.");
  109. return fd[0];
  110. }
  111. static void dns_slave_main(int fd) {
  112. char question[MAX_ADDRESSLEN];
  113. unsigned char question_len;
  114. struct hostent *rent;
  115. for(;;) {
  116. if(dns_read_block(fd, question, &question_len) < 0) { /* the master wants us to die */
  117. log(LOG_INFO,"dns_slave_main(): eof on read from master. Exiting.");
  118. exit(0);
  119. }
  120. rent = gethostbyname(question);
  121. if (!rent) {
  122. log(LOG_INFO,"dns_slave_main(): Could not resolve dest addr %s. Returning nulls.",question);
  123. if(dns_write_block(fd, "\0\0\0\0", 4) < 0) {
  124. log(LOG_INFO,"dns_slave_main(): writing to master failed. Exiting.");
  125. exit(0);
  126. }
  127. } else {
  128. if(dns_write_block(fd, rent->h_addr, rent->h_length) < 0) {
  129. log(LOG_INFO,"dns_slave_main(): writing to master failed. Exiting.");
  130. exit(0);
  131. }
  132. log(LOG_INFO,"dns_slave_main(): Answered question '%s'.",question);
  133. }
  134. }
  135. }
  136. static int dns_spawn_slave(void) {
  137. pid_t pid;
  138. int fd[2];
  139. if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) {
  140. perror("socketpair");
  141. exit(1);
  142. }
  143. pid = fork();
  144. if(pid < 0) {
  145. perror("fork");
  146. exit(1);
  147. }
  148. if(pid == 0) { /* i'm the child */
  149. close(fd[0]);
  150. dns_slave_main(fd[1]);
  151. assert(0); /* never gets here */
  152. }
  153. /* i'm the parent */
  154. log(LOG_INFO,"dns_spawn_slave(): just spawned a slave."); // XXX change to debug
  155. close(fd[1]);
  156. return fd[0];
  157. }
  158. /* read a first byte from fd, put it into *len. Then read *len
  159. * bytes from fd and put it into string.
  160. * Return -1 if eof or read error or bad len, else return 0.
  161. */
  162. int dns_read_block(int fd, char *string, unsigned char *len) {
  163. int read_result;
  164. log(LOG_DEBUG,"dns_read_block(): Calling read to learn length (fd %d).", fd);
  165. read_result = read(fd, len, 1);
  166. log(LOG_DEBUG,"dns_read_block(): read finished, returned %d", read_result);
  167. if (read_result < 0) {
  168. log(LOG_INFO,"dns_read_block(): read len returned error");
  169. return -1;
  170. } else if (read_result == 0) {
  171. log(LOG_INFO,"dns_read_block(): Encountered eof reading len");
  172. return -1;
  173. } else if (*len <= 0) {
  174. log(LOG_INFO,"dns_read_block(): len not >0");
  175. return -1;
  176. }
  177. log(LOG_DEBUG,"dns_read_block(): Calling read to get string, length %u.", *len);
  178. read_result = read(fd, string, *len);
  179. if (read_result < 0) {
  180. log(LOG_INFO,"dns_read_block(): read string returned error");
  181. return -1;
  182. } else if (read_result == 0) {
  183. log(LOG_INFO,"dns_read_block(): Encountered eof reading string");
  184. return -1;
  185. }
  186. string[*len] = 0; /* null terminate it, just in case */
  187. // log(LOG_INFO,"dns_read_block(): Read '%s', len %u.",string,*len);
  188. return 0;
  189. }
  190. /* write ("%c%s", string, len) onto fd */
  191. static int dns_write_block(int fd, char *string, unsigned char len) {
  192. int write_result;
  193. int written=0;
  194. char tmp[257];
  195. assert(len <= 250);
  196. tmp[0] = len;
  197. memcpy(tmp+1, string, len);
  198. log(LOG_DEBUG,"dns_write_block(): writing length %u, fd %d.", len, fd);
  199. while(written < len+1) {
  200. write_result = write(fd, tmp, len+1-written);
  201. if (write_result < 0) {
  202. return -1;
  203. }
  204. written += write_result;
  205. }
  206. return 0;
  207. }
  208. /* pull in question. block until we've read everything.
  209. * return -1 if eof. */
  210. static int dns_read_tor_question(int index) {
  211. log(LOG_DEBUG,"dns_read_tor_question(): Pulling question from tor");
  212. if(dns_read_block(slave_data[index].fd,
  213. slave_data[index].question,
  214. &slave_data[index].question_len) < 0)
  215. return -1;
  216. // log(LOG_INFO,"dns_read_tor_question(): Read question '%s'",slave_data[index].question);
  217. return 0;
  218. }
  219. /* pull in answer. block until we've read it. return -1 if eof. */
  220. static int dns_read_slave_response(int index) {
  221. if(dns_read_block(slave_data[index].fd,
  222. slave_data[index].answer,
  223. &slave_data[index].answer_len) < 0)
  224. return -1;
  225. return 0;
  226. }
  227. static int dns_find_idle_slave(int max) {
  228. int i;
  229. for(i=1;i<max;i++)
  230. if(slave_data[i].busy == 0) {
  231. log(LOG_DEBUG,"dns_find_idle_slave(): slave %d is chosen.",i);
  232. return i;
  233. }
  234. assert(0); /* should never get here */
  235. }
  236. static int dns_assign_to_slave(int from, int to) {
  237. slave_data[to].question_len = slave_data[from].question_len;
  238. memcpy(slave_data[to].question, slave_data[from].question, slave_data[from].question_len);
  239. // slave_data[from].question_len = 0;
  240. log(LOG_DEBUG,"dns_assign_to_slave(): from index %d to %d (writing fd %d)",from,to,slave_data[to].fd);
  241. if(dns_write_block(slave_data[to].fd,
  242. slave_data[to].question,
  243. slave_data[to].question_len) < 0) {
  244. log(LOG_INFO,"dns_assign_to_slave(): writing to slave failed.");
  245. return -1;
  246. }
  247. return 0;
  248. }
  249. static int dns_master_to_tor(int from, int to) {
  250. char tmp[MAX_ADDRESSLEN*2];
  251. unsigned char len;
  252. len = slave_data[from].question_len+1+slave_data[from].answer_len;
  253. memcpy(tmp, slave_data[from].question, slave_data[from].question_len);
  254. tmp[slave_data[from].question_len] = 0; /* null terminate it */
  255. memcpy(tmp+1+slave_data[from].question_len, slave_data[from].answer, slave_data[from].answer_len);
  256. log(LOG_DEBUG,"dns_master_to_tor(): question is '%s', length %d",slave_data[from].question,slave_data[from].question_len);
  257. log(LOG_DEBUG,"dns_master_to_tor(): answer is %d %d %d %d",
  258. slave_data[from].answer[0],
  259. slave_data[from].answer[1],
  260. slave_data[from].answer[2],
  261. slave_data[from].answer[3]);
  262. assert(slave_data[from].answer_len == 4);
  263. if(dns_write_block(slave_data[to].fd, tmp, len) < 0) {
  264. log(LOG_INFO,"dns_master_to_tor(): writing to tor failed.");
  265. return -1;
  266. }
  267. return 0;
  268. }
  269. static void dns_master_main(int fd) {
  270. int nfds=1; /* the 0th index is the tor process, the rest are slaves */
  271. int num_slaves_busy=0;
  272. int num_slaves_needed = MIN_DNSSLAVES;
  273. int poll_result, idle, i;
  274. poll_data[0].fd = slave_data[0].fd = fd;
  275. poll_data[0].events = POLLIN;
  276. for(;;) { /* loop forever */
  277. assert(num_slaves_needed < MAX_DNSSLAVES);
  278. while(nfds-1 < num_slaves_needed) {
  279. /* add another slave. */
  280. i = nfds;
  281. memset(&slave_data[i], 0, sizeof(struct slave_data_t));
  282. memset(&poll_data[i], 0, sizeof(struct pollfd));
  283. slave_data[i].fd = poll_data[i].fd = dns_spawn_slave();
  284. poll_data[i].events = POLLIN; /* listen always, to prevent accidental deadlock */
  285. nfds++;
  286. }
  287. /* XXX later, decide on a timeout value, to catch wedged slaves */
  288. poll_result = poll(poll_data, nfds, -1);
  289. log(LOG_DEBUG,"dns_master_main(): Poll returned -- activity!");
  290. for(i=0;i<nfds;i++) {
  291. if(poll_data[i].revents & POLLIN) {
  292. if(i==0) { /* note that we read only one question per poll loop */
  293. if(dns_read_tor_question(i) >= 0) {
  294. while(1) {
  295. idle = dns_find_idle_slave(nfds);
  296. if(dns_assign_to_slave(i, idle) >= 0)
  297. break; /* successfully assigned to one */
  298. /* XXX slave must die, recalc num slaves and num busy */
  299. }
  300. num_slaves_busy++;
  301. } else { /* error */
  302. log(LOG_INFO,"dns_master_main(): dns_read_tor_question failed. Master dying.");
  303. exit(1);
  304. }
  305. } else {
  306. if(dns_read_slave_response(i) >= 0) {
  307. if(dns_master_to_tor(i, 0) < 0) {
  308. log(LOG_INFO,"dns_master_main(): dns_master_to_tor failed. Master dying.");
  309. exit(1);
  310. }
  311. slave_data[i].busy = 0;
  312. num_slaves_busy--;
  313. poll_data[0].events = POLLIN; /* resume reading from tor if we'd stopped */
  314. } else { /* error */
  315. log(LOG_INFO,"dns_master_main(): dns_read_slave_response failed. Leaving slave stranded (FIXME)");
  316. }
  317. }
  318. }
  319. }
  320. log(LOG_DEBUG,"dns_master_main(): Finished looping over fd's.");
  321. if(num_slaves_busy >= num_slaves_needed) {
  322. if(num_slaves_needed == MAX_DNSSLAVES-1)
  323. poll_data[0].events = 0; /* stop reading from tor */
  324. else
  325. num_slaves_needed++;
  326. }
  327. }
  328. assert(0); /* should never get here */
  329. }
  330. #include "tree.h"
  331. struct pending_connection_t {
  332. struct connection_t *conn;
  333. struct pending_connection_t *next;
  334. };
  335. struct cached_resolve {
  336. SPLAY_ENTRY(cached_resolve) node;
  337. char question[MAX_ADDRESSLEN]; /* the hostname to be resolved */
  338. uint32_t answer; /* in host order. I know I'm horrible for assuming ipv4 */
  339. char state; /* 0 is pending; 1 means answer is valid; 2 means resolve failed */
  340. #define CACHE_STATE_PENDING 0
  341. #define CACHE_STATE_VALID 1
  342. #define CACHE_STATE_FAILED 2
  343. uint32_t expire; /* remove untouched items from cache after some time? */
  344. struct pending_connection_t *pending_connections;
  345. struct cached_resolve *next;
  346. };
  347. SPLAY_HEAD(cache_tree, cached_resolve) cache_root;
  348. static int compare_cached_resolves(struct cached_resolve *a, struct cached_resolve *b) {
  349. /* make this smarter one day? */
  350. return strncasecmp(a->question, b->question, MAX_ADDRESSLEN);
  351. }
  352. SPLAY_PROTOTYPE(cache_tree, cached_resolve, node, compare_cached_resolves);
  353. SPLAY_GENERATE(cache_tree, cached_resolve, node, compare_cached_resolves);
  354. void init_cache_tree(void) {
  355. SPLAY_INIT(&cache_root);
  356. }
  357. /* see if the question 'exitconn->address' has been answered. if so,
  358. * if resolve valid, put it into exitconn->addr and call
  359. * connection_exit_connect directly. If resolve failed, return -1.
  360. *
  361. * Else, if seen before and pending, add conn to the pending list,
  362. * and return 0.
  363. *
  364. * Else, if not seen before, add conn to pending list, hand to
  365. * dns farm, and return 0.
  366. */
  367. int dns_resolve(connection_t *exitconn) {
  368. struct cached_resolve *new_resolve;
  369. struct cached_resolve *resolve;
  370. struct pending_connection_t *pending_connection;
  371. new_resolve = malloc(sizeof(struct cached_resolve));
  372. memset(new_resolve, 0, sizeof(struct cached_resolve));
  373. strncpy(new_resolve->question, exitconn->address, MAX_ADDRESSLEN);
  374. /* try adding it to the tree. if it's already there it will
  375. * return it. */
  376. resolve = SPLAY_INSERT(cache_tree, &cache_root, new_resolve);
  377. if(resolve) { /* already there. free up new_resolve */
  378. free(new_resolve);
  379. switch(resolve->state) {
  380. case CACHE_STATE_PENDING:
  381. /* add us to the pending list */
  382. pending_connection = malloc(sizeof(struct pending_connection_t));
  383. pending_connection->conn = exitconn;
  384. pending_connection->next = new_resolve->pending_connections;
  385. new_resolve->pending_connections = pending_connection;
  386. return dns_tor_to_master(exitconn);
  387. case CACHE_STATE_VALID:
  388. exitconn->addr = resolve->answer;
  389. return connection_exit_connect(exitconn);
  390. case CACHE_STATE_FAILED:
  391. return -1;
  392. }
  393. } else { /* this was newly added to the tree. ask the dns farm. */
  394. new_resolve->state = CACHE_STATE_PENDING;
  395. /* add us to the pending list */
  396. pending_connection = malloc(sizeof(struct pending_connection_t));
  397. pending_connection->conn = exitconn;
  398. pending_connection->next = new_resolve->pending_connections;
  399. new_resolve->pending_connections = pending_connection;
  400. return dns_tor_to_master(exitconn);
  401. }
  402. assert(0);
  403. return 0; /* not reached; keep gcc happy */
  404. }
  405. static int dns_tor_to_master(connection_t *exitconn) {
  406. connection_t *dnsconn;
  407. unsigned char len;
  408. int do_dns_directly=0;
  409. dnsconn = connection_get_by_type(CONN_TYPE_DNSMASTER);
  410. if(!dnsconn) {
  411. log(LOG_ERR,"dns_tor_to_master(): dns master nowhere to be found!");
  412. }
  413. if(!dnsconn || do_dns_directly) {
  414. /* new version which does it all right here */
  415. struct hostent *rent;
  416. rent = gethostbyname(exitconn->address);
  417. if (!rent) {
  418. return dns_found_answer(exitconn->address, 0, 0);
  419. }
  420. return dns_found_answer(exitconn->address, *(uint32_t *)rent->h_addr, 1);
  421. }
  422. len = strlen(exitconn->address);
  423. if(connection_write_to_buf(&len, 1, dnsconn) < 0) {
  424. log(LOG_DEBUG,"dns_tor_to_master(): Couldn't write length.");
  425. return -1;
  426. }
  427. if(connection_write_to_buf(exitconn->address, len, dnsconn) < 0) {
  428. log(LOG_DEBUG,"dns_tor_to_master(): Couldn't write address.");
  429. return -1;
  430. }
  431. // log(LOG_DEBUG,"dns_tor_to_master(): submitted '%s'", address);
  432. return 0;
  433. }
  434. static int dns_found_answer(char *question, uint32_t answer, uint32_t valid) {
  435. struct pending_connection_t *pend;
  436. struct cached_resolve search;
  437. struct cached_resolve *resolve;
  438. strncpy(search.question, question, MAX_ADDRESSLEN);
  439. resolve = SPLAY_FIND(cache_tree, &cache_root, &search);
  440. if(!resolve) {
  441. log(LOG_ERR,"dns_found_answer(): Answer to unasked question '%s'? Dropping.", question);
  442. return 0;
  443. }
  444. assert(resolve->state == CACHE_STATE_PENDING);
  445. resolve->answer = ntohl(answer);
  446. if(valid)
  447. resolve->state = CACHE_STATE_VALID;
  448. else
  449. resolve->state = CACHE_STATE_FAILED;
  450. while(resolve->pending_connections) {
  451. pend = resolve->pending_connections;
  452. pend->conn->addr = resolve->answer;
  453. if(resolve->state == CACHE_STATE_FAILED || connection_exit_connect(pend->conn) < 0) {
  454. pend->conn->marked_for_close = 1;
  455. }
  456. resolve->pending_connections = pend->next;
  457. free(pend);
  458. }
  459. return 0;
  460. }