gnunet-service-dns.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2012 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file dns/gnunet-service-dns.c
  18. * @brief service to intercept and modify DNS queries (and replies) of this system
  19. * @author Christian Grothoff
  20. *
  21. * For "secure" interaction with the legacy DNS system, we permit
  22. * replies only to arrive within a 5s window (and they must match
  23. * ports, IPs and request IDs). Furthermore, we let the OS pick a
  24. * source port, opening up to 128 sockets per address family (IPv4 or
  25. * IPv6). Those sockets are closed if they are not in use for 5s
  26. * (which means they will be freshly randomized afterwards). For new
  27. * requests, we pick a random slot in the array with 128 socket slots
  28. * (and re-use an existing socket if the slot is still in use). Thus
  29. * each request will be given one of 128 random source ports, and the
  30. * 128 random source ports will also change "often" (less often if the
  31. * system is very busy, each time if we are mostly idle). At the same
  32. * time, the system will never use more than 256 UDP sockets.
  33. */
  34. #include "platform.h"
  35. #include "gnunet_util_lib.h"
  36. #include "gnunet_applications.h"
  37. #include "gnunet_constants.h"
  38. #include "gnunet_protocols.h"
  39. #include "gnunet_signatures.h"
  40. #include "dns.h"
  41. #include "gnunet_dns_service.h"
  42. #include "gnunet_dnsparser_lib.h"
  43. #include "gnunet_dnsstub_lib.h"
  44. #include "gnunet_statistics_service.h"
  45. #include "gnunet_tun_lib.h"
  46. /**
  47. * Port number for DNS
  48. */
  49. #define DNS_PORT 53
  50. /**
  51. * Generic logging shorthand
  52. */
  53. #define LOG(kind, ...) \
  54. GNUNET_log_from (kind, "dns", __VA_ARGS__);
  55. /**
  56. * Phases each request goes through.
  57. */
  58. enum RequestPhase
  59. {
  60. /**
  61. * Request has just been received.
  62. */
  63. RP_INIT,
  64. /**
  65. * Showing the request to all monitor clients. If
  66. * client list is empty, will enter QUERY phase.
  67. */
  68. RP_REQUEST_MONITOR,
  69. /**
  70. * Showing the request to PRE-RESOLUTION clients to find an answer.
  71. * If client list is empty, will trigger global DNS request.
  72. */
  73. RP_QUERY,
  74. /**
  75. * Global Internet query is now pending.
  76. */
  77. RP_INTERNET_DNS,
  78. /**
  79. * Client (or global DNS request) has resulted in a response.
  80. * Forward to all POST-RESOLUTION clients. If client list is empty,
  81. * will enter RESPONSE_MONITOR phase.
  82. */
  83. RP_MODIFY,
  84. /**
  85. * Showing the request to all monitor clients. If
  86. * client list is empty, give the result to the hijacker (and be done).
  87. */
  88. RP_RESPONSE_MONITOR,
  89. /**
  90. * Some client has told us to drop the request.
  91. */
  92. RP_DROP
  93. };
  94. /**
  95. * Entry we keep for each client.
  96. */
  97. struct ClientRecord
  98. {
  99. /**
  100. * Kept in doubly-linked list.
  101. */
  102. struct ClientRecord *next;
  103. /**
  104. * Kept in doubly-linked list.
  105. */
  106. struct ClientRecord *prev;
  107. /**
  108. * Handle to the client.
  109. */
  110. struct GNUNET_SERVICE_Client *client;
  111. /**
  112. * Message queue to talk to @a client.
  113. */
  114. struct GNUNET_MQ_Handle *mq;
  115. /**
  116. * Flags for the client.
  117. */
  118. enum GNUNET_DNS_Flags flags;
  119. };
  120. /**
  121. * Entry we keep for each active request.
  122. */
  123. struct RequestRecord
  124. {
  125. /**
  126. * List of clients that still need to see this request (each entry
  127. * is set to NULL when the client is done).
  128. */
  129. struct ClientRecord **client_wait_list;
  130. /**
  131. * Payload of the UDP packet (the UDP payload), can be either query
  132. * or already the response.
  133. */
  134. char *payload;
  135. /**
  136. * Socket we are using to transmit this request (must match if we receive
  137. * a response).
  138. */
  139. struct GNUNET_DNSSTUB_RequestSocket *rs;
  140. /**
  141. * Source address of the original request (for sending response).
  142. */
  143. struct sockaddr_storage src_addr;
  144. /**
  145. * Destination address of the original request (for potential use as exit).
  146. */
  147. struct sockaddr_storage dst_addr;
  148. /**
  149. * ID of this request, also basis for hashing. Lowest 16 bit will
  150. * be our message ID when doing a global DNS request and our index
  151. * into the 'requests' array.
  152. */
  153. uint64_t request_id;
  154. /**
  155. * Number of bytes in payload.
  156. */
  157. size_t payload_length;
  158. /**
  159. * Length of the @e client_wait_list.
  160. */
  161. unsigned int client_wait_list_length;
  162. /**
  163. * In which phase this this request?
  164. */
  165. enum RequestPhase phase;
  166. };
  167. /**
  168. * Global return value from 'main'.
  169. */
  170. static int global_ret;
  171. /**
  172. * The configuration to use
  173. */
  174. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  175. /**
  176. * Statistics.
  177. */
  178. static struct GNUNET_STATISTICS_Handle *stats;
  179. /**
  180. * Handle to DNS hijacker helper process ("gnunet-helper-dns").
  181. */
  182. static struct GNUNET_HELPER_Handle *hijacker;
  183. /**
  184. * Command-line arguments we are giving to the hijacker process.
  185. */
  186. static char *helper_argv[8];
  187. /**
  188. * Head of DLL of clients we consult.
  189. */
  190. static struct ClientRecord *clients_head;
  191. /**
  192. * Tail of DLL of clients we consult.
  193. */
  194. static struct ClientRecord *clients_tail;
  195. /**
  196. * Array of all open requests.
  197. */
  198. static struct RequestRecord requests[UINT16_MAX + 1];
  199. /**
  200. * Generator for unique request IDs.
  201. */
  202. static uint64_t request_id_gen;
  203. /**
  204. * Handle to the DNS Stub resolver.
  205. */
  206. static struct GNUNET_DNSSTUB_Context *dnsstub;
  207. /**
  208. * We're done processing a DNS request, free associated memory.
  209. *
  210. * @param rr request to clean up
  211. */
  212. static void
  213. cleanup_rr (struct RequestRecord *rr)
  214. {
  215. GNUNET_free_non_null (rr->payload);
  216. rr->payload = NULL;
  217. rr->payload_length = 0;
  218. GNUNET_array_grow (rr->client_wait_list,
  219. rr->client_wait_list_length,
  220. 0);
  221. }
  222. /**
  223. * Task run during shutdown.
  224. *
  225. * @param cls unused
  226. */
  227. static void
  228. cleanup_task (void *cls GNUNET_UNUSED)
  229. {
  230. if (NULL != hijacker)
  231. {
  232. GNUNET_HELPER_stop (hijacker, GNUNET_NO);
  233. hijacker = NULL;
  234. }
  235. for (unsigned int i=0;i<8;i++)
  236. GNUNET_free_non_null (helper_argv[i]);
  237. for (unsigned int i=0;i<=UINT16_MAX;i++)
  238. cleanup_rr (&requests[i]);
  239. if (NULL != stats)
  240. {
  241. GNUNET_STATISTICS_destroy (stats,
  242. GNUNET_NO);
  243. stats = NULL;
  244. }
  245. if (NULL != dnsstub)
  246. {
  247. GNUNET_DNSSTUB_stop (dnsstub);
  248. dnsstub = NULL;
  249. }
  250. }
  251. /**
  252. * We're done with some request, finish processing.
  253. *
  254. * @param rr request send to the network or just clean up.
  255. */
  256. static void
  257. request_done (struct RequestRecord *rr)
  258. {
  259. struct GNUNET_MessageHeader *hdr;
  260. size_t reply_len;
  261. uint16_t source_port;
  262. uint16_t destination_port;
  263. GNUNET_array_grow (rr->client_wait_list,
  264. rr->client_wait_list_length,
  265. 0);
  266. if (RP_RESPONSE_MONITOR != rr->phase)
  267. {
  268. /* no response, drop */
  269. LOG (GNUNET_ERROR_TYPE_DEBUG,
  270. "Got no response for request %llu, dropping\n",
  271. (unsigned long long) rr->request_id);
  272. cleanup_rr (rr);
  273. return;
  274. }
  275. LOG (GNUNET_ERROR_TYPE_DEBUG,
  276. "Transmitting response for request %llu\n",
  277. (unsigned long long) rr->request_id);
  278. /* send response via hijacker */
  279. reply_len = sizeof (struct GNUNET_MessageHeader);
  280. reply_len += sizeof (struct GNUNET_TUN_Layer2PacketHeader);
  281. switch (rr->src_addr.ss_family)
  282. {
  283. case AF_INET:
  284. reply_len += sizeof (struct GNUNET_TUN_IPv4Header);
  285. break;
  286. case AF_INET6:
  287. reply_len += sizeof (struct GNUNET_TUN_IPv6Header);
  288. break;
  289. default:
  290. GNUNET_break (0);
  291. cleanup_rr (rr);
  292. return;
  293. }
  294. reply_len += sizeof (struct GNUNET_TUN_UdpHeader);
  295. reply_len += rr->payload_length;
  296. if (reply_len >= GNUNET_MAX_MESSAGE_SIZE)
  297. {
  298. /* response too big, drop */
  299. GNUNET_break (0); /* how can this be? */
  300. cleanup_rr(rr);
  301. return;
  302. }
  303. {
  304. char buf[reply_len] GNUNET_ALIGN;
  305. size_t off;
  306. struct GNUNET_TUN_IPv4Header ip4;
  307. struct GNUNET_TUN_IPv6Header ip6;
  308. /* first, GNUnet message header */
  309. hdr = (struct GNUNET_MessageHeader*) buf;
  310. hdr->type = htons (GNUNET_MESSAGE_TYPE_DNS_HELPER);
  311. hdr->size = htons ((uint16_t) reply_len);
  312. off = sizeof (struct GNUNET_MessageHeader);
  313. /* first, TUN header */
  314. {
  315. struct GNUNET_TUN_Layer2PacketHeader tun;
  316. tun.flags = htons (0);
  317. if (rr->src_addr.ss_family == AF_INET)
  318. tun.proto = htons (ETH_P_IPV4);
  319. else
  320. tun.proto = htons (ETH_P_IPV6);
  321. GNUNET_memcpy (&buf[off],
  322. &tun,
  323. sizeof (struct GNUNET_TUN_Layer2PacketHeader));
  324. off += sizeof (struct GNUNET_TUN_Layer2PacketHeader);
  325. }
  326. /* now IP header */
  327. switch (rr->src_addr.ss_family)
  328. {
  329. case AF_INET:
  330. {
  331. struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr;
  332. struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr;
  333. source_port = dst->sin_port;
  334. destination_port = src->sin_port;
  335. GNUNET_TUN_initialize_ipv4_header (&ip4,
  336. IPPROTO_UDP,
  337. reply_len - off - sizeof (struct GNUNET_TUN_IPv4Header),
  338. &dst->sin_addr,
  339. &src->sin_addr);
  340. GNUNET_memcpy (&buf[off],
  341. &ip4,
  342. sizeof (ip4));
  343. off += sizeof (ip4);
  344. }
  345. break;
  346. case AF_INET6:
  347. {
  348. struct sockaddr_in6 *src = (struct sockaddr_in6 *) &rr->src_addr;
  349. struct sockaddr_in6 *dst = (struct sockaddr_in6 *) &rr->dst_addr;
  350. source_port = dst->sin6_port;
  351. destination_port = src->sin6_port;
  352. GNUNET_TUN_initialize_ipv6_header (&ip6,
  353. IPPROTO_UDP,
  354. reply_len - off - sizeof (struct GNUNET_TUN_IPv6Header),
  355. &dst->sin6_addr,
  356. &src->sin6_addr);
  357. GNUNET_memcpy (&buf[off],
  358. &ip6,
  359. sizeof (ip6));
  360. off += sizeof (ip6);
  361. }
  362. break;
  363. default:
  364. GNUNET_assert (0);
  365. }
  366. /* now UDP header */
  367. {
  368. struct GNUNET_TUN_UdpHeader udp;
  369. udp.source_port = source_port;
  370. udp.destination_port = destination_port;
  371. udp.len = htons (reply_len - off);
  372. if (AF_INET == rr->src_addr.ss_family)
  373. GNUNET_TUN_calculate_udp4_checksum (&ip4,
  374. &udp,
  375. rr->payload,
  376. rr->payload_length);
  377. else
  378. GNUNET_TUN_calculate_udp6_checksum (&ip6,
  379. &udp,
  380. rr->payload,
  381. rr->payload_length);
  382. GNUNET_memcpy (&buf[off],
  383. &udp,
  384. sizeof (udp));
  385. off += sizeof (udp);
  386. }
  387. /* now DNS payload */
  388. {
  389. GNUNET_memcpy (&buf[off], rr->payload, rr->payload_length);
  390. off += rr->payload_length;
  391. }
  392. /* final checks & sending */
  393. GNUNET_assert (off == reply_len);
  394. (void) GNUNET_HELPER_send (hijacker,
  395. hdr,
  396. GNUNET_YES,
  397. NULL, NULL);
  398. GNUNET_STATISTICS_update (stats,
  399. gettext_noop ("# DNS requests answered via TUN interface"),
  400. 1, GNUNET_NO);
  401. }
  402. /* clean up, we're done */
  403. cleanup_rr (rr);
  404. }
  405. /**
  406. * Show the payload of the given request record to the client
  407. * (and wait for a response).
  408. *
  409. * @param rr request to send to client
  410. * @param cr client to send the response to
  411. */
  412. static void
  413. send_request_to_client (struct RequestRecord *rr,
  414. struct ClientRecord *cr)
  415. {
  416. struct GNUNET_MQ_Envelope *env;
  417. struct GNUNET_DNS_Request *req;
  418. if (sizeof (struct GNUNET_DNS_Request) + rr->payload_length >= GNUNET_MAX_MESSAGE_SIZE)
  419. {
  420. GNUNET_break (0);
  421. cleanup_rr (rr);
  422. return;
  423. }
  424. LOG (GNUNET_ERROR_TYPE_DEBUG,
  425. "Sending information about request %llu to local client\n",
  426. (unsigned long long) rr->request_id);
  427. env = GNUNET_MQ_msg_extra (req,
  428. rr->payload_length,
  429. GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST);
  430. req->reserved = htonl (0);
  431. req->request_id = rr->request_id;
  432. GNUNET_memcpy (&req[1],
  433. rr->payload,
  434. rr->payload_length);
  435. GNUNET_MQ_send (cr->mq,
  436. env);
  437. }
  438. /**
  439. * Callback called from DNSSTUB resolver when a resolution
  440. * succeeded.
  441. *
  442. * @param cls NULL
  443. * @param dns the response itself
  444. * @param r number of bytes in dns
  445. */
  446. static void
  447. process_dns_result (void *cls,
  448. const struct GNUNET_TUN_DnsHeader *dns,
  449. size_t r);
  450. /**
  451. * A client has completed its processing for this
  452. * request. Move on.
  453. *
  454. * @param rr request to process further
  455. */
  456. static void
  457. next_phase (struct RequestRecord *rr)
  458. {
  459. struct ClientRecord *cr;
  460. int nz;
  461. if (rr->phase == RP_DROP)
  462. {
  463. cleanup_rr (rr);
  464. return;
  465. }
  466. nz = -1;
  467. for (unsigned int j=0;j<rr->client_wait_list_length;j++)
  468. {
  469. if (NULL != rr->client_wait_list[j])
  470. {
  471. nz = (int) j;
  472. break;
  473. }
  474. }
  475. if (-1 != nz)
  476. {
  477. send_request_to_client (rr,
  478. rr->client_wait_list[nz]);
  479. return;
  480. }
  481. /* done with current phase, advance! */
  482. LOG (GNUNET_ERROR_TYPE_DEBUG,
  483. "Request %llu now in phase %d\n",
  484. rr->request_id,
  485. rr->phase);
  486. switch (rr->phase)
  487. {
  488. case RP_INIT:
  489. rr->phase = RP_REQUEST_MONITOR;
  490. for (cr = clients_head; NULL != cr; cr = cr->next)
  491. {
  492. if (0 != (cr->flags & GNUNET_DNS_FLAG_REQUEST_MONITOR))
  493. GNUNET_array_append (rr->client_wait_list,
  494. rr->client_wait_list_length,
  495. cr);
  496. }
  497. next_phase (rr);
  498. return;
  499. case RP_REQUEST_MONITOR:
  500. rr->phase = RP_QUERY;
  501. for (cr = clients_head; NULL != cr; cr = cr->next)
  502. {
  503. if (0 != (cr->flags & GNUNET_DNS_FLAG_PRE_RESOLUTION))
  504. GNUNET_array_append (rr->client_wait_list,
  505. rr->client_wait_list_length,
  506. cr);
  507. }
  508. next_phase (rr);
  509. return;
  510. case RP_QUERY:
  511. #if 0
  512. /* TODO: optionally, use this to forward DNS requests to the
  513. *original* DNS server instead of the one we have configured...
  514. (but then we need to create a fresh dnsstub for each request
  515. *and* manage the timeout) */
  516. switch (rr->dst_addr.ss_family)
  517. {
  518. case AF_INET:
  519. salen = sizeof (struct sockaddr_in);
  520. sa = (const struct sockaddr *) &rr->dst_addr;
  521. break;
  522. case AF_INET6:
  523. salen = sizeof (struct sockaddr_in6);
  524. sa = (const struct sockaddr *) &rr->dst_addr;
  525. break;
  526. default:
  527. GNUNET_assert (0);
  528. }
  529. #endif
  530. rr->phase = RP_INTERNET_DNS;
  531. rr->rs = GNUNET_DNSSTUB_resolve (dnsstub,
  532. rr->payload,
  533. rr->payload_length,
  534. &process_dns_result,
  535. NULL);
  536. if (NULL == rr->rs)
  537. {
  538. GNUNET_STATISTICS_update (stats,
  539. gettext_noop ("# DNS exit failed (failed to open socket)"),
  540. 1,
  541. GNUNET_NO);
  542. cleanup_rr (rr);
  543. return;
  544. }
  545. return;
  546. case RP_INTERNET_DNS:
  547. rr->phase = RP_MODIFY;
  548. for (cr = clients_head; NULL != cr; cr = cr->next)
  549. {
  550. if (0 != (cr->flags & GNUNET_DNS_FLAG_POST_RESOLUTION))
  551. GNUNET_array_append (rr->client_wait_list,
  552. rr->client_wait_list_length,
  553. cr);
  554. }
  555. next_phase (rr);
  556. return;
  557. case RP_MODIFY:
  558. rr->phase = RP_RESPONSE_MONITOR;
  559. for (cr = clients_head; NULL != cr; cr = cr->next)
  560. {
  561. if (0 != (cr->flags & GNUNET_DNS_FLAG_RESPONSE_MONITOR))
  562. GNUNET_array_append (rr->client_wait_list,
  563. rr->client_wait_list_length,
  564. cr);
  565. }
  566. next_phase (rr);
  567. return;
  568. case RP_RESPONSE_MONITOR:
  569. request_done (rr);
  570. break;
  571. case RP_DROP:
  572. cleanup_rr (rr);
  573. break;
  574. default:
  575. GNUNET_break (0);
  576. cleanup_rr (rr);
  577. break;
  578. }
  579. }
  580. /**
  581. * A client connected, setup our data structures.
  582. *
  583. * @param cls unused
  584. * @param client handle of client that connected
  585. * @param mq message queue to talk to @a client
  586. * @return our `struct ClientRecord`
  587. */
  588. static void *
  589. client_connect_cb (void *cls,
  590. struct GNUNET_SERVICE_Client *client,
  591. struct GNUNET_MQ_Handle *mq)
  592. {
  593. struct ClientRecord *cr = cls;
  594. cr = GNUNET_new (struct ClientRecord);
  595. cr->client = client;
  596. cr->mq = mq;
  597. GNUNET_CONTAINER_DLL_insert (clients_head,
  598. clients_tail,
  599. cr);
  600. return cr;
  601. }
  602. /**
  603. * A client disconnected, clean up after it.
  604. *
  605. * @param cls unused
  606. * @param client handle of client that disconnected
  607. * @param app_ctx our `struct ClientRecord`
  608. */
  609. static void
  610. client_disconnect_cb (void *cls,
  611. struct GNUNET_SERVICE_Client *client,
  612. void *app_ctx)
  613. {
  614. struct ClientRecord *cr = app_ctx;
  615. struct RequestRecord *rr;
  616. GNUNET_CONTAINER_DLL_remove (clients_head,
  617. clients_tail,
  618. cr);
  619. for (unsigned int i=0;i<UINT16_MAX;i++)
  620. {
  621. rr = &requests[i];
  622. if (0 == rr->client_wait_list_length)
  623. continue; /* not in use */
  624. for (unsigned int j=0;j<rr->client_wait_list_length;j++)
  625. {
  626. if (rr->client_wait_list[j] == cr)
  627. {
  628. rr->client_wait_list[j] = NULL;
  629. next_phase (rr);
  630. }
  631. }
  632. }
  633. GNUNET_free (cr);
  634. }
  635. /**
  636. * Callback called from DNSSTUB resolver when a resolution
  637. * succeeded.
  638. *
  639. * @param cls NULL
  640. * @param dns the response itself
  641. * @param r number of bytes in dns
  642. */
  643. static void
  644. process_dns_result (void *cls,
  645. const struct GNUNET_TUN_DnsHeader *dns,
  646. size_t r)
  647. {
  648. struct RequestRecord *rr;
  649. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  650. "Processing DNS result from stub resolver\n");
  651. GNUNET_assert (NULL == cls);
  652. if (NULL == dns)
  653. return; /* ignore */
  654. rr = &requests[dns->id];
  655. if (rr->phase != RP_INTERNET_DNS)
  656. {
  657. /* unexpected / bogus reply */
  658. GNUNET_STATISTICS_update (stats,
  659. gettext_noop ("# External DNS response discarded (no matching request)"),
  660. 1, GNUNET_NO);
  661. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  662. "Received DNS reply that does not match any pending request. Dropping.\n");
  663. return;
  664. }
  665. LOG (GNUNET_ERROR_TYPE_DEBUG,
  666. "Got a response from the stub resolver for DNS request %llu intercepted locally!\n",
  667. (unsigned long long) rr->request_id);
  668. GNUNET_free_non_null (rr->payload);
  669. rr->payload = GNUNET_malloc (r);
  670. GNUNET_memcpy (rr->payload,
  671. dns,
  672. r);
  673. rr->payload_length = r;
  674. next_phase (rr);
  675. }
  676. /**
  677. * We got a new client. Make sure all new DNS requests pass by its desk.
  678. *
  679. * @param cls the client
  680. * @param reg the init message
  681. */
  682. static void
  683. handle_client_init (void *cls,
  684. const struct GNUNET_DNS_Register *reg)
  685. {
  686. struct ClientRecord *cr = cls;
  687. cr->flags = (enum GNUNET_DNS_Flags) ntohl (reg->flags);
  688. GNUNET_SERVICE_client_continue (cr->client);
  689. }
  690. /**
  691. * Check a response from a client.
  692. *
  693. * @param cls the client
  694. * @param resp the response
  695. * @return #GNUNET_OK (always fine)
  696. */
  697. static int
  698. check_client_response (void *cls,
  699. const struct GNUNET_DNS_Response *resp)
  700. {
  701. return GNUNET_OK; /* any payload is acceptable */
  702. }
  703. /**
  704. * Handle a response from a client.
  705. *
  706. * @param cls the client
  707. * @param resp the response
  708. */
  709. static void
  710. handle_client_response (void *cls,
  711. const struct GNUNET_DNS_Response *resp)
  712. {
  713. struct ClientRecord *cr = cls;
  714. struct RequestRecord *rr;
  715. uint16_t msize;
  716. uint16_t off;
  717. msize = ntohs (resp->header.size);
  718. off = (uint16_t) resp->request_id;
  719. rr = &requests[off];
  720. LOG (GNUNET_ERROR_TYPE_DEBUG,
  721. "Received DNS response with ID %llu from local client!\n",
  722. (unsigned long long) resp->request_id);
  723. if (rr->request_id != resp->request_id)
  724. {
  725. GNUNET_STATISTICS_update (stats,
  726. gettext_noop ("# Client response discarded (no matching request)"),
  727. 1,
  728. GNUNET_NO);
  729. GNUNET_SERVICE_client_continue (cr->client);
  730. return;
  731. }
  732. for (unsigned int i=0;i<rr->client_wait_list_length;i++)
  733. {
  734. if (NULL == rr->client_wait_list[i])
  735. continue;
  736. if (rr->client_wait_list[i] != cr)
  737. continue;
  738. rr->client_wait_list[i] = NULL;
  739. switch (ntohl (resp->drop_flag))
  740. {
  741. case 0: /* drop */
  742. rr->phase = RP_DROP;
  743. break;
  744. case 1: /* no change */
  745. break;
  746. case 2: /* update */
  747. msize -= sizeof (struct GNUNET_DNS_Response);
  748. if ( (sizeof (struct GNUNET_TUN_DnsHeader) > msize) ||
  749. (RP_REQUEST_MONITOR == rr->phase) ||
  750. (RP_RESPONSE_MONITOR == rr->phase) )
  751. {
  752. GNUNET_break (0);
  753. GNUNET_SERVICE_client_drop (cr->client);
  754. next_phase (rr);
  755. return;
  756. }
  757. GNUNET_free_non_null (rr->payload);
  758. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  759. "Changing DNS reply according to client specifications\n");
  760. rr->payload = GNUNET_malloc (msize);
  761. rr->payload_length = msize;
  762. GNUNET_memcpy (rr->payload, &resp[1], msize);
  763. if (rr->phase == RP_QUERY)
  764. {
  765. /* clear wait list, we're moving to MODIFY phase next */
  766. GNUNET_array_grow (rr->client_wait_list,
  767. rr->client_wait_list_length,
  768. 0);
  769. }
  770. /* if query changed to answer, move past DNS resolution phase... */
  771. if ( (RP_QUERY == rr->phase) &&
  772. (rr->payload_length > sizeof (struct GNUNET_TUN_DnsHeader)) &&
  773. ((struct GNUNET_TUN_DnsFlags*)&(((struct GNUNET_TUN_DnsHeader*) rr->payload)->flags))->query_or_response == 1)
  774. {
  775. rr->phase = RP_INTERNET_DNS;
  776. GNUNET_array_grow (rr->client_wait_list,
  777. rr->client_wait_list_length,
  778. 0);
  779. }
  780. break;
  781. }
  782. next_phase (rr);
  783. GNUNET_SERVICE_client_continue (cr->client);
  784. return;
  785. }
  786. /* odd, client was not on our list for the request, that ought
  787. to be an error */
  788. GNUNET_break (0);
  789. GNUNET_SERVICE_client_drop (cr->client);
  790. }
  791. /**
  792. * Functions with this signature are called whenever a complete
  793. * message is received by the tokenizer from the DNS hijack process.
  794. *
  795. * @param cls closure
  796. * @param message the actual message, a DNS request we should handle
  797. */
  798. static int
  799. process_helper_messages (void *cls,
  800. const struct GNUNET_MessageHeader *message)
  801. {
  802. uint16_t msize;
  803. const struct GNUNET_TUN_Layer2PacketHeader *tun;
  804. const struct GNUNET_TUN_IPv4Header *ip4;
  805. const struct GNUNET_TUN_IPv6Header *ip6;
  806. const struct GNUNET_TUN_UdpHeader *udp;
  807. const struct GNUNET_TUN_DnsHeader *dns;
  808. struct RequestRecord *rr;
  809. struct sockaddr_in *srca4;
  810. struct sockaddr_in6 *srca6;
  811. struct sockaddr_in *dsta4;
  812. struct sockaddr_in6 *dsta6;
  813. LOG (GNUNET_ERROR_TYPE_DEBUG,
  814. "Intercepted message via DNS hijacker\n");
  815. msize = ntohs (message->size);
  816. if (msize < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_TUN_IPv4Header))
  817. {
  818. /* non-IP packet received on TUN!? */
  819. GNUNET_break (0);
  820. return GNUNET_OK;
  821. }
  822. msize -= sizeof (struct GNUNET_MessageHeader);
  823. tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
  824. msize -= sizeof (struct GNUNET_TUN_Layer2PacketHeader);
  825. switch (ntohs (tun->proto))
  826. {
  827. case ETH_P_IPV4:
  828. ip4 = (const struct GNUNET_TUN_IPv4Header *) &tun[1];
  829. ip6 = NULL; /* make compiler happy */
  830. if ( (msize < sizeof (struct GNUNET_TUN_IPv4Header)) ||
  831. (ip4->version != 4) ||
  832. (ip4->header_length != sizeof (struct GNUNET_TUN_IPv4Header) / 4) ||
  833. (ntohs(ip4->total_length) != msize) ||
  834. (ip4->protocol != IPPROTO_UDP) )
  835. {
  836. /* non-IP/UDP packet received on TUN (or with options) */
  837. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  838. _("Received malformed IPv4-UDP packet on TUN interface.\n"));
  839. return GNUNET_OK;
  840. }
  841. udp = (const struct GNUNET_TUN_UdpHeader*) &ip4[1];
  842. msize -= sizeof (struct GNUNET_TUN_IPv4Header);
  843. break;
  844. case ETH_P_IPV6:
  845. ip4 = NULL; /* make compiler happy */
  846. ip6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
  847. if ( (msize < sizeof (struct GNUNET_TUN_IPv6Header)) ||
  848. (ip6->version != 6) ||
  849. (ntohs (ip6->payload_length) != msize - sizeof (struct GNUNET_TUN_IPv6Header)) ||
  850. (ip6->next_header != IPPROTO_UDP) )
  851. {
  852. /* non-IP/UDP packet received on TUN (or with extensions) */
  853. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  854. _("Received malformed IPv6-UDP packet on TUN interface.\n"));
  855. return GNUNET_OK;
  856. }
  857. udp = (const struct GNUNET_TUN_UdpHeader *) &ip6[1];
  858. msize -= sizeof (struct GNUNET_TUN_IPv6Header);
  859. break;
  860. default:
  861. /* non-IP packet received on TUN!? */
  862. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  863. _("Got non-IP packet with %u bytes and protocol %u from TUN\n"),
  864. (unsigned int) msize,
  865. ntohs (tun->proto));
  866. return GNUNET_OK;
  867. }
  868. if ( (msize <= sizeof (struct GNUNET_TUN_UdpHeader) + sizeof (struct GNUNET_TUN_DnsHeader)) ||
  869. (DNS_PORT != ntohs (udp->destination_port)) )
  870. {
  871. /* non-DNS packet received on TUN, ignore */
  872. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  873. _("DNS interceptor got non-DNS packet (dropped)\n"));
  874. GNUNET_STATISTICS_update (stats,
  875. gettext_noop ("# Non-DNS UDP packet received via TUN interface"),
  876. 1, GNUNET_NO);
  877. return GNUNET_OK;
  878. }
  879. msize -= sizeof (struct GNUNET_TUN_UdpHeader);
  880. dns = (const struct GNUNET_TUN_DnsHeader*) &udp[1];
  881. rr = &requests[dns->id];
  882. /* clean up from previous request */
  883. GNUNET_free_non_null (rr->payload);
  884. rr->payload = NULL;
  885. GNUNET_array_grow (rr->client_wait_list,
  886. rr->client_wait_list_length,
  887. 0);
  888. /* setup new request */
  889. rr->phase = RP_INIT;
  890. switch (ntohs (tun->proto))
  891. {
  892. case ETH_P_IPV4:
  893. {
  894. srca4 = (struct sockaddr_in*) &rr->src_addr;
  895. dsta4 = (struct sockaddr_in*) &rr->dst_addr;
  896. memset (srca4, 0, sizeof (struct sockaddr_in));
  897. memset (dsta4, 0, sizeof (struct sockaddr_in));
  898. srca4->sin_family = AF_INET;
  899. dsta4->sin_family = AF_INET;
  900. srca4->sin_addr = ip4->source_address;
  901. dsta4->sin_addr = ip4->destination_address;
  902. srca4->sin_port = udp->source_port;
  903. dsta4->sin_port = udp->destination_port;
  904. #if HAVE_SOCKADDR_IN_SIN_LEN
  905. srca4->sin_len = sizeof (struct sockaddr_in);
  906. dsta4->sin_len = sizeof (struct sockaddr_in);
  907. #endif
  908. }
  909. break;
  910. case ETH_P_IPV6:
  911. {
  912. srca6 = (struct sockaddr_in6*) &rr->src_addr;
  913. dsta6 = (struct sockaddr_in6*) &rr->dst_addr;
  914. memset (srca6, 0, sizeof (struct sockaddr_in6));
  915. memset (dsta6, 0, sizeof (struct sockaddr_in6));
  916. srca6->sin6_family = AF_INET6;
  917. dsta6->sin6_family = AF_INET6;
  918. srca6->sin6_addr = ip6->source_address;
  919. dsta6->sin6_addr = ip6->destination_address;
  920. srca6->sin6_port = udp->source_port;
  921. dsta6->sin6_port = udp->destination_port;
  922. #if HAVE_SOCKADDR_IN_SIN_LEN
  923. srca6->sin6_len = sizeof (struct sockaddr_in6);
  924. dsta6->sin6_len = sizeof (struct sockaddr_in6);
  925. #endif
  926. }
  927. break;
  928. default:
  929. GNUNET_assert (0);
  930. }
  931. rr->payload = GNUNET_malloc (msize);
  932. rr->payload_length = msize;
  933. GNUNET_memcpy (rr->payload, dns, msize);
  934. rr->request_id = dns->id | (request_id_gen << 16);
  935. request_id_gen++;
  936. LOG (GNUNET_ERROR_TYPE_DEBUG,
  937. "Creating new DNS request %llu\n",
  938. (unsigned long long) rr->request_id);
  939. GNUNET_STATISTICS_update (stats,
  940. gettext_noop ("# DNS requests received via TUN interface"),
  941. 1, GNUNET_NO);
  942. /* start request processing state machine */
  943. next_phase (rr);
  944. return GNUNET_OK;
  945. }
  946. /**
  947. * @param cls closure
  948. * @param cfg_ configuration to use
  949. * @param service the initialized service
  950. */
  951. static void
  952. run (void *cls,
  953. const struct GNUNET_CONFIGURATION_Handle *cfg_,
  954. struct GNUNET_SERVICE_Handle *service)
  955. {
  956. char *ifc_name;
  957. char *ipv4addr;
  958. char *ipv4mask;
  959. char *ipv6addr;
  960. char *ipv6prefix;
  961. char *dns_exit;
  962. char *helper_path;
  963. char *binary;
  964. int nortsetup;
  965. cfg = cfg_;
  966. stats = GNUNET_STATISTICS_create ("dns", cfg);
  967. GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
  968. cls);
  969. dnsstub = GNUNET_DNSSTUB_start (128);
  970. /* TODO: support multiple DNS_EXIT servers being configured */
  971. /* TODO: see above TODO on using DNS server from original packet.
  972. Not sure which is best... */
  973. dns_exit = NULL;
  974. if ( (GNUNET_OK !=
  975. GNUNET_CONFIGURATION_get_value_string (cfg,
  976. "dns",
  977. "DNS_EXIT",
  978. &dns_exit)) ||
  979. (GNUNET_OK !=
  980. GNUNET_DNSSTUB_add_dns_ip (dnsstub,
  981. dns_exit)) )
  982. {
  983. GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
  984. "dns",
  985. "DNS_EXIT",
  986. _("need a valid IPv4 or IPv6 address\n"));
  987. GNUNET_free_non_null (dns_exit);
  988. }
  989. helper_path = NULL;
  990. GNUNET_CONFIGURATION_get_value_string (cfg,
  991. "DNS",
  992. "HELPER_PATH",
  993. &helper_path);
  994. binary = GNUNET_OS_get_binary_path ("gnunet-helper-dns", helper_path);
  995. GNUNET_free_non_null (helper_path);
  996. if (GNUNET_YES !=
  997. GNUNET_OS_check_helper_binary (binary,
  998. GNUNET_YES,
  999. NULL)) // TODO: once we have a windows-testcase, add test parameters here
  1000. {
  1001. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1002. _("`%s' must be installed SUID, will not run DNS interceptor\n"),
  1003. binary);
  1004. global_ret = 1;
  1005. GNUNET_free (binary);
  1006. return;
  1007. }
  1008. helper_argv[0] = GNUNET_strdup ("gnunet-dns");
  1009. if (GNUNET_SYSERR ==
  1010. GNUNET_CONFIGURATION_get_value_string (cfg,
  1011. "dns",
  1012. "IFNAME",
  1013. &ifc_name))
  1014. {
  1015. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1016. "No entry 'IFNAME' in configuration!\n");
  1017. GNUNET_free (binary);
  1018. GNUNET_SCHEDULER_shutdown ();
  1019. return;
  1020. }
  1021. helper_argv[1] = ifc_name;
  1022. if ( (GNUNET_SYSERR ==
  1023. GNUNET_CONFIGURATION_get_value_string (cfg,
  1024. "dns",
  1025. "IPV6ADDR",
  1026. &ipv6addr)) )
  1027. {
  1028. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1029. "No entry 'IPV6ADDR' in configuration!\n");
  1030. GNUNET_free (binary);
  1031. GNUNET_SCHEDULER_shutdown ();
  1032. return;
  1033. }
  1034. helper_argv[2] = ipv6addr;
  1035. if (GNUNET_SYSERR ==
  1036. GNUNET_CONFIGURATION_get_value_string (cfg,
  1037. "dns",
  1038. "IPV6PREFIX",
  1039. &ipv6prefix))
  1040. {
  1041. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1042. "No entry 'IPV6PREFIX' in configuration!\n");
  1043. GNUNET_free (binary);
  1044. GNUNET_SCHEDULER_shutdown ();
  1045. return;
  1046. }
  1047. helper_argv[3] = ipv6prefix;
  1048. if (GNUNET_SYSERR ==
  1049. GNUNET_CONFIGURATION_get_value_string (cfg,
  1050. "dns",
  1051. "IPV4ADDR",
  1052. &ipv4addr))
  1053. {
  1054. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1055. "No entry 'IPV4ADDR' in configuration!\n");
  1056. GNUNET_free (binary);
  1057. GNUNET_SCHEDULER_shutdown ();
  1058. return;
  1059. }
  1060. helper_argv[4] = ipv4addr;
  1061. if (GNUNET_SYSERR ==
  1062. GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV4MASK",
  1063. &ipv4mask))
  1064. {
  1065. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1066. "No entry 'IPV4MASK' in configuration!\n");
  1067. GNUNET_free (binary);
  1068. GNUNET_SCHEDULER_shutdown ();
  1069. return;
  1070. }
  1071. helper_argv[5] = ipv4mask;
  1072. nortsetup = GNUNET_CONFIGURATION_get_value_yesno (cfg, "dns",
  1073. "SKIP_ROUTING_SETUP");
  1074. if (GNUNET_YES == nortsetup)
  1075. helper_argv[6] = GNUNET_strdup("1");
  1076. else
  1077. helper_argv[6] = GNUNET_strdup("0");
  1078. helper_argv[7] = NULL;
  1079. hijacker = GNUNET_HELPER_start (GNUNET_NO,
  1080. binary,
  1081. helper_argv,
  1082. &process_helper_messages,
  1083. NULL, NULL);
  1084. GNUNET_free (binary);
  1085. }
  1086. /**
  1087. * Define "main" method using service macro.
  1088. */
  1089. GNUNET_SERVICE_MAIN
  1090. ("dns",
  1091. GNUNET_SERVICE_OPTION_NONE,
  1092. &run,
  1093. &client_connect_cb,
  1094. &client_disconnect_cb,
  1095. NULL,
  1096. GNUNET_MQ_hd_fixed_size (client_init,
  1097. GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT,
  1098. struct GNUNET_DNS_Register,
  1099. NULL),
  1100. GNUNET_MQ_hd_var_size (client_response,
  1101. GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE,
  1102. struct GNUNET_DNS_Response,
  1103. NULL),
  1104. GNUNET_MQ_handler_end ());
  1105. /* FIXME: this might need a port on systems without 'getresgid' */
  1106. #if HAVE_GETRESGID
  1107. /**
  1108. * Enable use of SGID capabilities on POSIX
  1109. */
  1110. void __attribute__ ((constructor))
  1111. GNUNET_DNS_init ()
  1112. {
  1113. gid_t rgid;
  1114. gid_t egid;
  1115. gid_t sgid;
  1116. if (-1 == getresgid (&rgid,
  1117. &egid,
  1118. &sgid))
  1119. {
  1120. fprintf (stderr,
  1121. "getresgid failed: %s\n",
  1122. strerror (errno));
  1123. }
  1124. else if (sgid != rgid)
  1125. {
  1126. if (-1 == setregid (sgid,
  1127. sgid))
  1128. fprintf (stderr,
  1129. "setregid failed: %s\n",
  1130. strerror (errno));
  1131. }
  1132. }
  1133. #endif
  1134. /* end of gnunet-service-dns.c */