gnunet-daemon-pt.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2010, 2012, 2017 Christian Grothoff
  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 pt/gnunet-daemon-pt.c
  18. * @brief tool to manipulate DNS and VPN services to perform protocol translation (IPvX over GNUnet)
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_dns_service.h"
  24. #include "gnunet_dnsparser_lib.h"
  25. #include "gnunet_cadet_service.h"
  26. #include "gnunet_tun_lib.h"
  27. #include "gnunet_dht_service.h"
  28. #include "gnunet_vpn_service.h"
  29. #include "gnunet_statistics_service.h"
  30. #include "gnunet_applications.h"
  31. #include "block_dns.h"
  32. /**
  33. * After how long do we time out if we could not get an IP from VPN or CADET?
  34. */
  35. #define TIMEOUT GNUNET_TIME_UNIT_MINUTES
  36. /**
  37. * How many bytes of payload do we allow at most for a DNS reply?
  38. * Given that this is pretty much limited to loopback, we can be
  39. * pretty high (Linux loopback defaults to 16k, most local UDP packets
  40. * should survive up to 9k (NFS), so 8k should be pretty safe in
  41. * general).
  42. */
  43. #define MAX_DNS_SIZE (8 * 1024)
  44. /**
  45. * How many channels do we open at most at the same time?
  46. */
  47. #define MAX_OPEN_TUNNELS 4
  48. /**
  49. * Which group of DNS records are we currently processing?
  50. */
  51. enum RequestGroup
  52. {
  53. /**
  54. * DNS answers
  55. */
  56. ANSWERS = 0,
  57. /**
  58. * DNS authority records
  59. */
  60. AUTHORITY_RECORDS = 1,
  61. /**
  62. * DNS additional records
  63. */
  64. ADDITIONAL_RECORDS = 2,
  65. /**
  66. * We're done processing.
  67. */
  68. END = 3
  69. };
  70. /**
  71. * Information tracked per DNS reply that we are processing.
  72. */
  73. struct ReplyContext
  74. {
  75. /**
  76. * Handle to submit the final result.
  77. */
  78. struct GNUNET_DNS_RequestHandle *rh;
  79. /**
  80. * DNS packet that is being modified.
  81. */
  82. struct GNUNET_DNSPARSER_Packet *dns;
  83. /**
  84. * Active redirection request with the VPN.
  85. */
  86. struct GNUNET_VPN_RedirectionRequest *rr;
  87. /**
  88. * Record for which we have an active redirection request.
  89. */
  90. struct GNUNET_DNSPARSER_Record *rec;
  91. /**
  92. * Offset in the current record group that is being modified.
  93. */
  94. unsigned int offset;
  95. /**
  96. * Group that is being modified
  97. */
  98. enum RequestGroup group;
  99. };
  100. /**
  101. * Handle to a peer that advertised that it is willing to serve
  102. * as a DNS exit. We try to keep a few channels open and a few
  103. * peers in reserve.
  104. */
  105. struct CadetExit
  106. {
  107. /**
  108. * Kept in a DLL.
  109. */
  110. struct CadetExit *next;
  111. /**
  112. * Kept in a DLL.
  113. */
  114. struct CadetExit *prev;
  115. /**
  116. * Channel we use for DNS requests over CADET, NULL if we did
  117. * not initialze a channel to this peer yet.
  118. */
  119. struct GNUNET_CADET_Channel *cadet_channel;
  120. /**
  121. * At what time did the peer's advertisement expire?
  122. */
  123. struct GNUNET_TIME_Absolute expiration;
  124. /**
  125. * Head of DLL of requests waiting for a response.
  126. */
  127. struct RequestContext *receive_queue_head;
  128. /**
  129. * Tail of DLL of requests waiting for a response.
  130. */
  131. struct RequestContext *receive_queue_tail;
  132. /**
  133. * Identity of the peer that is providing the exit for us.
  134. */
  135. struct GNUNET_PeerIdentity peer;
  136. /**
  137. * How many DNS requests did we transmit via this channel?
  138. */
  139. unsigned int num_transmitted;
  140. /**
  141. * How many DNS requests were answered via this channel?
  142. */
  143. unsigned int num_answered;
  144. /**
  145. * Size of the window, 0 if we are busy.
  146. */
  147. /* unsigned */ int idle;
  148. };
  149. /**
  150. * State we keep for a request that is going out via CADET.
  151. */
  152. struct RequestContext
  153. {
  154. /**
  155. * We keep these in a DLL.
  156. */
  157. struct RequestContext *next;
  158. /**
  159. * We keep these in a DLL.
  160. */
  161. struct RequestContext *prev;
  162. /**
  163. * Exit that was chosen for this request.
  164. */
  165. struct CadetExit *exit;
  166. /**
  167. * Handle for interaction with DNS service.
  168. */
  169. struct GNUNET_DNS_RequestHandle *rh;
  170. /**
  171. * Envelope with the request we are transmitting.
  172. */
  173. struct GNUNET_MQ_Envelope *env;
  174. /**
  175. * Task used to abort this operation with timeout.
  176. */
  177. struct GNUNET_SCHEDULER_Task *timeout_task;
  178. /**
  179. * Length of the request message that follows this struct.
  180. */
  181. uint16_t mlen;
  182. /**
  183. * ID of the original DNS request (used to match the reply).
  184. */
  185. uint16_t dns_id;
  186. };
  187. /**
  188. * Head of DLL of cadet exits. Cadet exits with an open channel are
  189. * always at the beginning (so we do not have to traverse the entire
  190. * list to find them).
  191. */
  192. static struct CadetExit *exit_head;
  193. /**
  194. * Tail of DLL of cadet exits.
  195. */
  196. static struct CadetExit *exit_tail;
  197. /**
  198. * The handle to the configuration used throughout the process
  199. */
  200. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  201. /**
  202. * The handle to the VPN
  203. */
  204. static struct GNUNET_VPN_Handle *vpn_handle;
  205. /**
  206. * The handle to the CADET service
  207. */
  208. static struct GNUNET_CADET_Handle *cadet_handle;
  209. /**
  210. * Statistics.
  211. */
  212. static struct GNUNET_STATISTICS_Handle *stats;
  213. /**
  214. * The handle to DNS post-resolution modifications.
  215. */
  216. static struct GNUNET_DNS_Handle *dns_post_handle;
  217. /**
  218. * The handle to DNS pre-resolution modifications.
  219. */
  220. static struct GNUNET_DNS_Handle *dns_pre_handle;
  221. /**
  222. * Handle to access the DHT.
  223. */
  224. static struct GNUNET_DHT_Handle *dht;
  225. /**
  226. * Our DHT GET operation to find DNS exits.
  227. */
  228. static struct GNUNET_DHT_GetHandle *dht_get;
  229. /**
  230. * Are we doing IPv4-pt?
  231. */
  232. static int ipv4_pt;
  233. /**
  234. * Are we doing IPv6-pt?
  235. */
  236. static int ipv6_pt;
  237. /**
  238. * Are we channeling DNS queries?
  239. */
  240. static int dns_channel;
  241. /**
  242. * Number of DNS exit peers we currently have in the cadet channel.
  243. * Used to see if using the cadet channel makes any sense right now,
  244. * as well as to decide if we should open new channels.
  245. */
  246. static unsigned int dns_exit_available;
  247. /**
  248. * We are short on cadet exits, try to open another one.
  249. */
  250. static void
  251. try_open_exit (void);
  252. /**
  253. * Compute the weight of the given exit. The higher the weight,
  254. * the more likely it will be that the channel will be chosen.
  255. * A weigt of zero means that we should close the channel as it
  256. * is so bad, that we should not use it.
  257. *
  258. * @param exit exit to calculate the weight for
  259. * @return weight of the channel
  260. */
  261. static uint32_t
  262. get_channel_weight (struct CadetExit *exit)
  263. {
  264. uint32_t dropped;
  265. uint32_t drop_percent;
  266. uint32_t good_percent;
  267. GNUNET_assert (exit->num_transmitted >= exit->num_answered);
  268. dropped = exit->num_transmitted - exit->num_answered;
  269. if (exit->num_transmitted > 0)
  270. drop_percent = (uint32_t) ((100LL * dropped) / exit->num_transmitted);
  271. else
  272. drop_percent = 50; /* no data */
  273. if ((exit->num_transmitted > 20) &&
  274. (drop_percent > 25))
  275. return 0; /* statistically significant, and > 25% loss, die */
  276. good_percent = 100 - drop_percent;
  277. GNUNET_assert (0 != good_percent);
  278. if (UINT32_MAX / good_percent / good_percent < exit->num_transmitted)
  279. return UINT32_MAX; /* formula below would overflow */
  280. return 1 + good_percent * good_percent * exit->num_transmitted;
  281. }
  282. /**
  283. * Choose a cadet exit for a DNS request. We try to use a channel
  284. * that is reliable and currently available. All existing
  285. * channels are given a base weight of 1, plus a score relating
  286. * to the total number of queries answered in relation to the
  287. * total number of queries we sent to that channel. That
  288. * score is doubled if the channel is currently idle.
  289. *
  290. * @return NULL if no exit is known, otherwise the
  291. * exit that we should use to queue a message with
  292. */
  293. static struct CadetExit *
  294. choose_exit ()
  295. {
  296. struct CadetExit *pos;
  297. uint64_t total_transmitted;
  298. uint64_t selected_offset;
  299. uint32_t channel_weight;
  300. total_transmitted = 0;
  301. for (pos = exit_head; NULL != pos; pos = pos->next)
  302. {
  303. if (NULL == pos->cadet_channel)
  304. break;
  305. channel_weight = get_channel_weight (pos);
  306. total_transmitted += channel_weight;
  307. /* double weight for idle channels */
  308. if (0 != pos->idle)
  309. total_transmitted += channel_weight;
  310. }
  311. if (0 == total_transmitted)
  312. {
  313. /* no channels available, or only a very bad one... */
  314. return exit_head;
  315. }
  316. selected_offset = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
  317. total_transmitted);
  318. total_transmitted = 0;
  319. for (pos = exit_head; NULL != pos; pos = pos->next)
  320. {
  321. if (NULL == pos->cadet_channel)
  322. break;
  323. channel_weight = get_channel_weight (pos);
  324. total_transmitted += channel_weight;
  325. /* double weight for idle channels */
  326. if (0 != pos->idle)
  327. total_transmitted += channel_weight;
  328. if (total_transmitted > selected_offset)
  329. return pos;
  330. }
  331. GNUNET_break (0);
  332. return NULL;
  333. }
  334. /**
  335. * We're done modifying all records in the response. Submit the reply
  336. * and free the resources of the rc.
  337. *
  338. * @param rc context to process
  339. */
  340. static void
  341. finish_request (struct ReplyContext *rc)
  342. {
  343. char *buf;
  344. size_t buf_len;
  345. if (GNUNET_SYSERR ==
  346. GNUNET_DNSPARSER_pack (rc->dns,
  347. MAX_DNS_SIZE,
  348. &buf,
  349. &buf_len))
  350. {
  351. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  352. _ ("Failed to pack DNS request. Dropping.\n"));
  353. GNUNET_DNS_request_drop (rc->rh);
  354. }
  355. else
  356. {
  357. GNUNET_STATISTICS_update (stats,
  358. gettext_noop ("# DNS requests mapped to VPN"),
  359. 1, GNUNET_NO);
  360. GNUNET_DNS_request_answer (rc->rh,
  361. buf_len,
  362. buf);
  363. GNUNET_free (buf);
  364. }
  365. GNUNET_DNSPARSER_free_packet (rc->dns);
  366. GNUNET_free (rc);
  367. }
  368. /**
  369. * Process the next record of the given request context.
  370. * When done, submit the reply and free the resources of
  371. * the rc.
  372. *
  373. * @param rc context to process
  374. */
  375. static void
  376. submit_request (struct ReplyContext *rc);
  377. /**
  378. * Callback invoked from the VPN service once a redirection is
  379. * available. Provides the IP address that can now be used to
  380. * reach the requested destination. We substitute the active
  381. * record and then continue with 'submit_request' to look at
  382. * the other records.
  383. *
  384. * @param cls our `struct ReplyContext`
  385. * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error;
  386. * will match 'result_af' from the request
  387. * @param address IP address (struct in_addr or struct in_addr6, depending on 'af')
  388. * that the VPN allocated for the redirection;
  389. * traffic to this IP will now be redirected to the
  390. * specified target peer; NULL on error
  391. */
  392. static void
  393. vpn_allocation_callback (void *cls,
  394. int af,
  395. const void *address)
  396. {
  397. struct ReplyContext *rc = cls;
  398. rc->rr = NULL;
  399. if (af == AF_UNSPEC)
  400. {
  401. GNUNET_DNS_request_drop (rc->rh);
  402. GNUNET_DNSPARSER_free_packet (rc->dns);
  403. GNUNET_free (rc);
  404. return;
  405. }
  406. GNUNET_STATISTICS_update (stats,
  407. gettext_noop ("# DNS records modified"),
  408. 1,
  409. GNUNET_NO);
  410. switch (rc->rec->type)
  411. {
  412. case GNUNET_DNSPARSER_TYPE_A:
  413. GNUNET_assert (AF_INET == af);
  414. GNUNET_memcpy (rc->rec->data.raw.data,
  415. address,
  416. sizeof(struct in_addr));
  417. break;
  418. case GNUNET_DNSPARSER_TYPE_AAAA:
  419. GNUNET_assert (AF_INET6 == af);
  420. GNUNET_memcpy (rc->rec->data.raw.data,
  421. address,
  422. sizeof(struct in6_addr));
  423. break;
  424. default:
  425. GNUNET_assert (0);
  426. return;
  427. }
  428. rc->rec = NULL;
  429. submit_request (rc);
  430. }
  431. /**
  432. * Modify the given DNS record by asking VPN to create a channel
  433. * to the given address. When done, continue with submitting
  434. * other records from the request context ('submit_request' is
  435. * our continuation).
  436. *
  437. * @param rc context to process
  438. * @param rec record to modify
  439. */
  440. static void
  441. modify_address (struct ReplyContext *rc,
  442. struct GNUNET_DNSPARSER_Record *rec)
  443. {
  444. int af;
  445. switch (rec->type)
  446. {
  447. case GNUNET_DNSPARSER_TYPE_A:
  448. af = AF_INET;
  449. GNUNET_assert (rec->data.raw.data_len == sizeof(struct in_addr));
  450. break;
  451. case GNUNET_DNSPARSER_TYPE_AAAA:
  452. af = AF_INET6;
  453. GNUNET_assert (rec->data.raw.data_len == sizeof(struct in6_addr));
  454. break;
  455. default:
  456. GNUNET_assert (0);
  457. return;
  458. }
  459. rc->rec = rec;
  460. rc->rr = GNUNET_VPN_redirect_to_ip (vpn_handle,
  461. af,
  462. af,
  463. rec->data.raw.data,
  464. GNUNET_TIME_relative_to_absolute (
  465. TIMEOUT),
  466. &vpn_allocation_callback,
  467. rc);
  468. }
  469. /**
  470. * Process the next record of the given request context.
  471. * When done, submit the reply and free the resources of
  472. * the rc.
  473. *
  474. * @param rc context to process
  475. */
  476. static void
  477. submit_request (struct ReplyContext *rc)
  478. {
  479. struct GNUNET_DNSPARSER_Record *ra;
  480. unsigned int ra_len;
  481. unsigned int i;
  482. while (1)
  483. {
  484. switch (rc->group)
  485. {
  486. case ANSWERS:
  487. ra = rc->dns->answers;
  488. ra_len = rc->dns->num_answers;
  489. break;
  490. case AUTHORITY_RECORDS:
  491. ra = rc->dns->authority_records;
  492. ra_len = rc->dns->num_authority_records;
  493. break;
  494. case ADDITIONAL_RECORDS:
  495. ra = rc->dns->additional_records;
  496. ra_len = rc->dns->num_additional_records;
  497. break;
  498. case END:
  499. finish_request (rc);
  500. return;
  501. default:
  502. GNUNET_assert (0);
  503. }
  504. for (i = rc->offset; i < ra_len; i++)
  505. {
  506. switch (ra[i].type)
  507. {
  508. case GNUNET_DNSPARSER_TYPE_A:
  509. if (ipv4_pt)
  510. {
  511. rc->offset = i + 1;
  512. modify_address (rc,
  513. &ra[i]);
  514. return;
  515. }
  516. break;
  517. case GNUNET_DNSPARSER_TYPE_AAAA:
  518. if (ipv6_pt)
  519. {
  520. rc->offset = i + 1;
  521. modify_address (rc,
  522. &ra[i]);
  523. return;
  524. }
  525. break;
  526. }
  527. }
  528. rc->group++;
  529. }
  530. }
  531. /**
  532. * Test if any of the given records need protocol-translation work.
  533. *
  534. * @param ra array of records
  535. * @param ra_len number of entries in @a ra
  536. * @return #GNUNET_YES if any of the given records require protocol-translation
  537. */
  538. static int
  539. work_test (const struct GNUNET_DNSPARSER_Record *ra,
  540. unsigned int ra_len)
  541. {
  542. unsigned int i;
  543. for (i = 0; i < ra_len; i++)
  544. {
  545. switch (ra[i].type)
  546. {
  547. case GNUNET_DNSPARSER_TYPE_A:
  548. if (ipv4_pt)
  549. return GNUNET_YES;
  550. break;
  551. case GNUNET_DNSPARSER_TYPE_AAAA:
  552. if (ipv6_pt)
  553. return GNUNET_YES;
  554. break;
  555. }
  556. }
  557. return GNUNET_NO;
  558. }
  559. /**
  560. * This function is called AFTER we got an IP address for a
  561. * DNS request. Now, the PT daemon has the chance to substitute
  562. * the IP address with one from the VPN range to channel requests
  563. * destined for this IP address via VPN and CADET.
  564. *
  565. * @param cls closure
  566. * @param rh request handle to user for reply
  567. * @param request_length number of bytes in request
  568. * @param request udp payload of the DNS request
  569. */
  570. static void
  571. dns_post_request_handler (void *cls,
  572. struct GNUNET_DNS_RequestHandle *rh,
  573. size_t request_length,
  574. const char *request)
  575. {
  576. struct GNUNET_DNSPARSER_Packet *dns;
  577. struct ReplyContext *rc;
  578. int work;
  579. GNUNET_STATISTICS_update (stats,
  580. gettext_noop ("# DNS replies intercepted"),
  581. 1, GNUNET_NO);
  582. dns = GNUNET_DNSPARSER_parse (request,
  583. request_length);
  584. if (NULL == dns)
  585. {
  586. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  587. _ ("Failed to parse DNS request. Dropping.\n"));
  588. GNUNET_DNS_request_drop (rh);
  589. return;
  590. }
  591. work = GNUNET_NO;
  592. work |= work_test (dns->answers,
  593. dns->num_answers);
  594. work |= work_test (dns->authority_records,
  595. dns->num_authority_records);
  596. work |= work_test (dns->additional_records,
  597. dns->num_additional_records);
  598. if (! work)
  599. {
  600. GNUNET_DNS_request_forward (rh);
  601. GNUNET_DNSPARSER_free_packet (dns);
  602. return;
  603. }
  604. rc = GNUNET_new (struct ReplyContext);
  605. rc->rh = rh;
  606. rc->dns = dns;
  607. rc->offset = 0;
  608. rc->group = ANSWERS;
  609. submit_request (rc);
  610. }
  611. /**
  612. * Task run if the time to answer a DNS request via CADET is over.
  613. *
  614. * @param cls the `struct RequestContext` to abort
  615. */
  616. static void
  617. timeout_request (void *cls)
  618. {
  619. struct RequestContext *rc = cls;
  620. struct CadetExit *exit = rc->exit;
  621. GNUNET_STATISTICS_update (stats,
  622. gettext_noop ("# DNS requests dropped (timeout)"),
  623. 1,
  624. GNUNET_NO);
  625. GNUNET_DNS_request_drop (rc->rh);
  626. GNUNET_free (rc);
  627. if ((0 == get_channel_weight (exit)) &&
  628. (NULL == exit->receive_queue_head))
  629. {
  630. /* this straw broke the camel's back: this channel now has
  631. such a low score that it will not be used; close it! */
  632. GNUNET_CADET_channel_destroy (exit->cadet_channel);
  633. exit->cadet_channel = NULL;
  634. GNUNET_CONTAINER_DLL_remove (exit_head,
  635. exit_tail,
  636. exit);
  637. GNUNET_CONTAINER_DLL_insert_tail (exit_head,
  638. exit_tail,
  639. exit);
  640. /* go back to semi-innocent: mark as not great, but
  641. avoid a prohibitively negative score (see
  642. #get_channel_weight(), which checks for a certain
  643. minimum number of transmissions before making
  644. up an opinion) */
  645. exit->num_transmitted = 5;
  646. exit->num_answered = 0;
  647. dns_exit_available--;
  648. /* now try to open an alternative exit */
  649. try_open_exit ();
  650. }
  651. }
  652. /**
  653. * This function is called *before* the DNS request has been
  654. * given to a "local" DNS resolver. Channeling for DNS requests
  655. * was enabled, so we now need to send the request via some CADET
  656. * channel to a DNS EXIT for resolution.
  657. *
  658. * @param cls closure
  659. * @param rh request handle to user for reply
  660. * @param request_length number of bytes in request
  661. * @param request udp payload of the DNS request
  662. */
  663. static void
  664. dns_pre_request_handler (void *cls,
  665. struct GNUNET_DNS_RequestHandle *rh,
  666. size_t request_length,
  667. const char *request)
  668. {
  669. struct RequestContext *rc;
  670. struct GNUNET_MQ_Envelope *env;
  671. struct GNUNET_MessageHeader *hdr;
  672. struct GNUNET_TUN_DnsHeader dns;
  673. struct CadetExit *exit;
  674. GNUNET_STATISTICS_update (stats,
  675. gettext_noop ("# DNS requests intercepted"),
  676. 1, GNUNET_NO);
  677. if (0 == dns_exit_available)
  678. {
  679. GNUNET_STATISTICS_update (stats,
  680. gettext_noop (
  681. "# DNS requests dropped (DNS cadet channel down)"),
  682. 1, GNUNET_NO);
  683. GNUNET_DNS_request_drop (rh);
  684. return;
  685. }
  686. if (request_length < sizeof(dns))
  687. {
  688. GNUNET_STATISTICS_update (stats,
  689. gettext_noop (
  690. "# DNS requests dropped (malformed)"),
  691. 1, GNUNET_NO);
  692. GNUNET_DNS_request_drop (rh);
  693. return;
  694. }
  695. exit = choose_exit ();
  696. GNUNET_assert (NULL != exit);
  697. GNUNET_assert (NULL != exit->cadet_channel);
  698. env = GNUNET_MQ_msg_extra (hdr,
  699. request_length,
  700. GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET);
  701. GNUNET_memcpy (&hdr[1],
  702. request,
  703. request_length);
  704. rc = GNUNET_new (struct RequestContext);
  705. rc->exit = exit;
  706. rc->rh = rh;
  707. rc->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
  708. &timeout_request,
  709. rc);
  710. GNUNET_memcpy (&dns,
  711. request,
  712. sizeof(dns));
  713. rc->dns_id = dns.id;
  714. rc->env = env;
  715. GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head,
  716. exit->receive_queue_tail,
  717. rc);
  718. if (0 < exit->idle)
  719. exit->idle--;
  720. exit->num_transmitted++;
  721. GNUNET_MQ_send (GNUNET_CADET_get_mq (exit->cadet_channel),
  722. GNUNET_MQ_env_copy (env));
  723. }
  724. GNUNET_NETWORK_STRUCT_BEGIN
  725. /**
  726. * Message with a DNS response.
  727. */
  728. struct DnsResponseMessage
  729. {
  730. /**
  731. * GNUnet header, of type #GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET
  732. */
  733. struct GNUNET_MessageHeader header;
  734. /**
  735. * DNS header.
  736. */
  737. struct GNUNET_TUN_DnsHeader dns;
  738. /* Followed by more DNS payload */
  739. };
  740. GNUNET_NETWORK_STRUCT_END
  741. /**
  742. * Process a request via cadet to perform a DNS query.
  743. *
  744. * @param cls the `struct CadetExit` which got the message
  745. * @param msg the actual message
  746. * @return #GNUNET_OK to keep the connection open,
  747. * #GNUNET_SYSERR to close it (signal serious error)
  748. */
  749. static int
  750. check_dns_response (void *cls,
  751. const struct DnsResponseMessage *msg)
  752. {
  753. return GNUNET_OK; /* all OK */
  754. }
  755. /**
  756. * Process a request via cadet to perform a DNS query.
  757. *
  758. * @param cls the `struct CadetExit` which got the message
  759. * @param msg the actual message
  760. */
  761. static void
  762. handle_dns_response (void *cls,
  763. const struct DnsResponseMessage *msg)
  764. {
  765. struct CadetExit *exit = cls;
  766. size_t mlen;
  767. struct RequestContext *rc;
  768. mlen = ntohs (msg->header.size) - sizeof(*msg);
  769. for (rc = exit->receive_queue_head; NULL != rc; rc = rc->next)
  770. {
  771. if (msg->dns.id == rc->dns_id)
  772. {
  773. GNUNET_STATISTICS_update (stats,
  774. gettext_noop ("# DNS replies received"),
  775. 1,
  776. GNUNET_NO);
  777. GNUNET_DNS_request_answer (rc->rh,
  778. mlen + sizeof(struct GNUNET_TUN_DnsHeader),
  779. (const void*) &msg->dns);
  780. GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head,
  781. exit->receive_queue_tail,
  782. rc);
  783. GNUNET_SCHEDULER_cancel (rc->timeout_task);
  784. GNUNET_MQ_discard (rc->env);
  785. GNUNET_free (rc);
  786. exit->num_answered++;
  787. return;
  788. }
  789. }
  790. GNUNET_STATISTICS_update (stats,
  791. gettext_noop ("# DNS replies dropped (too late?)"),
  792. 1, GNUNET_NO);
  793. }
  794. /**
  795. * Abort all pending DNS requests with the given cadet exit.
  796. *
  797. * @param exit cadet exit to abort requests for
  798. */
  799. static void
  800. abort_all_requests (struct CadetExit *exit)
  801. {
  802. struct RequestContext *rc;
  803. while (NULL != (rc = exit->receive_queue_head))
  804. {
  805. GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head,
  806. exit->receive_queue_tail,
  807. rc);
  808. GNUNET_DNS_request_drop (rc->rh);
  809. GNUNET_SCHEDULER_cancel (rc->timeout_task);
  810. GNUNET_MQ_discard (rc->env);
  811. GNUNET_free (rc);
  812. }
  813. }
  814. /**
  815. * Function scheduled as very last function, cleans up after us
  816. *
  817. * @param cls closure, NULL
  818. */
  819. static void
  820. cleanup (void *cls)
  821. {
  822. struct CadetExit *exit;
  823. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  824. "Protocol translation daemon is shutting down now\n");
  825. if (NULL != vpn_handle)
  826. {
  827. GNUNET_VPN_disconnect (vpn_handle);
  828. vpn_handle = NULL;
  829. }
  830. while (NULL != (exit = exit_head))
  831. {
  832. GNUNET_CONTAINER_DLL_remove (exit_head,
  833. exit_tail,
  834. exit);
  835. if (NULL != exit->cadet_channel)
  836. {
  837. GNUNET_CADET_channel_destroy (exit->cadet_channel);
  838. exit->cadet_channel = NULL;
  839. }
  840. abort_all_requests (exit);
  841. GNUNET_free (exit);
  842. }
  843. if (NULL != cadet_handle)
  844. {
  845. GNUNET_CADET_disconnect (cadet_handle);
  846. cadet_handle = NULL;
  847. }
  848. if (NULL != dns_post_handle)
  849. {
  850. GNUNET_DNS_disconnect (dns_post_handle);
  851. dns_post_handle = NULL;
  852. }
  853. if (NULL != dns_pre_handle)
  854. {
  855. GNUNET_DNS_disconnect (dns_pre_handle);
  856. dns_pre_handle = NULL;
  857. }
  858. if (NULL != stats)
  859. {
  860. GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
  861. stats = NULL;
  862. }
  863. if (NULL != dht_get)
  864. {
  865. GNUNET_DHT_get_stop (dht_get);
  866. dht_get = NULL;
  867. }
  868. if (NULL != dht)
  869. {
  870. GNUNET_DHT_disconnect (dht);
  871. dht = NULL;
  872. }
  873. }
  874. /**
  875. * Function called whenever a channel is destroyed. Should clean up
  876. * the associated state and attempt to build a new one.
  877. *
  878. * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
  879. *
  880. * @param cls closure (the `struct CadetExit` set from #GNUNET_CADET_connect)
  881. * @param channel connection to the other end (henceforth invalid)
  882. * @param channel_ctx place where local state associated
  883. * with the channel is stored
  884. */
  885. static void
  886. cadet_channel_end_cb (void *cls,
  887. const struct GNUNET_CADET_Channel *channel)
  888. {
  889. struct CadetExit *exit = cls;
  890. struct CadetExit *alt;
  891. struct RequestContext *rc;
  892. exit->cadet_channel = NULL;
  893. dns_exit_available--;
  894. /* open alternative channels */
  895. /* our channel is now closed, move our requests to an alternative
  896. channel */
  897. alt = choose_exit ();
  898. while (NULL != (rc = exit->receive_queue_head))
  899. {
  900. GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head,
  901. exit->receive_queue_tail,
  902. rc);
  903. rc->exit = alt;
  904. GNUNET_CONTAINER_DLL_insert (alt->receive_queue_head,
  905. alt->receive_queue_tail,
  906. rc);
  907. GNUNET_MQ_send (GNUNET_CADET_get_mq (alt->cadet_channel),
  908. GNUNET_MQ_env_copy (rc->env));
  909. }
  910. try_open_exit ();
  911. }
  912. /**
  913. * Function called whenever a channel has excess capacity.
  914. *
  915. * @param cls the `struct CadetExit`
  916. * @param channel connection to the other end
  917. * @param window_size how much capacity do we have
  918. */
  919. static void
  920. channel_idle_notify_cb (void *cls,
  921. const struct GNUNET_CADET_Channel *channel,
  922. int window_size)
  923. {
  924. struct CadetExit *pos = cls;
  925. pos->idle = window_size;
  926. }
  927. /**
  928. * We are short on cadet exits, try to open another one.
  929. */
  930. static void
  931. try_open_exit ()
  932. {
  933. struct CadetExit *pos;
  934. uint32_t candidate_count;
  935. uint32_t candidate_selected;
  936. struct GNUNET_HashCode port;
  937. GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER,
  938. strlen (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER),
  939. &port);
  940. candidate_count = 0;
  941. for (pos = exit_head; NULL != pos; pos = pos->next)
  942. if (NULL == pos->cadet_channel)
  943. candidate_count++;
  944. if (0 == candidate_count)
  945. {
  946. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  947. "No DNS exits available yet.\n");
  948. return;
  949. }
  950. candidate_selected = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
  951. candidate_count);
  952. candidate_count = 0;
  953. for (pos = exit_head; NULL != pos; pos = pos->next)
  954. if (NULL == pos->cadet_channel)
  955. {
  956. candidate_count++;
  957. if (candidate_selected < candidate_count)
  958. {
  959. struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
  960. GNUNET_MQ_hd_var_size (dns_response,
  961. GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET,
  962. struct DnsResponseMessage,
  963. pos),
  964. GNUNET_MQ_handler_end ()
  965. };
  966. /* move to the head of the DLL */
  967. pos->cadet_channel
  968. = GNUNET_CADET_channel_create (cadet_handle,
  969. pos,
  970. &pos->peer,
  971. &port,
  972. &channel_idle_notify_cb,
  973. &cadet_channel_end_cb,
  974. cadet_handlers);
  975. if (NULL == pos->cadet_channel)
  976. {
  977. GNUNET_break (0);
  978. continue;
  979. }
  980. GNUNET_CONTAINER_DLL_remove (exit_head,
  981. exit_tail,
  982. pos);
  983. GNUNET_CONTAINER_DLL_insert (exit_head,
  984. exit_tail,
  985. pos);
  986. dns_exit_available++;
  987. return;
  988. }
  989. }
  990. GNUNET_assert (NULL == exit_head);
  991. }
  992. /**
  993. * Function called whenever we find an advertisement for a
  994. * DNS exit in the DHT. If we don't have a cadet channel,
  995. * we should build one; otherwise, we should save the
  996. * advertisement for later use.
  997. *
  998. * @param cls closure
  999. * @param exp when will this value expire
  1000. * @param key key of the result
  1001. * @param get_path peers on reply path (or NULL if not recorded)
  1002. * [0] = datastore's first neighbor, [length - 1] = local peer
  1003. * @param get_path_length number of entries in @a get_path
  1004. * @param put_path peers on the PUT path (or NULL if not recorded)
  1005. * [0] = origin, [length - 1] = datastore
  1006. * @param put_path_length number of entries in @a put_path
  1007. * @param type type of the result
  1008. * @param size number of bytes in @a data
  1009. * @param data pointer to the result data
  1010. */
  1011. static void
  1012. handle_dht_result (void *cls,
  1013. struct GNUNET_TIME_Absolute exp,
  1014. const struct GNUNET_HashCode *key,
  1015. const struct GNUNET_PeerIdentity *get_path,
  1016. unsigned int get_path_length,
  1017. const struct GNUNET_PeerIdentity *put_path,
  1018. unsigned int put_path_length,
  1019. enum GNUNET_BLOCK_Type type,
  1020. size_t size, const void *data)
  1021. {
  1022. const struct GNUNET_DNS_Advertisement *ad;
  1023. struct CadetExit *exit;
  1024. if (sizeof(struct GNUNET_DNS_Advertisement) != size)
  1025. {
  1026. GNUNET_break (0);
  1027. return;
  1028. }
  1029. ad = data;
  1030. for (exit = exit_head; NULL != exit; exit = exit->next)
  1031. if (0 == GNUNET_memcmp (&ad->peer,
  1032. &exit->peer))
  1033. break;
  1034. if (NULL == exit)
  1035. {
  1036. exit = GNUNET_new (struct CadetExit);
  1037. exit->peer = ad->peer;
  1038. /* channel is closed, so insert at the end */
  1039. GNUNET_CONTAINER_DLL_insert_tail (exit_head,
  1040. exit_tail,
  1041. exit);
  1042. }
  1043. exit->expiration = GNUNET_TIME_absolute_max (exit->expiration,
  1044. GNUNET_TIME_absolute_ntoh (
  1045. ad->expiration_time));
  1046. if (dns_exit_available < MAX_OPEN_TUNNELS)
  1047. try_open_exit ();
  1048. }
  1049. /**
  1050. * @brief Main function that will be run by the scheduler.
  1051. *
  1052. * @param cls closure
  1053. * @param args remaining command-line arguments
  1054. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  1055. * @param cfg_ configuration
  1056. */
  1057. static void
  1058. run (void *cls, char *const *args GNUNET_UNUSED,
  1059. const char *cfgfile GNUNET_UNUSED,
  1060. const struct GNUNET_CONFIGURATION_Handle *cfg_)
  1061. {
  1062. struct GNUNET_HashCode dns_key;
  1063. cfg = cfg_;
  1064. stats = GNUNET_STATISTICS_create ("pt",
  1065. cfg);
  1066. ipv4_pt = GNUNET_CONFIGURATION_get_value_yesno (cfg,
  1067. "pt",
  1068. "TUNNEL_IPV4");
  1069. ipv6_pt = GNUNET_CONFIGURATION_get_value_yesno (cfg,
  1070. "pt",
  1071. "TUNNEL_IPV6");
  1072. dns_channel = GNUNET_CONFIGURATION_get_value_yesno (cfg,
  1073. "pt",
  1074. "TUNNEL_DNS");
  1075. if (! (ipv4_pt || ipv6_pt || dns_channel))
  1076. {
  1077. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1078. _ ("No useful service enabled. Exiting.\n"));
  1079. GNUNET_SCHEDULER_shutdown ();
  1080. return;
  1081. }
  1082. GNUNET_SCHEDULER_add_shutdown (&cleanup, cls);
  1083. if (ipv4_pt || ipv6_pt)
  1084. {
  1085. dns_post_handle
  1086. = GNUNET_DNS_connect (cfg,
  1087. GNUNET_DNS_FLAG_POST_RESOLUTION,
  1088. &dns_post_request_handler,
  1089. NULL);
  1090. if (NULL == dns_post_handle)
  1091. {
  1092. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1093. _ ("Failed to connect to %s service. Exiting.\n"),
  1094. "DNS");
  1095. GNUNET_SCHEDULER_shutdown ();
  1096. return;
  1097. }
  1098. vpn_handle = GNUNET_VPN_connect (cfg);
  1099. if (NULL == vpn_handle)
  1100. {
  1101. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1102. _ ("Failed to connect to %s service. Exiting.\n"),
  1103. "VPN");
  1104. GNUNET_SCHEDULER_shutdown ();
  1105. return;
  1106. }
  1107. }
  1108. if (dns_channel)
  1109. {
  1110. dns_pre_handle
  1111. = GNUNET_DNS_connect (cfg,
  1112. GNUNET_DNS_FLAG_PRE_RESOLUTION,
  1113. &dns_pre_request_handler,
  1114. NULL);
  1115. if (NULL == dns_pre_handle)
  1116. {
  1117. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1118. _ ("Failed to connect to %s service. Exiting.\n"),
  1119. "DNS");
  1120. GNUNET_SCHEDULER_shutdown ();
  1121. return;
  1122. }
  1123. cadet_handle = GNUNET_CADET_connect (cfg);
  1124. if (NULL == cadet_handle)
  1125. {
  1126. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1127. _ ("Failed to connect to %s service. Exiting.\n"),
  1128. "CADET");
  1129. GNUNET_SCHEDULER_shutdown ();
  1130. return;
  1131. }
  1132. dht = GNUNET_DHT_connect (cfg, 1);
  1133. if (NULL == dht)
  1134. {
  1135. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1136. _ ("Failed to connect to %s service. Exiting.\n"),
  1137. "DHT");
  1138. GNUNET_SCHEDULER_shutdown ();
  1139. return;
  1140. }
  1141. GNUNET_CRYPTO_hash ("dns",
  1142. strlen ("dns"),
  1143. &dns_key);
  1144. dht_get = GNUNET_DHT_get_start (dht,
  1145. GNUNET_BLOCK_TYPE_DNS,
  1146. &dns_key,
  1147. 1,
  1148. GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
  1149. NULL, 0,
  1150. &handle_dht_result,
  1151. NULL);
  1152. }
  1153. }
  1154. /**
  1155. * The main function
  1156. *
  1157. * @param argc number of arguments from the command line
  1158. * @param argv command line arguments
  1159. * @return 0 ok, 1 on error
  1160. */
  1161. int
  1162. main (int argc,
  1163. char *const *argv)
  1164. {
  1165. static const struct GNUNET_GETOPT_CommandLineOption options[] = {
  1166. GNUNET_GETOPT_OPTION_END
  1167. };
  1168. int ret;
  1169. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc,
  1170. argv,
  1171. &argc,
  1172. &argv))
  1173. return 2;
  1174. ret = (GNUNET_OK ==
  1175. GNUNET_PROGRAM_run (argc,
  1176. argv,
  1177. "gnunet-daemon-pt",
  1178. gettext_noop (
  1179. "Daemon to run to perform IP protocol translation to GNUnet"),
  1180. options,
  1181. &run,
  1182. NULL))
  1183. ? 0
  1184. : 1;
  1185. GNUNET_free ((void*) argv);
  1186. return ret;
  1187. }
  1188. /* end of gnunet-daemon-pt.c */