2 This file is part of GNUnet.
3 Copyright (C) 2009-2018 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @file util/resolver_api.c
21 * @brief resolver for writing a tool
22 * @author Christian Grothoff
25 #include "gnunet_util_lib.h"
26 #include "gnunet_protocols.h"
27 #include "gnunet_resolver_service.h"
30 #define LOG(kind,...) GNUNET_log_from (kind, "util-resolver-api", __VA_ARGS__)
32 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-resolver-api", syscall)
35 * Maximum supported length for a hostname
37 #define MAX_HOSTNAME 1024
41 * Possible hostnames for "loopback".
43 static const char *loopback[] = {
53 static const struct GNUNET_CONFIGURATION_Handle *resolver_cfg;
56 * Our connection to the resolver service, created on-demand, but then
57 * persists until error or shutdown.
59 static struct GNUNET_MQ_Handle *mq;
62 * Head of DLL of requests.
64 static struct GNUNET_RESOLVER_RequestHandle *req_head;
67 * Tail of DLL of requests.
69 static struct GNUNET_RESOLVER_RequestHandle *req_tail;
72 * ID of the last request we sent to the service
74 static uint32_t last_request_id;
77 * How long should we wait to reconnect?
79 static struct GNUNET_TIME_Relative backoff;
82 * Task for reconnecting.
84 static struct GNUNET_SCHEDULER_Task *r_task;
87 * Task ID of shutdown task; only present while we have a
88 * connection to the resolver service.
90 static struct GNUNET_SCHEDULER_Task *s_task;
94 * Handle to a request given to the resolver. Can be used to cancel
95 * the request prior to the timeout or successful execution. Also
96 * used to track our internal state for the request.
98 struct GNUNET_RESOLVER_RequestHandle
102 * Next entry in DLL of requests.
104 struct GNUNET_RESOLVER_RequestHandle *next;
107 * Previous entry in DLL of requests.
109 struct GNUNET_RESOLVER_RequestHandle *prev;
112 * Callback if this is an name resolution request,
115 GNUNET_RESOLVER_AddressCallback addr_callback;
118 * Callback if this is a reverse lookup request,
121 GNUNET_RESOLVER_HostnameCallback name_callback;
124 * Closure for the callbacks.
129 * When should this request time out?
131 struct GNUNET_TIME_Absolute timeout;
134 * Task handle for making reply callbacks in numeric lookups
135 * asynchronous, and for timeout handling.
137 struct GNUNET_SCHEDULER_Task *task;
140 * Desired address family.
145 * Identifies the request. The response will contain this id.
150 * Has this request been transmitted to the service?
151 * #GNUNET_YES if transmitted
152 * #GNUNET_YES if not transmitted
153 * #GNUNET_SYSERR when request was canceled
158 * Did we add this request to the queue?
163 * Desired direction (IP to name or name to IP)
168 * #GNUNET_YES if a response was received
170 int received_response;
173 * Length of the data that follows this struct.
180 * Check that the resolver service runs on localhost
183 * @return #GNUNET_OK if the resolver is properly configured,
184 * #GNUNET_SYSERR otherwise.
190 struct sockaddr_in v4;
191 struct sockaddr_in6 v6;
194 GNUNET_CONFIGURATION_have_value (resolver_cfg,
198 memset (&v4, 0, sizeof (v4));
199 v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
200 v4.sin_family = AF_INET;
201 #if HAVE_SOCKADDR_IN_SIN_LEN
202 v4.sin_len = sizeof (v4);
204 memset (&v6, 0, sizeof (v6));
205 v6.sin6_family = AF_INET6;
206 #if HAVE_SOCKADDR_IN_SIN_LEN
207 v6.sin6_len = sizeof (v6);
210 GNUNET_CONFIGURATION_get_value_string (resolver_cfg,
215 LOG (GNUNET_ERROR_TYPE_INFO,
216 _("Missing `%s' for `%s' in configuration, DNS resolution will be unavailable.\n"),
219 return GNUNET_SYSERR;
221 if ( (1 == inet_pton (AF_INET, hostname, &v4)) ||
222 (1 == inet_pton (AF_INET6, hostname, &v6)) )
224 GNUNET_free (hostname);
227 for (unsigned int i = 0;
230 if (0 == strcasecmp (loopback[i],
233 GNUNET_free (hostname);
236 LOG (GNUNET_ERROR_TYPE_INFO,
237 _("Missing `%s' or numeric IP address for `%s' of `%s' in configuration, DNS resolution will be unavailable.\n"),
241 GNUNET_free (hostname);
242 return GNUNET_SYSERR;
247 * Create the connection to the resolver service.
249 * @param cfg configuration to use
252 GNUNET_RESOLVER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
254 GNUNET_assert (NULL != cfg);
255 backoff = GNUNET_TIME_UNIT_MILLISECONDS;
261 * Destroy the connection to the resolver service.
264 GNUNET_RESOLVER_disconnect ()
266 struct GNUNET_RESOLVER_RequestHandle *rh;
268 while (NULL != (rh = req_head))
270 GNUNET_assert (GNUNET_SYSERR == rh->was_transmitted);
271 GNUNET_CONTAINER_DLL_remove (req_head,
278 LOG (GNUNET_ERROR_TYPE_DEBUG,
279 "Disconnecting from DNS service\n");
280 GNUNET_MQ_destroy (mq);
285 GNUNET_SCHEDULER_cancel (r_task);
290 GNUNET_SCHEDULER_cancel (s_task);
297 * Task executed on system shutdown.
300 shutdown_task (void *cls)
304 GNUNET_RESOLVER_disconnect ();
305 backoff = GNUNET_TIME_UNIT_MILLISECONDS;
310 * Consider disconnecting if we have no further requests pending.
315 for (struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
318 if (GNUNET_SYSERR != rh->was_transmitted)
322 GNUNET_SCHEDULER_cancel (r_task);
327 s_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
334 * Convert IP address to string without DNS resolution.
336 * @param af address family
337 * @param ip the address
338 * @param ip_len number of bytes in @a ip
339 * @return address as a string, NULL on error
346 char buf[INET6_ADDRSTRLEN];
351 if (ip_len != sizeof (struct in_addr))
359 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
365 if (ip_len != sizeof (struct in6_addr))
373 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
382 return GNUNET_strdup (buf);
387 * Adjust exponential back-off and reconnect to the service.
394 * Generic error handler, called with the appropriate error code and
395 * the same closure specified at the creation of the message queue.
396 * Not every message queue implementation supports an error handler.
399 * @param error error code
402 mq_error_handler (void *cls,
403 enum GNUNET_MQ_Error error)
406 GNUNET_MQ_destroy (mq);
408 LOG (GNUNET_ERROR_TYPE_DEBUG,
409 "MQ error %d, reconnecting\n",
416 * Process pending requests to the resolver.
421 struct GNUNET_RESOLVER_GetMessage *msg;
422 struct GNUNET_MQ_Envelope *env;
423 struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
432 /* nothing to do, release socket really soon if there is nothing
433 * else happening... */
436 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
441 if (GNUNET_NO != rh->was_transmitted)
442 return; /* waiting for reply */
443 env = GNUNET_MQ_msg_extra (msg,
445 GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
446 msg->direction = htonl (rh->direction);
447 msg->af = htonl (rh->af);
448 msg->id = htonl (rh->id);
449 GNUNET_memcpy (&msg[1],
452 LOG (GNUNET_ERROR_TYPE_DEBUG,
453 "Transmitting DNS resolution request (ID %u) to DNS service\n",
457 rh->was_transmitted = GNUNET_YES;
462 * Check validity of response with a hostname for a DNS lookup.
465 * @param msg message with the hostname
468 check_response (void *cls,
469 const struct GNUNET_RESOLVER_ResponseMessage *msg)
474 /* implemented in #handle_response() for now */
480 * Check validity of response with a hostname for a DNS lookup.
481 * NOTE: right now rather messy, might want to use different
482 * message types for different response formats in the future.
485 * @param msg message with the response
488 handle_response (void *cls,
489 const struct GNUNET_RESOLVER_ResponseMessage *msg)
491 struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
494 uint32_t request_id = msg->id;
496 for (; rh != NULL; rh = rh->next)
498 if (rh->id == request_id)
505 /* Resolver service sent extra replies to query (after terminator)? Bad! */
507 GNUNET_MQ_destroy (mq);
512 size = ntohs (msg->header.size);
513 if (size == sizeof (struct GNUNET_RESOLVER_ResponseMessage))
515 LOG (GNUNET_ERROR_TYPE_DEBUG,
516 "Received empty response from DNS service\n");
517 /* message contains not data, just header; end of replies */
518 /* check if request was canceled */
519 if (GNUNET_SYSERR != rh->was_transmitted)
521 /* no reverse lookup was successful, return IP as string */
522 if (NULL != rh->name_callback)
524 if (GNUNET_NO == rh->received_response)
526 nret = no_resolve (rh->af,
529 rh->name_callback (rh->cls, nret);
532 /* finally, make termination call */
533 if (GNUNET_SYSERR != rh->was_transmitted)
534 rh->name_callback (rh->cls,
537 if ( (NULL != rh->addr_callback) &&
538 (GNUNET_SYSERR != rh->was_transmitted) )
539 rh->addr_callback (rh->cls,
543 rh->was_transmitted = GNUNET_NO;
544 GNUNET_RESOLVER_request_cancel (rh);
548 /* return reverse lookup results to caller */
549 if (NULL != rh->name_callback)
551 const char *hostname;
553 hostname = (const char *) &msg[1];
554 if (hostname[size - sizeof (struct GNUNET_RESOLVER_ResponseMessage) - 1] != '\0')
557 if (GNUNET_SYSERR != rh->was_transmitted)
558 rh->name_callback (rh->cls,
560 rh->was_transmitted = GNUNET_NO;
561 GNUNET_RESOLVER_request_cancel (rh);
562 GNUNET_MQ_destroy (mq);
567 LOG (GNUNET_ERROR_TYPE_DEBUG,
568 "Resolver returns `%s' for IP `%s'.\n",
570 GNUNET_a2s ((const void *) &rh[1],
572 if (rh->was_transmitted != GNUNET_SYSERR)
573 rh->name_callback (rh->cls,
575 rh->received_response = GNUNET_YES;
577 /* return lookup results to caller */
578 if (NULL != rh->addr_callback)
580 struct sockaddr_in v4;
581 struct sockaddr_in6 v6;
582 const struct sockaddr *sa;
588 ip_len = size - sizeof (struct GNUNET_RESOLVER_ResponseMessage);
589 if (ip_len == sizeof (struct in_addr))
591 memset (&v4, 0, sizeof (v4));
592 v4.sin_family = AF_INET;
593 v4.sin_addr = *(struct in_addr*) ip;
594 #if HAVE_SOCKADDR_IN_SIN_LEN
595 v4.sin_len = sizeof (v4);
598 sa = (const struct sockaddr *) &v4;
600 else if (ip_len == sizeof (struct in6_addr))
602 memset (&v6, 0, sizeof (v6));
603 v6.sin6_family = AF_INET6;
604 v6.sin6_addr = *(struct in6_addr*) ip;
605 #if HAVE_SOCKADDR_IN_SIN_LEN
606 v6.sin6_len = sizeof (v6);
609 sa = (const struct sockaddr *) &v6;
614 if (GNUNET_SYSERR != rh->was_transmitted)
615 rh->addr_callback (rh->cls,
618 rh->was_transmitted = GNUNET_NO;
619 GNUNET_RESOLVER_request_cancel (rh);
620 GNUNET_MQ_destroy (mq);
625 LOG (GNUNET_ERROR_TYPE_DEBUG,
626 "Received IP from DNS service\n");
627 if (GNUNET_SYSERR != rh->was_transmitted)
628 rh->addr_callback (rh->cls,
636 * We've been asked to lookup the address for a hostname and were
637 * given a valid numeric string. Perform the callbacks for the
640 * @param cls `struct GNUNET_RESOLVER_RequestHandle` for the request
643 numeric_resolution (void *cls)
645 struct GNUNET_RESOLVER_RequestHandle *rh = cls;
646 struct sockaddr_in v4;
647 struct sockaddr_in6 v6;
648 const char *hostname;
651 memset (&v4, 0, sizeof (v4));
652 v4.sin_family = AF_INET;
653 #if HAVE_SOCKADDR_IN_SIN_LEN
654 v4.sin_len = sizeof (v4);
656 memset (&v6, 0, sizeof (v6));
657 v6.sin6_family = AF_INET6;
658 #if HAVE_SOCKADDR_IN_SIN_LEN
659 v6.sin6_len = sizeof (v6);
661 hostname = (const char *) &rh[1];
662 if ( ( (rh->af == AF_UNSPEC) ||
663 (rh->af == AF_INET) ) &&
664 (1 == inet_pton (AF_INET,
668 rh->addr_callback (rh->cls,
669 (const struct sockaddr *) &v4,
671 if ( (rh->af == AF_UNSPEC) &&
672 (GNUNET_SYSERR != rh->was_transmitted) &&
673 (1 == inet_pton (AF_INET6,
677 /* this can happen on some systems IF "hostname" is "localhost" */
678 rh->addr_callback (rh->cls,
679 (const struct sockaddr *) &v6,
682 if (GNUNET_SYSERR != rh->was_transmitted)
683 rh->addr_callback (rh->cls,
689 if ( ( (rh->af == AF_UNSPEC) ||
690 (rh->af == AF_INET6) ) &&
691 (1 == inet_pton (AF_INET6,
695 rh->addr_callback (rh->cls,
696 (const struct sockaddr *) &v6,
698 if (GNUNET_SYSERR != rh->was_transmitted)
699 rh->addr_callback (rh->cls,
705 /* why are we here? this task should not have been scheduled! */
712 * We've been asked to lookup the address for a hostname and were
713 * given a variant of "loopback". Perform the callbacks for the
714 * respective loopback numeric addresses.
716 * @param cls `struct GNUNET_RESOLVER_RequestHandle` for the request
719 loopback_resolution (void *cls)
721 struct GNUNET_RESOLVER_RequestHandle *rh = cls;
722 struct sockaddr_in v4;
723 struct sockaddr_in6 v6;
726 memset (&v4, 0, sizeof (v4));
727 v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
728 v4.sin_family = AF_INET;
729 #if HAVE_SOCKADDR_IN_SIN_LEN
730 v4.sin_len = sizeof (v4);
732 memset (&v6, 0, sizeof (v6));
733 v6.sin6_family = AF_INET6;
734 #if HAVE_SOCKADDR_IN_SIN_LEN
735 v6.sin6_len = sizeof (v6);
737 v6.sin6_addr = in6addr_loopback;
741 rh->addr_callback (rh->cls,
742 (const struct sockaddr *) &v4,
746 rh->addr_callback (rh->cls,
747 (const struct sockaddr *) &v6,
751 rh->addr_callback (rh->cls,
752 (const struct sockaddr *) &v6,
754 rh->addr_callback (rh->cls,
755 (const struct sockaddr *) &v4,
763 if (GNUNET_SYSERR != rh->was_transmitted)
764 rh->addr_callback (rh->cls,
767 LOG (GNUNET_ERROR_TYPE_DEBUG,
768 "Finished resolving hostname `%s'.\n",
769 (const char *) &rh[1]);
775 * Now try to reconnect to the resolver service.
780 reconnect_task (void *cls)
782 struct GNUNET_MQ_MessageHandler handlers[] = {
783 GNUNET_MQ_hd_var_size (response,
784 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE,
785 struct GNUNET_RESOLVER_ResponseMessage,
787 GNUNET_MQ_handler_end ()
792 if (NULL == req_head)
793 return; /* no work pending */
794 LOG (GNUNET_ERROR_TYPE_DEBUG,
795 "Trying to connect to DNS service\n");
796 mq = GNUNET_CLIENT_connect (resolver_cfg,
803 LOG (GNUNET_ERROR_TYPE_DEBUG,
804 "Failed to connect, will try again later\n");
813 * Adjust exponential back-off and reconnect to the service.
818 struct GNUNET_RESOLVER_RequestHandle *rh;
822 GNUNET_assert (NULL == mq);
823 if (NULL != (rh = req_head))
825 switch (rh->was_transmitted)
828 /* nothing more to do */
831 /* disconnected, transmit again! */
832 rh->was_transmitted = GNUNET_NO;
835 /* request was cancelled, remove entirely */
836 GNUNET_CONTAINER_DLL_remove (req_head,
847 LOG (GNUNET_ERROR_TYPE_DEBUG,
848 "Will try to connect to DNS service in %s\n",
849 GNUNET_STRINGS_relative_time_to_string (backoff,
851 GNUNET_assert (NULL != resolver_cfg);
852 r_task = GNUNET_SCHEDULER_add_delayed (backoff,
855 backoff = GNUNET_TIME_STD_BACKOFF (backoff);
860 * A DNS resolution timed out. Notify the application.
862 * @param cls the `struct GNUNET_RESOLVER_RequestHandle *`
865 handle_lookup_timeout (void *cls)
867 struct GNUNET_RESOLVER_RequestHandle *rh = cls;
870 if (GNUNET_NO == rh->direction)
872 LOG (GNUNET_ERROR_TYPE_INFO,
873 _("Timeout trying to resolve hostname `%s'.\n"),
874 (const char *) &rh[1]);
875 if (NULL != rh->addr_callback)
876 rh->addr_callback (rh->cls,
882 #if !defined(GNUNET_CULL_LOGGING)
883 char buf[INET6_ADDRSTRLEN];
885 LOG (GNUNET_ERROR_TYPE_INFO,
886 _("Timeout trying to resolve IP address `%s'.\n"),
888 (const void *) &rh[1],
892 if (GNUNET_NO == rh->received_response)
896 nret = no_resolve (rh->af,
899 if (NULL != rh->name_callback)
900 rh->name_callback (rh->cls, nret);
903 /* finally, make termination call */
904 if (NULL != rh->name_callback)
905 rh->name_callback (rh->cls,
908 rh->was_transmitted = GNUNET_NO;
909 GNUNET_RESOLVER_request_cancel (rh);
915 * Convert a string to one or more IP addresses.
917 * @param hostname the hostname to resolve
918 * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any"
919 * @param callback function to call with addresses
920 * @param callback_cls closure for @a callback
921 * @param timeout how long to try resolving
922 * @return handle that can be used to cancel the request, NULL on error
924 struct GNUNET_RESOLVER_RequestHandle *
925 GNUNET_RESOLVER_ip_get (const char *hostname,
927 struct GNUNET_TIME_Relative timeout,
928 GNUNET_RESOLVER_AddressCallback callback,
931 struct GNUNET_RESOLVER_RequestHandle *rh;
936 slen = strlen (hostname) + 1;
937 if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >=
938 GNUNET_MAX_MESSAGE_SIZE)
943 LOG (GNUNET_ERROR_TYPE_DEBUG,
944 "Trying to resolve hostname `%s'.\n",
946 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen);
948 rh->id = ++last_request_id;
949 rh->addr_callback = callback;
950 rh->cls = callback_cls;
951 GNUNET_memcpy (&rh[1],
955 rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
956 rh->direction = GNUNET_NO;
957 /* first, check if this is a numeric address */
958 if ( ( (1 == inet_pton (AF_INET,
962 (af == AF_UNSPEC) ) ) ||
963 ( (1 == inet_pton (AF_INET6,
966 ( (af == AF_INET6) ||
967 (af == AF_UNSPEC)) ) )
969 rh->task = GNUNET_SCHEDULER_add_now (&numeric_resolution,
973 /* then, check if this is a loopback address */
974 for (unsigned int i = 0;
977 if (0 == strcasecmp (loopback[i],
980 rh->task = GNUNET_SCHEDULER_add_now (&loopback_resolution,
984 if (GNUNET_OK != check_config ())
989 rh->task = GNUNET_SCHEDULER_add_delayed (timeout,
990 &handle_lookup_timeout,
992 GNUNET_CONTAINER_DLL_insert_tail (req_head,
995 rh->was_queued = GNUNET_YES;
998 GNUNET_SCHEDULER_cancel (s_task);
1001 process_requests ();
1007 * We've been asked to convert an address to a string without
1008 * a reverse lookup, either because the client asked for it
1009 * or because the DNS lookup hit a timeout. Do the numeric
1010 * conversion and invoke the callback.
1012 * @param cls `struct GNUNET_RESOLVER_RequestHandle` for the request
1015 numeric_reverse (void *cls)
1017 struct GNUNET_RESOLVER_RequestHandle *rh = cls;
1021 result = no_resolve (rh->af,
1024 LOG (GNUNET_ERROR_TYPE_DEBUG,
1025 "Resolver returns `%s'.\n",
1029 rh->name_callback (rh->cls,
1031 GNUNET_free (result);
1033 rh->name_callback (rh->cls,
1035 if (NULL != rh->task)
1037 GNUNET_SCHEDULER_cancel (rh->task);
1045 * Get an IP address as a string.
1047 * @param sa host address
1048 * @param salen length of host address in @a sa
1049 * @param do_resolve use #GNUNET_NO to return numeric hostname
1050 * @param timeout how long to try resolving
1051 * @param callback function to call with hostnames
1052 * last callback is NULL when finished
1053 * @param cls closure for @a callback
1054 * @return handle that can be used to cancel the request
1056 struct GNUNET_RESOLVER_RequestHandle *
1057 GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa,
1060 struct GNUNET_TIME_Relative timeout,
1061 GNUNET_RESOLVER_HostnameCallback callback,
1064 struct GNUNET_RESOLVER_RequestHandle *rh;
1068 if (GNUNET_OK != check_config ())
1070 LOG (GNUNET_ERROR_TYPE_ERROR,
1071 _("Resolver not configured correctly.\n"));
1075 switch (sa->sa_family)
1078 GNUNET_assert (salen == sizeof (struct sockaddr_in));
1079 ip_len = sizeof (struct in_addr);
1080 ip = &((const struct sockaddr_in*)sa)->sin_addr;
1083 GNUNET_assert (salen == sizeof (struct sockaddr_in6));
1084 ip_len = sizeof (struct in6_addr);
1085 ip = &((const struct sockaddr_in6*)sa)->sin6_addr;
1091 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + salen);
1092 rh->name_callback = callback;
1094 rh->af = sa->sa_family;
1095 rh->id = ++last_request_id;
1096 rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1097 GNUNET_memcpy (&rh[1],
1100 rh->data_len = ip_len;
1101 rh->direction = GNUNET_YES;
1102 rh->received_response = GNUNET_NO;
1103 if (GNUNET_NO == do_resolve)
1105 rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse,
1109 rh->task = GNUNET_SCHEDULER_add_delayed (timeout,
1110 &handle_lookup_timeout,
1112 GNUNET_CONTAINER_DLL_insert_tail (req_head,
1115 rh->was_queued = GNUNET_YES;
1118 GNUNET_SCHEDULER_cancel (s_task);
1121 process_requests ();
1127 * Get local fully qualified af name
1132 GNUNET_RESOLVER_local_fqdn_get ()
1134 char hostname[GNUNET_OS_get_hostname_max_length () + 1];
1136 if (0 != gethostname (hostname,
1137 sizeof (hostname) - 1))
1139 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1143 LOG (GNUNET_ERROR_TYPE_DEBUG,
1144 "Resolving our FQDN `%s'\n",
1146 #if HAVE_GETADDRINFO
1148 struct addrinfo *ai;
1152 if (0 != (ret = getaddrinfo (hostname,
1157 LOG (GNUNET_ERROR_TYPE_ERROR,
1158 _("Could not resolve our FQDN: %s\n"),
1159 gai_strerror (ret));
1162 if (NULL != ai->ai_canonname)
1163 rval = GNUNET_strdup (ai->ai_canonname);
1165 rval = GNUNET_strdup (hostname);
1169 #elif HAVE_GETHOSTBYNAME2
1171 struct hostent *host;
1173 host = gethostbyname2 (hostname,
1176 host = gethostbyname2 (hostname,
1180 LOG (GNUNET_ERROR_TYPE_ERROR,
1181 _("Could not resolve our FQDN: %s\n"),
1182 hstrerror (h_errno));
1185 return GNUNET_strdup (host->h_name);
1187 #elif HAVE_GETHOSTBYNAME
1189 struct hostent *host;
1191 host = gethostbyname (hostname);
1194 LOG (GNUNET_ERROR_TYPE_ERROR,
1195 _("Could not resolve our FQDN: %s\n"),
1196 hstrerror (h_errno));
1199 return GNUNET_strdup (host->h_name);
1202 /* fallback: just hope name is already FQDN */
1203 return GNUNET_strdup (hostname);
1209 * Looking our own hostname.
1211 * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any"
1212 * @param timeout how long to try resolving
1213 * @param callback function to call with addresses
1214 * @param cls closure for @a callback
1215 * @return handle that can be used to cancel the request, NULL on error
1217 struct GNUNET_RESOLVER_RequestHandle *
1218 GNUNET_RESOLVER_hostname_resolve (int af,
1219 struct GNUNET_TIME_Relative timeout,
1220 GNUNET_RESOLVER_AddressCallback callback,
1223 char hostname[GNUNET_OS_get_hostname_max_length () + 1];
1225 if (0 != gethostname (hostname, sizeof (hostname) - 1))
1227 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1231 LOG (GNUNET_ERROR_TYPE_DEBUG,
1232 "Resolving our hostname `%s'\n",
1234 return GNUNET_RESOLVER_ip_get (hostname,
1243 * Cancel a request that is still pending with the resolver.
1244 * Note that a client MUST NOT cancel a request that has
1245 * been completed (i.e, the callback has been called to
1246 * signal timeout or the final result).
1248 * @param rh handle of request to cancel
1251 GNUNET_RESOLVER_request_cancel (struct GNUNET_RESOLVER_RequestHandle *rh)
1253 if (GNUNET_NO == rh->direction)
1254 LOG (GNUNET_ERROR_TYPE_DEBUG,
1255 "Asked to cancel request to resolve hostname `%s'.\n",
1256 (const char *) &rh[1]);
1257 if (NULL != rh->task)
1259 GNUNET_SCHEDULER_cancel (rh->task);
1262 if (GNUNET_NO == rh->was_transmitted)
1264 if (GNUNET_YES == rh->was_queued)
1265 GNUNET_CONTAINER_DLL_remove (req_head,
1269 check_disconnect ();
1272 GNUNET_assert (GNUNET_YES == rh->was_transmitted);
1273 rh->was_transmitted = GNUNET_SYSERR; /* mark as cancelled */
1274 check_disconnect ();
1278 /* end of resolver_api.c */