resolver_api.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2009-2018 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 util/resolver_api.c
  18. * @brief resolver for writing a tool
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_protocols.h"
  24. #include "gnunet_resolver_service.h"
  25. #include "resolver.h"
  26. #define LOG(kind, ...) GNUNET_log_from (kind, "util-resolver-api", __VA_ARGS__)
  27. #define LOG_STRERROR(kind, syscall) GNUNET_log_from_strerror (kind, \
  28. "util-resolver-api", \
  29. syscall)
  30. /**
  31. * Maximum supported length for a hostname
  32. */
  33. #define MAX_HOSTNAME 1024
  34. /**
  35. * Possible hostnames for "loopback".
  36. */
  37. static const char *loopback[] = {
  38. "localhost",
  39. "ip6-localnet",
  40. NULL
  41. };
  42. /**
  43. * Configuration.
  44. */
  45. static const struct GNUNET_CONFIGURATION_Handle *resolver_cfg;
  46. /**
  47. * Our connection to the resolver service, created on-demand, but then
  48. * persists until error or shutdown.
  49. */
  50. static struct GNUNET_MQ_Handle *mq;
  51. /**
  52. * Head of DLL of requests.
  53. */
  54. static struct GNUNET_RESOLVER_RequestHandle *req_head;
  55. /**
  56. * Tail of DLL of requests.
  57. */
  58. static struct GNUNET_RESOLVER_RequestHandle *req_tail;
  59. /**
  60. * ID of the last request we sent to the service
  61. */
  62. static uint32_t last_request_id;
  63. /**
  64. * How long should we wait to reconnect?
  65. */
  66. static struct GNUNET_TIME_Relative backoff;
  67. /**
  68. * Task for reconnecting.
  69. */
  70. static struct GNUNET_SCHEDULER_Task *r_task;
  71. /**
  72. * Task ID of shutdown task; only present while we have a
  73. * connection to the resolver service.
  74. */
  75. static struct GNUNET_SCHEDULER_Task *s_task;
  76. /**
  77. * Handle to a request given to the resolver. Can be used to cancel
  78. * the request prior to the timeout or successful execution. Also
  79. * used to track our internal state for the request.
  80. */
  81. struct GNUNET_RESOLVER_RequestHandle
  82. {
  83. /**
  84. * Next entry in DLL of requests.
  85. */
  86. struct GNUNET_RESOLVER_RequestHandle *next;
  87. /**
  88. * Previous entry in DLL of requests.
  89. */
  90. struct GNUNET_RESOLVER_RequestHandle *prev;
  91. /**
  92. * Callback if this is an name resolution request,
  93. * otherwise NULL.
  94. */
  95. GNUNET_RESOLVER_AddressCallback addr_callback;
  96. /**
  97. * Callback if this is a reverse lookup request,
  98. * otherwise NULL.
  99. */
  100. GNUNET_RESOLVER_HostnameCallback name_callback;
  101. /**
  102. * Closure for the callbacks.
  103. */
  104. void *cls;
  105. /**
  106. * When should this request time out?
  107. */
  108. struct GNUNET_TIME_Absolute timeout;
  109. /**
  110. * Task handle for making reply callbacks in numeric lookups
  111. * asynchronous, and for timeout handling.
  112. */
  113. struct GNUNET_SCHEDULER_Task *task;
  114. /**
  115. * Desired address family.
  116. */
  117. int af;
  118. /**
  119. * Identifies the request. The response will contain this id.
  120. */
  121. uint32_t id;
  122. /**
  123. * Has this request been transmitted to the service?
  124. * #GNUNET_YES if transmitted
  125. * #GNUNET_YES if not transmitted
  126. * #GNUNET_SYSERR when request was canceled
  127. */
  128. int was_transmitted;
  129. /**
  130. * Did we add this request to the queue?
  131. */
  132. int was_queued;
  133. /**
  134. * Desired direction (IP to name or name to IP)
  135. */
  136. int direction;
  137. /**
  138. * #GNUNET_YES if a response was received
  139. */
  140. int received_response;
  141. /**
  142. * Length of the data that follows this struct.
  143. */
  144. size_t data_len;
  145. };
  146. /**
  147. * Check that the resolver service runs on localhost
  148. * (or equivalent).
  149. *
  150. * @return #GNUNET_OK if the resolver is properly configured,
  151. * #GNUNET_SYSERR otherwise.
  152. */
  153. static int
  154. check_config ()
  155. {
  156. char *hostname;
  157. struct sockaddr_in v4;
  158. struct sockaddr_in6 v6;
  159. if (GNUNET_OK ==
  160. GNUNET_CONFIGURATION_have_value (resolver_cfg,
  161. "resolver",
  162. "UNIXPATH"))
  163. return GNUNET_OK;
  164. memset (&v4, 0, sizeof(v4));
  165. v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
  166. v4.sin_family = AF_INET;
  167. #if HAVE_SOCKADDR_IN_SIN_LEN
  168. v4.sin_len = sizeof(v4);
  169. #endif
  170. memset (&v6, 0, sizeof(v6));
  171. v6.sin6_family = AF_INET6;
  172. #if HAVE_SOCKADDR_IN_SIN_LEN
  173. v6.sin6_len = sizeof(v6);
  174. #endif
  175. if (GNUNET_OK !=
  176. GNUNET_CONFIGURATION_get_value_string (resolver_cfg,
  177. "resolver",
  178. "HOSTNAME",
  179. &hostname))
  180. {
  181. LOG (GNUNET_ERROR_TYPE_INFO,
  182. _ (
  183. "Missing `%s' for `%s' in configuration, DNS resolution will be unavailable.\n"),
  184. "HOSTNAME",
  185. "resolver");
  186. return GNUNET_SYSERR;
  187. }
  188. if ((1 == inet_pton (AF_INET, hostname, &v4)) ||
  189. (1 == inet_pton (AF_INET6, hostname, &v6)))
  190. {
  191. GNUNET_free (hostname);
  192. return GNUNET_OK;
  193. }
  194. for (unsigned int i = 0;
  195. NULL != loopback[i];
  196. i++)
  197. if (0 == strcasecmp (loopback[i],
  198. hostname))
  199. {
  200. GNUNET_free (hostname);
  201. return GNUNET_OK;
  202. }
  203. LOG (GNUNET_ERROR_TYPE_INFO,
  204. _ (
  205. "Missing `%s' or numeric IP address for `%s' of `%s' in configuration, DNS resolution will be unavailable.\n"),
  206. "localhost",
  207. "HOSTNAME",
  208. "resolver");
  209. GNUNET_free (hostname);
  210. return GNUNET_SYSERR;
  211. }
  212. /**
  213. * Create the connection to the resolver service.
  214. *
  215. * @param cfg configuration to use
  216. */
  217. void
  218. GNUNET_RESOLVER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
  219. {
  220. GNUNET_assert (NULL != cfg);
  221. backoff = GNUNET_TIME_UNIT_MILLISECONDS;
  222. resolver_cfg = cfg;
  223. }
  224. /**
  225. * Destroy the connection to the resolver service.
  226. */
  227. void
  228. GNUNET_RESOLVER_disconnect ()
  229. {
  230. struct GNUNET_RESOLVER_RequestHandle *rh;
  231. while (NULL != (rh = req_head))
  232. {
  233. GNUNET_assert (GNUNET_SYSERR == rh->was_transmitted);
  234. GNUNET_CONTAINER_DLL_remove (req_head,
  235. req_tail,
  236. rh);
  237. GNUNET_free (rh);
  238. }
  239. if (NULL != mq)
  240. {
  241. LOG (GNUNET_ERROR_TYPE_DEBUG,
  242. "Disconnecting from DNS service\n");
  243. GNUNET_MQ_destroy (mq);
  244. mq = NULL;
  245. }
  246. if (NULL != r_task)
  247. {
  248. GNUNET_SCHEDULER_cancel (r_task);
  249. r_task = NULL;
  250. }
  251. if (NULL != s_task)
  252. {
  253. GNUNET_SCHEDULER_cancel (s_task);
  254. s_task = NULL;
  255. }
  256. }
  257. /**
  258. * Task executed on system shutdown.
  259. */
  260. static void
  261. shutdown_task (void *cls)
  262. {
  263. (void) cls;
  264. s_task = NULL;
  265. GNUNET_RESOLVER_disconnect ();
  266. backoff = GNUNET_TIME_UNIT_MILLISECONDS;
  267. }
  268. /**
  269. * Consider disconnecting if we have no further requests pending.
  270. */
  271. static void
  272. check_disconnect ()
  273. {
  274. for (struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
  275. NULL != rh;
  276. rh = rh->next)
  277. if (GNUNET_SYSERR != rh->was_transmitted)
  278. return;
  279. if (NULL != r_task)
  280. {
  281. GNUNET_SCHEDULER_cancel (r_task);
  282. r_task = NULL;
  283. }
  284. if (NULL != s_task)
  285. return;
  286. s_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
  287. &shutdown_task,
  288. NULL);
  289. }
  290. /**
  291. * Convert IP address to string without DNS resolution.
  292. *
  293. * @param af address family
  294. * @param ip the address
  295. * @param ip_len number of bytes in @a ip
  296. * @return address as a string, NULL on error
  297. */
  298. static char *
  299. no_resolve (int af,
  300. const void *ip,
  301. socklen_t ip_len)
  302. {
  303. char buf[INET6_ADDRSTRLEN];
  304. switch (af)
  305. {
  306. case AF_INET:
  307. if (ip_len != sizeof(struct in_addr))
  308. return NULL;
  309. if (NULL ==
  310. inet_ntop (AF_INET,
  311. ip,
  312. buf,
  313. sizeof(buf)))
  314. {
  315. LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
  316. "inet_ntop");
  317. return NULL;
  318. }
  319. break;
  320. case AF_INET6:
  321. if (ip_len != sizeof(struct in6_addr))
  322. return NULL;
  323. if (NULL ==
  324. inet_ntop (AF_INET6,
  325. ip,
  326. buf,
  327. sizeof(buf)))
  328. {
  329. LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
  330. "inet_ntop");
  331. return NULL;
  332. }
  333. break;
  334. default:
  335. GNUNET_break (0);
  336. return NULL;
  337. }
  338. return GNUNET_strdup (buf);
  339. }
  340. /**
  341. * Adjust exponential back-off and reconnect to the service.
  342. */
  343. static void
  344. reconnect (void);
  345. /**
  346. * Generic error handler, called with the appropriate error code and
  347. * the same closure specified at the creation of the message queue.
  348. * Not every message queue implementation supports an error handler.
  349. *
  350. * @param cls NULL
  351. * @param error error code
  352. */
  353. static void
  354. mq_error_handler (void *cls,
  355. enum GNUNET_MQ_Error error)
  356. {
  357. (void) cls;
  358. GNUNET_MQ_destroy (mq);
  359. mq = NULL;
  360. LOG (GNUNET_ERROR_TYPE_DEBUG,
  361. "MQ error %d, reconnecting\n",
  362. error);
  363. reconnect ();
  364. }
  365. /**
  366. * Process pending requests to the resolver.
  367. */
  368. static void
  369. process_requests ()
  370. {
  371. struct GNUNET_RESOLVER_GetMessage *msg;
  372. struct GNUNET_MQ_Envelope *env;
  373. struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
  374. if (NULL == mq)
  375. {
  376. reconnect ();
  377. return;
  378. }
  379. if (NULL == rh)
  380. {
  381. /* nothing to do, release socket really soon if there is nothing
  382. * else happening... */
  383. if (NULL == s_task)
  384. s_task =
  385. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
  386. &shutdown_task,
  387. NULL);
  388. return;
  389. }
  390. if (GNUNET_NO != rh->was_transmitted)
  391. return; /* waiting for reply */
  392. env = GNUNET_MQ_msg_extra (msg,
  393. rh->data_len,
  394. GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
  395. msg->direction = htonl (rh->direction);
  396. msg->af = htonl (rh->af);
  397. msg->client_id = rh->id;
  398. GNUNET_memcpy (&msg[1],
  399. &rh[1],
  400. rh->data_len);
  401. LOG (GNUNET_ERROR_TYPE_DEBUG,
  402. "Transmitting DNS resolution request (ID %u) to DNS service\n",
  403. rh->id);
  404. GNUNET_MQ_send (mq,
  405. env);
  406. rh->was_transmitted = GNUNET_YES;
  407. }
  408. /**
  409. * Check validity of response with a hostname for a DNS lookup.
  410. *
  411. * @param cls NULL
  412. * @param msg message with the hostname
  413. */
  414. static int
  415. check_response (void *cls,
  416. const struct GNUNET_RESOLVER_ResponseMessage *msg)
  417. {
  418. (void) cls;
  419. (void) msg;
  420. /* implemented in #handle_response() for now */
  421. return GNUNET_OK;
  422. }
  423. /**
  424. * Check validity of response with a hostname for a DNS lookup.
  425. * NOTE: right now rather messy, might want to use different
  426. * message types for different response formats in the future.
  427. *
  428. * @param cls NULL
  429. * @param msg message with the response
  430. */
  431. static void
  432. handle_response (void *cls,
  433. const struct GNUNET_RESOLVER_ResponseMessage *msg)
  434. {
  435. struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
  436. uint16_t size;
  437. char *nret;
  438. uint32_t client_request_id = msg->client_id;
  439. for (; rh != NULL; rh = rh->next)
  440. {
  441. if (rh->id == client_request_id)
  442. break;
  443. }
  444. (void) cls;
  445. if (NULL == rh)
  446. {
  447. /* Resolver service sent extra replies to query (after terminator)? Bad! */
  448. GNUNET_break (0);
  449. GNUNET_MQ_destroy (mq);
  450. mq = NULL;
  451. reconnect ();
  452. return;
  453. }
  454. size = ntohs (msg->header.size);
  455. if (size == sizeof(struct GNUNET_RESOLVER_ResponseMessage))
  456. {
  457. LOG (GNUNET_ERROR_TYPE_DEBUG,
  458. "Received empty response from DNS service\n");
  459. /* message contains not data, just header; end of replies */
  460. /* check if request was canceled */
  461. if (GNUNET_SYSERR != rh->was_transmitted)
  462. {
  463. /* no reverse lookup was successful, return IP as string */
  464. if (NULL != rh->name_callback)
  465. {
  466. if (GNUNET_NO == rh->received_response)
  467. {
  468. nret = no_resolve (rh->af,
  469. &rh[1],
  470. rh->data_len);
  471. rh->name_callback (rh->cls, nret);
  472. GNUNET_free (nret);
  473. }
  474. /* finally, make termination call */
  475. if (GNUNET_SYSERR != rh->was_transmitted)
  476. rh->name_callback (rh->cls,
  477. NULL);
  478. }
  479. if ((NULL != rh->addr_callback) &&
  480. (GNUNET_SYSERR != rh->was_transmitted))
  481. rh->addr_callback (rh->cls,
  482. NULL,
  483. 0);
  484. }
  485. rh->was_transmitted = GNUNET_NO;
  486. GNUNET_RESOLVER_request_cancel (rh);
  487. process_requests ();
  488. return;
  489. }
  490. /* return reverse lookup results to caller */
  491. if (NULL != rh->name_callback)
  492. {
  493. const char *hostname;
  494. hostname = (const char *) &msg[1];
  495. if (hostname[size - sizeof(struct GNUNET_RESOLVER_ResponseMessage) - 1] !=
  496. '\0')
  497. {
  498. GNUNET_break (0);
  499. if (GNUNET_SYSERR != rh->was_transmitted)
  500. rh->name_callback (rh->cls,
  501. NULL);
  502. rh->was_transmitted = GNUNET_NO;
  503. GNUNET_RESOLVER_request_cancel (rh);
  504. GNUNET_MQ_destroy (mq);
  505. mq = NULL;
  506. reconnect ();
  507. return;
  508. }
  509. LOG (GNUNET_ERROR_TYPE_DEBUG,
  510. "Resolver returns `%s' for IP `%s'.\n",
  511. hostname,
  512. GNUNET_a2s ((const void *) &rh[1],
  513. rh->data_len));
  514. if (rh->was_transmitted != GNUNET_SYSERR)
  515. rh->name_callback (rh->cls,
  516. hostname);
  517. rh->received_response = GNUNET_YES;
  518. }
  519. /* return lookup results to caller */
  520. if (NULL != rh->addr_callback)
  521. {
  522. struct sockaddr_in v4;
  523. struct sockaddr_in6 v6;
  524. const struct sockaddr *sa;
  525. socklen_t salen;
  526. const void *ip;
  527. size_t ip_len;
  528. ip = &msg[1];
  529. ip_len = size - sizeof(struct GNUNET_RESOLVER_ResponseMessage);
  530. if (ip_len == sizeof(struct in_addr))
  531. {
  532. memset (&v4, 0, sizeof(v4));
  533. v4.sin_family = AF_INET;
  534. v4.sin_addr = *(struct in_addr*) ip;
  535. #if HAVE_SOCKADDR_IN_SIN_LEN
  536. v4.sin_len = sizeof(v4);
  537. #endif
  538. salen = sizeof(v4);
  539. sa = (const struct sockaddr *) &v4;
  540. }
  541. else if (ip_len == sizeof(struct in6_addr))
  542. {
  543. memset (&v6, 0, sizeof(v6));
  544. v6.sin6_family = AF_INET6;
  545. v6.sin6_addr = *(struct in6_addr*) ip;
  546. #if HAVE_SOCKADDR_IN_SIN_LEN
  547. v6.sin6_len = sizeof(v6);
  548. #endif
  549. salen = sizeof(v6);
  550. sa = (const struct sockaddr *) &v6;
  551. }
  552. else
  553. {
  554. GNUNET_break (0);
  555. if (GNUNET_SYSERR != rh->was_transmitted)
  556. rh->addr_callback (rh->cls,
  557. NULL,
  558. 0);
  559. rh->was_transmitted = GNUNET_NO;
  560. GNUNET_RESOLVER_request_cancel (rh);
  561. GNUNET_MQ_destroy (mq);
  562. mq = NULL;
  563. reconnect ();
  564. return;
  565. }
  566. LOG (GNUNET_ERROR_TYPE_DEBUG,
  567. "Received IP from DNS service\n");
  568. if (GNUNET_SYSERR != rh->was_transmitted)
  569. rh->addr_callback (rh->cls,
  570. sa,
  571. salen);
  572. }
  573. }
  574. /**
  575. * We've been asked to lookup the address for a hostname and were
  576. * given a valid numeric string. Perform the callbacks for the
  577. * numeric addresses.
  578. *
  579. * @param cls `struct GNUNET_RESOLVER_RequestHandle` for the request
  580. */
  581. static void
  582. numeric_resolution (void *cls)
  583. {
  584. struct GNUNET_RESOLVER_RequestHandle *rh = cls;
  585. struct sockaddr_in v4;
  586. struct sockaddr_in6 v6;
  587. const char *hostname;
  588. rh->task = NULL;
  589. memset (&v4, 0, sizeof(v4));
  590. v4.sin_family = AF_INET;
  591. #if HAVE_SOCKADDR_IN_SIN_LEN
  592. v4.sin_len = sizeof(v4);
  593. #endif
  594. memset (&v6, 0, sizeof(v6));
  595. v6.sin6_family = AF_INET6;
  596. #if HAVE_SOCKADDR_IN_SIN_LEN
  597. v6.sin6_len = sizeof(v6);
  598. #endif
  599. hostname = (const char *) &rh[1];
  600. if (((rh->af == AF_UNSPEC) ||
  601. (rh->af == AF_INET)) &&
  602. (1 == inet_pton (AF_INET,
  603. hostname,
  604. &v4.sin_addr)))
  605. {
  606. rh->addr_callback (rh->cls,
  607. (const struct sockaddr *) &v4,
  608. sizeof(v4));
  609. if ((rh->af == AF_UNSPEC) &&
  610. (GNUNET_SYSERR != rh->was_transmitted) &&
  611. (1 == inet_pton (AF_INET6,
  612. hostname,
  613. &v6.sin6_addr)))
  614. {
  615. /* this can happen on some systems IF "hostname" is "localhost" */
  616. rh->addr_callback (rh->cls,
  617. (const struct sockaddr *) &v6,
  618. sizeof(v6));
  619. }
  620. if (GNUNET_SYSERR != rh->was_transmitted)
  621. rh->addr_callback (rh->cls,
  622. NULL,
  623. 0);
  624. GNUNET_free (rh);
  625. return;
  626. }
  627. if (((rh->af == AF_UNSPEC) ||
  628. (rh->af == AF_INET6)) &&
  629. (1 == inet_pton (AF_INET6,
  630. hostname,
  631. &v6.sin6_addr)))
  632. {
  633. rh->addr_callback (rh->cls,
  634. (const struct sockaddr *) &v6,
  635. sizeof(v6));
  636. if (GNUNET_SYSERR != rh->was_transmitted)
  637. rh->addr_callback (rh->cls,
  638. NULL,
  639. 0);
  640. GNUNET_free (rh);
  641. return;
  642. }
  643. /* why are we here? this task should not have been scheduled! */
  644. GNUNET_assert (0);
  645. GNUNET_free (rh);
  646. }
  647. /**
  648. * We've been asked to lookup the address for a hostname and were
  649. * given a variant of "loopback". Perform the callbacks for the
  650. * respective loopback numeric addresses.
  651. *
  652. * @param cls `struct GNUNET_RESOLVER_RequestHandle` for the request
  653. */
  654. static void
  655. loopback_resolution (void *cls)
  656. {
  657. struct GNUNET_RESOLVER_RequestHandle *rh = cls;
  658. struct sockaddr_in v4;
  659. struct sockaddr_in6 v6;
  660. rh->task = NULL;
  661. memset (&v4, 0, sizeof(v4));
  662. v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
  663. v4.sin_family = AF_INET;
  664. #if HAVE_SOCKADDR_IN_SIN_LEN
  665. v4.sin_len = sizeof(v4);
  666. #endif
  667. memset (&v6, 0, sizeof(v6));
  668. v6.sin6_family = AF_INET6;
  669. #if HAVE_SOCKADDR_IN_SIN_LEN
  670. v6.sin6_len = sizeof(v6);
  671. #endif
  672. v6.sin6_addr = in6addr_loopback;
  673. switch (rh->af)
  674. {
  675. case AF_INET:
  676. rh->addr_callback (rh->cls,
  677. (const struct sockaddr *) &v4,
  678. sizeof(v4));
  679. break;
  680. case AF_INET6:
  681. rh->addr_callback (rh->cls,
  682. (const struct sockaddr *) &v6,
  683. sizeof(v6));
  684. break;
  685. case AF_UNSPEC:
  686. rh->addr_callback (rh->cls,
  687. (const struct sockaddr *) &v6,
  688. sizeof(v6));
  689. rh->addr_callback (rh->cls,
  690. (const struct sockaddr *) &v4,
  691. sizeof(v4));
  692. break;
  693. default:
  694. GNUNET_break (0);
  695. break;
  696. }
  697. if (GNUNET_SYSERR != rh->was_transmitted)
  698. rh->addr_callback (rh->cls,
  699. NULL,
  700. 0);
  701. LOG (GNUNET_ERROR_TYPE_DEBUG,
  702. "Finished resolving hostname `%s'.\n",
  703. (const char *) &rh[1]);
  704. GNUNET_free (rh);
  705. }
  706. /**
  707. * Now try to reconnect to the resolver service.
  708. *
  709. * @param cls NULL
  710. */
  711. static void
  712. reconnect_task (void *cls)
  713. {
  714. struct GNUNET_MQ_MessageHandler handlers[] = {
  715. GNUNET_MQ_hd_var_size (response,
  716. GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE,
  717. struct GNUNET_RESOLVER_ResponseMessage,
  718. NULL),
  719. GNUNET_MQ_handler_end ()
  720. };
  721. (void) cls;
  722. r_task = NULL;
  723. if (NULL == req_head)
  724. return; /* no work pending */
  725. LOG (GNUNET_ERROR_TYPE_DEBUG,
  726. "Trying to connect to DNS service\n");
  727. mq = GNUNET_CLIENT_connect (resolver_cfg,
  728. "resolver",
  729. handlers,
  730. &mq_error_handler,
  731. NULL);
  732. if (NULL == mq)
  733. {
  734. LOG (GNUNET_ERROR_TYPE_DEBUG,
  735. "Failed to connect, will try again later\n");
  736. reconnect ();
  737. return;
  738. }
  739. process_requests ();
  740. }
  741. /**
  742. * Adjust exponential back-off and reconnect to the service.
  743. */
  744. static void
  745. reconnect ()
  746. {
  747. struct GNUNET_RESOLVER_RequestHandle *rh;
  748. if (NULL != r_task)
  749. return;
  750. GNUNET_assert (NULL == mq);
  751. if (NULL != (rh = req_head))
  752. {
  753. switch (rh->was_transmitted)
  754. {
  755. case GNUNET_NO:
  756. /* nothing more to do */
  757. break;
  758. case GNUNET_YES:
  759. /* disconnected, transmit again! */
  760. rh->was_transmitted = GNUNET_NO;
  761. break;
  762. case GNUNET_SYSERR:
  763. /* request was cancelled, remove entirely */
  764. GNUNET_CONTAINER_DLL_remove (req_head,
  765. req_tail,
  766. rh);
  767. GNUNET_free (rh);
  768. check_disconnect ();
  769. break;
  770. default:
  771. GNUNET_assert (0);
  772. break;
  773. }
  774. }
  775. LOG (GNUNET_ERROR_TYPE_DEBUG,
  776. "Will try to connect to DNS service in %s\n",
  777. GNUNET_STRINGS_relative_time_to_string (backoff,
  778. GNUNET_YES));
  779. GNUNET_assert (NULL != resolver_cfg);
  780. r_task = GNUNET_SCHEDULER_add_delayed (backoff,
  781. &reconnect_task,
  782. NULL);
  783. backoff = GNUNET_TIME_STD_BACKOFF (backoff);
  784. }
  785. /**
  786. * A DNS resolution timed out. Notify the application.
  787. *
  788. * @param cls the `struct GNUNET_RESOLVER_RequestHandle *`
  789. */
  790. static void
  791. handle_lookup_timeout (void *cls)
  792. {
  793. struct GNUNET_RESOLVER_RequestHandle *rh = cls;
  794. rh->task = NULL;
  795. if (GNUNET_NO == rh->direction)
  796. {
  797. LOG (GNUNET_ERROR_TYPE_INFO,
  798. _ ("Timeout trying to resolve hostname `%s'.\n"),
  799. (const char *) &rh[1]);
  800. if (NULL != rh->addr_callback)
  801. rh->addr_callback (rh->cls,
  802. NULL,
  803. 0);
  804. }
  805. else
  806. {
  807. #if ! defined(GNUNET_CULL_LOGGING)
  808. char buf[INET6_ADDRSTRLEN];
  809. LOG (GNUNET_ERROR_TYPE_INFO,
  810. _ ("Timeout trying to resolve IP address `%s'.\n"),
  811. inet_ntop (rh->af,
  812. (const void *) &rh[1],
  813. buf,
  814. sizeof(buf)));
  815. #endif
  816. if (GNUNET_NO == rh->received_response)
  817. {
  818. char *nret;
  819. nret = no_resolve (rh->af,
  820. &rh[1],
  821. rh->data_len);
  822. if (NULL != rh->name_callback)
  823. rh->name_callback (rh->cls, nret);
  824. GNUNET_free (nret);
  825. }
  826. /* finally, make termination call */
  827. if (NULL != rh->name_callback)
  828. rh->name_callback (rh->cls,
  829. NULL);
  830. }
  831. rh->was_transmitted = GNUNET_NO;
  832. GNUNET_RESOLVER_request_cancel (rh);
  833. process_requests ();
  834. }
  835. /**
  836. * Convert a string to one or more IP addresses.
  837. *
  838. * @param hostname the hostname to resolve
  839. * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any"
  840. * @param callback function to call with addresses
  841. * @param callback_cls closure for @a callback
  842. * @param timeout how long to try resolving
  843. * @return handle that can be used to cancel the request, NULL on error
  844. */
  845. struct GNUNET_RESOLVER_RequestHandle *
  846. GNUNET_RESOLVER_ip_get (const char *hostname,
  847. int af,
  848. struct GNUNET_TIME_Relative timeout,
  849. GNUNET_RESOLVER_AddressCallback callback,
  850. void *callback_cls)
  851. {
  852. struct GNUNET_RESOLVER_RequestHandle *rh;
  853. size_t slen;
  854. struct in_addr v4;
  855. struct in6_addr v6;
  856. slen = strlen (hostname) + 1;
  857. if (slen + sizeof(struct GNUNET_RESOLVER_GetMessage) >=
  858. GNUNET_MAX_MESSAGE_SIZE)
  859. {
  860. GNUNET_break (0);
  861. return NULL;
  862. }
  863. LOG (GNUNET_ERROR_TYPE_DEBUG,
  864. "Trying to resolve hostname `%s'.\n",
  865. hostname);
  866. rh = GNUNET_malloc (sizeof(struct GNUNET_RESOLVER_RequestHandle) + slen);
  867. rh->af = af;
  868. rh->id = ++last_request_id;
  869. rh->addr_callback = callback;
  870. rh->cls = callback_cls;
  871. GNUNET_memcpy (&rh[1],
  872. hostname,
  873. slen);
  874. rh->data_len = slen;
  875. rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
  876. rh->direction = GNUNET_NO;
  877. /* first, check if this is a numeric address */
  878. if (((1 == inet_pton (AF_INET,
  879. hostname,
  880. &v4)) &&
  881. ((af == AF_INET) ||
  882. (af == AF_UNSPEC))) ||
  883. ((1 == inet_pton (AF_INET6,
  884. hostname,
  885. &v6)) &&
  886. ((af == AF_INET6) ||
  887. (af == AF_UNSPEC))))
  888. {
  889. rh->task = GNUNET_SCHEDULER_add_now (&numeric_resolution,
  890. rh);
  891. return rh;
  892. }
  893. /* then, check if this is a loopback address */
  894. for (unsigned int i = 0;
  895. NULL != loopback[i];
  896. i++)
  897. if (0 == strcasecmp (loopback[i],
  898. hostname))
  899. {
  900. rh->task = GNUNET_SCHEDULER_add_now (&loopback_resolution,
  901. rh);
  902. return rh;
  903. }
  904. if (GNUNET_OK != check_config ())
  905. {
  906. GNUNET_free (rh);
  907. return NULL;
  908. }
  909. rh->task = GNUNET_SCHEDULER_add_delayed (timeout,
  910. &handle_lookup_timeout,
  911. rh);
  912. GNUNET_CONTAINER_DLL_insert_tail (req_head,
  913. req_tail,
  914. rh);
  915. rh->was_queued = GNUNET_YES;
  916. if (NULL != s_task)
  917. {
  918. GNUNET_SCHEDULER_cancel (s_task);
  919. s_task = NULL;
  920. }
  921. process_requests ();
  922. return rh;
  923. }
  924. /**
  925. * We've been asked to convert an address to a string without
  926. * a reverse lookup, either because the client asked for it
  927. * or because the DNS lookup hit a timeout. Do the numeric
  928. * conversion and invoke the callback.
  929. *
  930. * @param cls `struct GNUNET_RESOLVER_RequestHandle` for the request
  931. */
  932. static void
  933. numeric_reverse (void *cls)
  934. {
  935. struct GNUNET_RESOLVER_RequestHandle *rh = cls;
  936. char *result;
  937. rh->task = NULL;
  938. result = no_resolve (rh->af,
  939. &rh[1],
  940. rh->data_len);
  941. LOG (GNUNET_ERROR_TYPE_DEBUG,
  942. "Resolver returns `%s'.\n",
  943. result);
  944. if (NULL != result)
  945. {
  946. rh->name_callback (rh->cls,
  947. result);
  948. GNUNET_free (result);
  949. }
  950. rh->name_callback (rh->cls,
  951. NULL);
  952. if (NULL != rh->task)
  953. {
  954. GNUNET_SCHEDULER_cancel (rh->task);
  955. rh->task = NULL;
  956. }
  957. GNUNET_free (rh);
  958. }
  959. /**
  960. * Get an IP address as a string.
  961. *
  962. * @param sa host address
  963. * @param salen length of host address in @a sa
  964. * @param do_resolve use #GNUNET_NO to return numeric hostname
  965. * @param timeout how long to try resolving
  966. * @param callback function to call with hostnames
  967. * last callback is NULL when finished
  968. * @param cls closure for @a callback
  969. * @return handle that can be used to cancel the request
  970. */
  971. struct GNUNET_RESOLVER_RequestHandle *
  972. GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa,
  973. socklen_t salen,
  974. int do_resolve,
  975. struct GNUNET_TIME_Relative timeout,
  976. GNUNET_RESOLVER_HostnameCallback callback,
  977. void *cls)
  978. {
  979. struct GNUNET_RESOLVER_RequestHandle *rh;
  980. size_t ip_len;
  981. const void *ip;
  982. if (GNUNET_OK != check_config ())
  983. {
  984. LOG (GNUNET_ERROR_TYPE_ERROR,
  985. _ ("Resolver not configured correctly.\n"));
  986. return NULL;
  987. }
  988. switch (sa->sa_family)
  989. {
  990. case AF_INET:
  991. GNUNET_assert (salen == sizeof(struct sockaddr_in));
  992. ip_len = sizeof(struct in_addr);
  993. ip = &((const struct sockaddr_in*) sa)->sin_addr;
  994. break;
  995. case AF_INET6:
  996. GNUNET_assert (salen == sizeof(struct sockaddr_in6));
  997. ip_len = sizeof(struct in6_addr);
  998. ip = &((const struct sockaddr_in6*) sa)->sin6_addr;
  999. break;
  1000. default:
  1001. GNUNET_break (0);
  1002. return NULL;
  1003. }
  1004. rh = GNUNET_malloc (sizeof(struct GNUNET_RESOLVER_RequestHandle) + salen);
  1005. rh->name_callback = callback;
  1006. rh->cls = cls;
  1007. rh->af = sa->sa_family;
  1008. rh->id = ++last_request_id;
  1009. rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
  1010. GNUNET_memcpy (&rh[1],
  1011. ip,
  1012. ip_len);
  1013. rh->data_len = ip_len;
  1014. rh->direction = GNUNET_YES;
  1015. rh->received_response = GNUNET_NO;
  1016. if (GNUNET_NO == do_resolve)
  1017. {
  1018. rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse,
  1019. rh);
  1020. return rh;
  1021. }
  1022. rh->task = GNUNET_SCHEDULER_add_delayed (timeout,
  1023. &handle_lookup_timeout,
  1024. rh);
  1025. GNUNET_CONTAINER_DLL_insert_tail (req_head,
  1026. req_tail,
  1027. rh);
  1028. rh->was_queued = GNUNET_YES;
  1029. if (NULL != s_task)
  1030. {
  1031. GNUNET_SCHEDULER_cancel (s_task);
  1032. s_task = NULL;
  1033. }
  1034. process_requests ();
  1035. return rh;
  1036. }
  1037. /**
  1038. * Get local fully qualified af name
  1039. *
  1040. * @return fqdn
  1041. */
  1042. char *
  1043. GNUNET_RESOLVER_local_fqdn_get ()
  1044. {
  1045. char hostname[GNUNET_OS_get_hostname_max_length () + 1];
  1046. if (0 != gethostname (hostname,
  1047. sizeof(hostname) - 1))
  1048. {
  1049. LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
  1050. "gethostname");
  1051. return NULL;
  1052. }
  1053. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1054. "Resolving our FQDN `%s'\n",
  1055. hostname);
  1056. #if HAVE_GETADDRINFO
  1057. {
  1058. struct addrinfo *ai;
  1059. int ret;
  1060. char *rval;
  1061. if (0 != (ret = getaddrinfo (hostname,
  1062. NULL,
  1063. NULL,
  1064. &ai)))
  1065. {
  1066. LOG (GNUNET_ERROR_TYPE_ERROR,
  1067. _ ("Could not resolve our FQDN: %s\n"),
  1068. gai_strerror (ret));
  1069. return NULL;
  1070. }
  1071. if (NULL != ai->ai_canonname)
  1072. rval = GNUNET_strdup (ai->ai_canonname);
  1073. else
  1074. rval = GNUNET_strdup (hostname);
  1075. freeaddrinfo (ai);
  1076. return rval;
  1077. }
  1078. #elif HAVE_GETHOSTBYNAME2
  1079. {
  1080. struct hostent *host;
  1081. host = gethostbyname2 (hostname,
  1082. AF_INET);
  1083. if (NULL == host)
  1084. host = gethostbyname2 (hostname,
  1085. AF_INET6);
  1086. if (NULL == host)
  1087. {
  1088. LOG (GNUNET_ERROR_TYPE_ERROR,
  1089. _ ("Could not resolve our FQDN: %s\n"),
  1090. hstrerror (h_errno));
  1091. return NULL;
  1092. }
  1093. return GNUNET_strdup (host->h_name);
  1094. }
  1095. #elif HAVE_GETHOSTBYNAME
  1096. {
  1097. struct hostent *host;
  1098. host = gethostbyname (hostname);
  1099. if (NULL == host)
  1100. {
  1101. LOG (GNUNET_ERROR_TYPE_ERROR,
  1102. _ ("Could not resolve our FQDN: %s\n"),
  1103. hstrerror (h_errno));
  1104. return NULL;
  1105. }
  1106. return GNUNET_strdup (host->h_name);
  1107. }
  1108. #else
  1109. /* fallback: just hope name is already FQDN */
  1110. return GNUNET_strdup (hostname);
  1111. #endif
  1112. }
  1113. /**
  1114. * Looking our own hostname.
  1115. *
  1116. * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any"
  1117. * @param timeout how long to try resolving
  1118. * @param callback function to call with addresses
  1119. * @param cls closure for @a callback
  1120. * @return handle that can be used to cancel the request, NULL on error
  1121. */
  1122. struct GNUNET_RESOLVER_RequestHandle *
  1123. GNUNET_RESOLVER_hostname_resolve (int af,
  1124. struct GNUNET_TIME_Relative timeout,
  1125. GNUNET_RESOLVER_AddressCallback callback,
  1126. void *cls)
  1127. {
  1128. char hostname[GNUNET_OS_get_hostname_max_length () + 1];
  1129. if (0 != gethostname (hostname, sizeof(hostname) - 1))
  1130. {
  1131. LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
  1132. "gethostname");
  1133. return NULL;
  1134. }
  1135. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1136. "Resolving our hostname `%s'\n",
  1137. hostname);
  1138. return GNUNET_RESOLVER_ip_get (hostname,
  1139. af,
  1140. timeout,
  1141. callback,
  1142. cls);
  1143. }
  1144. /**
  1145. * Cancel a request that is still pending with the resolver.
  1146. * Note that a client MUST NOT cancel a request that has
  1147. * been completed (i.e, the callback has been called to
  1148. * signal timeout or the final result).
  1149. *
  1150. * @param rh handle of request to cancel
  1151. */
  1152. void
  1153. GNUNET_RESOLVER_request_cancel (struct GNUNET_RESOLVER_RequestHandle *rh)
  1154. {
  1155. if (GNUNET_NO == rh->direction)
  1156. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1157. "Asked to cancel request to resolve hostname `%s'.\n",
  1158. (const char *) &rh[1]);
  1159. if (NULL != rh->task)
  1160. {
  1161. GNUNET_SCHEDULER_cancel (rh->task);
  1162. rh->task = NULL;
  1163. }
  1164. if (GNUNET_NO == rh->was_transmitted)
  1165. {
  1166. if (GNUNET_YES == rh->was_queued)
  1167. GNUNET_CONTAINER_DLL_remove (req_head,
  1168. req_tail,
  1169. rh);
  1170. GNUNET_free (rh);
  1171. check_disconnect ();
  1172. return;
  1173. }
  1174. GNUNET_assert (GNUNET_YES == rh->was_transmitted);
  1175. rh->was_transmitted = GNUNET_SYSERR; /* mark as cancelled */
  1176. check_disconnect ();
  1177. }
  1178. /* end of resolver_api.c */