GNUnet debian-0.24.3-29-g453fda2cf
 
Loading...
Searching...
No Matches
resolver_api.c File Reference

resolver for writing a tool More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_resolver_service.h"
#include "resolver.h"
Include dependency graph for resolver_api.c:

Go to the source code of this file.

Data Structures

struct  GNUNET_RESOLVER_RequestHandle
 Handle to a request given to the resolver. More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "util-resolver-api", __VA_ARGS__)
 
#define LOG_STRERROR(kind, syscall)
 
#define MAX_HOSTNAME   1024
 Maximum supported length for a hostname.
 

Functions

static int check_config ()
 Check that the resolver service runs on localhost (or equivalent).
 
void GNUNET_RESOLVER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
 Create the connection to the resolver service.
 
void GNUNET_RESOLVER_disconnect ()
 Destroy the connection to the resolver service.
 
static void shutdown_task (void *cls)
 Task executed on system shutdown.
 
static void check_disconnect ()
 Consider disconnecting if we have no further requests pending.
 
static char * no_resolve (int af, const void *ip, socklen_t ip_len)
 Convert IP address to string without DNS resolution.
 
static void reconnect (void)
 Adjust exponential back-off and reconnect to the service.
 
static void mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
 Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue.
 
static void process_requests ()
 Process pending requests to the resolver.
 
static int check_response (void *cls, const struct GNUNET_RESOLVER_ResponseMessage *msg)
 Check validity of response with a hostname for a DNS lookup.
 
static void handle_response (void *cls, const struct GNUNET_RESOLVER_ResponseMessage *msg)
 Check validity of response with a hostname for a DNS lookup.
 
static void numeric_resolution (void *cls)
 We've been asked to lookup the address for a hostname and were given a valid numeric string.
 
static void loopback_resolution (void *cls)
 We've been asked to lookup the address for a hostname and were given a variant of "loopback".
 
static void reconnect_task (void *cls)
 Now try to reconnect to the resolver service.
 
static void handle_lookup_timeout (void *cls)
 A DNS resolution timed out.
 
struct GNUNET_RESOLVER_RequestHandleGNUNET_RESOLVER_ip_get (const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
 Convert a string to one or more IP addresses.
 
static void numeric_reverse (void *cls)
 We've been asked to convert an address to a string without a reverse lookup, either because the client asked for it or because the DNS lookup hit a timeout.
 
struct GNUNET_RESOLVER_RequestHandleGNUNET_RESOLVER_hostname_get (const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls)
 Get an IP address as a string.
 
char * GNUNET_RESOLVER_local_fqdn_get ()
 Get local fully qualified af name.
 
struct GNUNET_RESOLVER_RequestHandleGNUNET_RESOLVER_hostname_resolve (int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *cls)
 Looking our own hostname.
 
void GNUNET_RESOLVER_request_cancel (struct GNUNET_RESOLVER_RequestHandle *rh)
 Cancel a request that is still pending with the resolver.
 

Variables

static const char * loopback []
 Possible hostnames for "loopback".
 
static const struct GNUNET_CONFIGURATION_Handleresolver_cfg
 Configuration.
 
static struct GNUNET_MQ_Handlemq
 Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
 
static struct GNUNET_RESOLVER_RequestHandlereq_head
 Head of DLL of requests.
 
static struct GNUNET_RESOLVER_RequestHandlereq_tail
 Tail of DLL of requests.
 
static uint32_t last_request_id
 ID of the last request we sent to the service.
 
static struct GNUNET_TIME_Relative backoff
 How long should we wait to reconnect?
 
static struct GNUNET_SCHEDULER_Taskr_task
 Task for reconnecting.
 
static struct GNUNET_SCHEDULER_Tasks_task
 Task ID of shutdown task; only present while we have a connection to the resolver service.
 

Detailed Description

resolver for writing a tool

Author
Christian Grothoff

Definition in file resolver_api.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util-resolver-api", __VA_ARGS__)

Definition at line 33 of file resolver_api.c.

◆ LOG_STRERROR

#define LOG_STRERROR (   kind,
  syscall 
)
Value:
"util-resolver-api", \
syscall)
#define GNUNET_log_from_strerror(level, component, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...

Definition at line 35 of file resolver_api.c.

47 {
48 "localhost",
49 "ip6-localnet",
50 NULL
51};
52
53
57static const struct GNUNET_CONFIGURATION_Handle *resolver_cfg;
58
63static struct GNUNET_MQ_Handle *mq;
64
69
74
78static uint32_t last_request_id;
79
83static struct GNUNET_TIME_Relative backoff;
84
88static struct GNUNET_SCHEDULER_Task *r_task;
89
94static struct GNUNET_SCHEDULER_Task *s_task;
95
96
103{
108
113
119
125
129 void *cls;
130
135
141
145 int af;
146
150 uint32_t id;
151
158 int was_transmitted;
159
163 int was_queued;
164
168 int direction;
169
174
178 size_t data_len;
179};
180
181
189static int
191{
192 char *hostname;
193 struct sockaddr_in v4;
194 struct sockaddr_in6 v6;
195
196 if (GNUNET_OK ==
198 "resolver",
199 "UNIXPATH"))
200 return GNUNET_OK;
201 memset (&v4, 0, sizeof(v4));
202 v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
203 v4.sin_family = AF_INET;
204#if HAVE_SOCKADDR_IN_SIN_LEN
205 v4.sin_len = sizeof(v4);
206#endif
207 memset (&v6, 0, sizeof(v6));
208 v6.sin6_family = AF_INET6;
209#if HAVE_SOCKADDR_IN_SIN_LEN
210 v6.sin6_len = sizeof(v6);
211#endif
212 if (GNUNET_OK !=
214 "resolver",
215 "HOSTNAME",
216 &hostname))
217 {
219 _ (
220 "Missing `%s' for `%s' in configuration, DNS resolution will be unavailable.\n"),
221 "HOSTNAME",
222 "resolver");
223 return GNUNET_SYSERR;
224 }
225 if ((1 == inet_pton (AF_INET, hostname, &v4)) ||
226 (1 == inet_pton (AF_INET6, hostname, &v6)))
227 {
228 GNUNET_free (hostname);
229 return GNUNET_OK;
230 }
231 for (unsigned int i = 0;
232 NULL != loopback[i];
233 i++)
234 if (0 == strcasecmp (loopback[i],
235 hostname))
236 {
237 GNUNET_free (hostname);
238 return GNUNET_OK;
239 }
241 _ (
242 "Missing `%s' or numeric IP address for `%s' of `%s' in configuration, DNS resolution will be unavailable.\n"),
243 "localhost",
244 "HOSTNAME",
245 "resolver");
246 GNUNET_free (hostname);
247 return GNUNET_SYSERR;
248}
249
250
256void
258{
259 GNUNET_assert (NULL != cfg);
262}
263
264
268void
270{
272
273 while (NULL != (rh = req_head))
274 {
277 req_tail,
278 rh);
279 GNUNET_free (rh);
280 }
281 if (NULL != mq)
282 {
284 "Disconnecting from DNS service\n");
286 mq = NULL;
287 }
288 if (NULL != r_task)
289 {
291 r_task = NULL;
292 }
293 if (NULL != s_task)
294 {
296 s_task = NULL;
297 }
298}
299
300
304static void
305shutdown_task (void *cls)
306{
307 (void) cls;
308 s_task = NULL;
311}
312
313
317static void
319{
320 for (struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
321 NULL != rh;
322 rh = rh->next)
324 return;
325 if (NULL != r_task)
326 {
328 r_task = NULL;
329 }
330 if (NULL != s_task)
331 return;
334 NULL);
335}
336
337
346static char *
347no_resolve (int af,
348 const void *ip,
349 socklen_t ip_len)
350{
351 char buf[INET6_ADDRSTRLEN];
352
353 switch (af)
354 {
355 case AF_INET:
356 if (ip_len != sizeof(struct in_addr))
357 return NULL;
358 if (NULL ==
359 inet_ntop (AF_INET,
360 ip,
361 buf,
362 sizeof(buf)))
363 {
365 "inet_ntop");
366 return NULL;
367 }
368 break;
369
370 case AF_INET6:
371 if (ip_len != sizeof(struct in6_addr))
372 return NULL;
373 if (NULL ==
374 inet_ntop (AF_INET6,
375 ip,
376 buf,
377 sizeof(buf)))
378 {
380 "inet_ntop");
381 return NULL;
382 }
383 break;
384
385 default:
386 GNUNET_break (0);
387 return NULL;
388 }
389 return GNUNET_strdup (buf);
390}
391
392
396static void
397reconnect (void);
398
399
408static void
409mq_error_handler (void *cls,
410 enum GNUNET_MQ_Error error)
411{
412 (void) cls;
414 mq = NULL;
416 "MQ error %d, reconnecting\n",
417 error);
418 reconnect ();
419}
420
421
425static void
427{
429 struct GNUNET_MQ_Envelope *env;
431
432 if (NULL == mq)
433 {
434 reconnect ();
435 return;
436 }
437 if (NULL == rh)
438 {
439 /* nothing to do, release socket really soon if there is nothing
440 * else happening... */
441 if (NULL == s_task)
442 s_task =
445 NULL);
446 return;
447 }
448 if (GNUNET_NO != rh->was_transmitted)
449 return; /* waiting for reply */
451 rh->data_len,
453 msg->direction = htonl (rh->direction);
454 msg->af = htonl (rh->af);
455 msg->client_id = rh->id;
456 GNUNET_memcpy (&msg[1],
457 &rh[1],
458 rh->data_len);
460 "Transmitting DNS resolution request (ID %u) to DNS service\n",
461 rh->id);
463 env);
465}
466
467
474static int
475check_response (void *cls,
477{
478 (void) cls;
479 (void) msg;
480
481 /* implemented in #handle_response() for now */
482 return GNUNET_OK;
483}
484
485
494static void
495handle_response (void *cls,
497{
499 uint16_t size;
500 char *nret;
501 uint32_t client_request_id = msg->client_id;
502
503 for (; rh != NULL; rh = rh->next)
504 {
505 if (rh->id == client_request_id)
506 break;
507 }
508
509 (void) cls;
510 if (NULL == rh)
511 {
512 /* Resolver service sent extra replies to query (after terminator)? Bad! */
513 GNUNET_break (0);
515 mq = NULL;
516 reconnect ();
517 return;
518 }
519 size = ntohs (msg->header.size);
520 if (size == sizeof(struct GNUNET_RESOLVER_ResponseMessage))
521 {
523 "Received empty response from DNS service\n");
524 /* message contains not data, just header; end of replies */
525 /* check if request was canceled */
527 {
528 /* no reverse lookup was successful, return IP as string */
529 if (NULL != rh->name_callback)
530 {
531 if (GNUNET_NO == rh->received_response)
532 {
533 nret = no_resolve (rh->af,
534 &rh[1],
535 rh->data_len);
536 rh->name_callback (rh->cls, nret);
537 GNUNET_free (nret);
538 }
539 /* finally, make termination call */
541 rh->name_callback (rh->cls,
542 NULL);
543 }
544 if ((NULL != rh->addr_callback) &&
546 rh->addr_callback (rh->cls,
547 NULL,
548 0);
549 }
553 return;
554 }
555 /* return reverse lookup results to caller */
556 if (NULL != rh->name_callback)
557 {
558 const char *hostname;
559
560 hostname = (const char *) &msg[1];
561 if (hostname[size - sizeof(struct GNUNET_RESOLVER_ResponseMessage) - 1] !=
562 '\0')
563 {
564 GNUNET_break (0);
566 rh->name_callback (rh->cls,
567 NULL);
571 mq = NULL;
572 reconnect ();
573 return;
574 }
576 "Resolver returns `%s' for IP `%s'.\n",
577 hostname,
578 GNUNET_a2s ((const void *) &rh[1],
579 rh->data_len));
581 rh->name_callback (rh->cls,
582 hostname);
584 }
585 /* return lookup results to caller */
586 if (NULL != rh->addr_callback)
587 {
588 struct sockaddr_in v4;
589 struct sockaddr_in6 v6;
590 const struct sockaddr *sa;
591 socklen_t salen;
592 const void *ip;
593 size_t ip_len;
594
595 ip = &msg[1];
596 ip_len = size - sizeof(struct GNUNET_RESOLVER_ResponseMessage);
597 if (ip_len == sizeof(struct in_addr))
598 {
599 memset (&v4, 0, sizeof(v4));
600 v4.sin_family = AF_INET;
601 v4.sin_addr = *(struct in_addr*) ip;
602#if HAVE_SOCKADDR_IN_SIN_LEN
603 v4.sin_len = sizeof(v4);
604#endif
605 salen = sizeof(v4);
606 sa = (const struct sockaddr *) &v4;
607 }
608 else if (ip_len == sizeof(struct in6_addr))
609 {
610 memset (&v6, 0, sizeof(v6));
611 v6.sin6_family = AF_INET6;
612 v6.sin6_addr = *(struct in6_addr*) ip;
613#if HAVE_SOCKADDR_IN_SIN_LEN
614 v6.sin6_len = sizeof(v6);
615#endif
616 salen = sizeof(v6);
617 sa = (const struct sockaddr *) &v6;
618 }
619 else
620 {
621 GNUNET_break (0);
623 rh->addr_callback (rh->cls,
624 NULL,
625 0);
629 mq = NULL;
630 reconnect ();
631 return;
632 }
634 "Received IP from DNS service\n");
636 rh->addr_callback (rh->cls,
637 sa,
638 salen);
639 }
640}
641
642
650static void
651numeric_resolution (void *cls)
652{
654 struct sockaddr_in v4;
655 struct sockaddr_in6 v6;
656 const char *hostname;
657
658 rh->task = NULL;
659 memset (&v4, 0, sizeof(v4));
660 v4.sin_family = AF_INET;
661#if HAVE_SOCKADDR_IN_SIN_LEN
662 v4.sin_len = sizeof(v4);
663#endif
664 memset (&v6, 0, sizeof(v6));
665 v6.sin6_family = AF_INET6;
666#if HAVE_SOCKADDR_IN_SIN_LEN
667 v6.sin6_len = sizeof(v6);
668#endif
669 hostname = (const char *) &rh[1];
670 if (((rh->af == AF_UNSPEC) ||
671 (rh->af == AF_INET)) &&
672 (1 == inet_pton (AF_INET,
673 hostname,
674 &v4.sin_addr)))
675 {
676 rh->addr_callback (rh->cls,
677 (const struct sockaddr *) &v4,
678 sizeof(v4));
679 if ((rh->af == AF_UNSPEC) &&
681 (1 == inet_pton (AF_INET6,
682 hostname,
683 &v6.sin6_addr)))
684 {
685 /* this can happen on some systems IF "hostname" is "localhost" */
686 rh->addr_callback (rh->cls,
687 (const struct sockaddr *) &v6,
688 sizeof(v6));
689 }
691 rh->addr_callback (rh->cls,
692 NULL,
693 0);
694 GNUNET_free (rh);
695 return;
696 }
697 if (((rh->af == AF_UNSPEC) ||
698 (rh->af == AF_INET6)) &&
699 (1 == inet_pton (AF_INET6,
700 hostname,
701 &v6.sin6_addr)))
702 {
703 rh->addr_callback (rh->cls,
704 (const struct sockaddr *) &v6,
705 sizeof(v6));
707 rh->addr_callback (rh->cls,
708 NULL,
709 0);
710 GNUNET_free (rh);
711 return;
712 }
713 /* why are we here? this task should not have been scheduled! */
714 GNUNET_assert (0);
715 GNUNET_free (rh);
716}
717
718
726static void
727loopback_resolution (void *cls)
728{
730 struct sockaddr_in v4;
731 struct sockaddr_in6 v6;
732
733 rh->task = NULL;
734 memset (&v4, 0, sizeof(v4));
735 v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
736 v4.sin_family = AF_INET;
737#if HAVE_SOCKADDR_IN_SIN_LEN
738 v4.sin_len = sizeof(v4);
739#endif
740 memset (&v6, 0, sizeof(v6));
741 v6.sin6_family = AF_INET6;
742#if HAVE_SOCKADDR_IN_SIN_LEN
743 v6.sin6_len = sizeof(v6);
744#endif
745 v6.sin6_addr = in6addr_loopback;
746 switch (rh->af)
747 {
748 case AF_INET:
749 rh->addr_callback (rh->cls,
750 (const struct sockaddr *) &v4,
751 sizeof(v4));
752 break;
753
754 case AF_INET6:
755 rh->addr_callback (rh->cls,
756 (const struct sockaddr *) &v6,
757 sizeof(v6));
758 break;
759
760 case AF_UNSPEC:
761 rh->addr_callback (rh->cls,
762 (const struct sockaddr *) &v6,
763 sizeof(v6));
764 rh->addr_callback (rh->cls,
765 (const struct sockaddr *) &v4,
766 sizeof(v4));
767
768 break;
769
770 default:
771 GNUNET_break (0);
772 break;
773 }
775 rh->addr_callback (rh->cls,
776 NULL,
777 0);
779 "Finished resolving hostname `%s'.\n",
780 (const char *) &rh[1]);
781 GNUNET_free (rh);
782}
783
784
790static void
791reconnect_task (void *cls)
792{
797 NULL),
799 };
800
801 (void) cls;
802 r_task = NULL;
803 if (NULL == req_head)
804 return; /* no work pending */
806 "Trying to connect to DNS service\n");
808 "resolver",
809 handlers,
811 NULL);
812 if (NULL == mq)
813 {
815 "Failed to connect, will try again later\n");
816 reconnect ();
817 return;
818 }
820}
821
822
826static void
827reconnect ()
828{
830
831 if (NULL != r_task)
832 return;
833 GNUNET_assert (NULL == mq);
834 if (NULL != (rh = req_head))
835 {
836 switch (rh->was_transmitted)
837 {
838 case GNUNET_NO:
839 /* nothing more to do */
840 break;
841
842 case GNUNET_YES:
843 /* disconnected, transmit again! */
845 break;
846
847 case GNUNET_SYSERR:
848 /* request was cancelled, remove entirely */
850 req_tail,
851 rh);
852 GNUNET_free (rh);
854 break;
855
856 default:
857 GNUNET_assert (0);
858 break;
859 }
860 }
862 "Will try to connect to DNS service in %s\n",
864 GNUNET_YES));
865 GNUNET_assert (NULL != resolver_cfg);
868 NULL);
870}
871
872
878static void
880{
882
883 rh->task = NULL;
884 if (GNUNET_NO == rh->direction)
885 {
887 _ ("Timeout trying to resolve hostname `%s'.\n"),
888 (const char *) &rh[1]);
889 if (NULL != rh->addr_callback)
890 rh->addr_callback (rh->cls,
891 NULL,
892 0);
893 }
894 else
895 {
896#if ! defined(GNUNET_CULL_LOGGING)
897 char buf[INET6_ADDRSTRLEN];
898
900 _ ("Timeout trying to resolve IP address `%s'.\n"),
901 inet_ntop (rh->af,
902 (const void *) &rh[1],
903 buf,
904 sizeof(buf)));
905#endif
906 if (GNUNET_NO == rh->received_response)
907 {
908 char *nret;
909
910 nret = no_resolve (rh->af,
911 &rh[1],
912 rh->data_len);
913 if (NULL != rh->name_callback)
914 rh->name_callback (rh->cls, nret);
915 GNUNET_free (nret);
916 }
917 /* finally, make termination call */
918 if (NULL != rh->name_callback)
919 rh->name_callback (rh->cls,
920 NULL);
921 }
925}
926
927
939GNUNET_RESOLVER_ip_get (const char *hostname,
940 int af,
943 void *callback_cls)
944{
946 size_t slen;
947 struct in_addr v4;
948 struct in6_addr v6;
949
950 slen = strlen (hostname) + 1;
951 if (slen + sizeof(struct GNUNET_RESOLVER_GetMessage) >=
953 {
954 GNUNET_break (0);
955 return NULL;
956 }
958 "Trying to resolve hostname `%s'.\n",
959 hostname);
960 rh = GNUNET_malloc (sizeof(struct GNUNET_RESOLVER_RequestHandle) + slen);
961 rh->af = af;
962 rh->id = ++last_request_id;
963 rh->addr_callback = callback;
964 rh->cls = callback_cls;
965 GNUNET_memcpy (&rh[1],
966 hostname,
967 slen);
968 rh->data_len = slen;
970 rh->direction = GNUNET_NO;
971 /* first, check if this is a numeric address */
972 if (((1 == inet_pton (AF_INET,
973 hostname,
974 &v4)) &&
975 ((af == AF_INET) ||
976 (af == AF_UNSPEC))) ||
977 ((1 == inet_pton (AF_INET6,
978 hostname,
979 &v6)) &&
980 ((af == AF_INET6) ||
981 (af == AF_UNSPEC))))
982 {
984 rh);
985 return rh;
986 }
987 /* then, check if this is a loopback address */
988 for (unsigned int i = 0;
989 NULL != loopback[i];
990 i++)
991 if (0 == strcasecmp (loopback[i],
992 hostname))
993 {
995 rh);
996 return rh;
997 }
998 if (GNUNET_OK != check_config ())
999 {
1000 GNUNET_free (rh);
1001 return NULL;
1002 }
1005 rh);
1007 req_tail,
1008 rh);
1009 rh->was_queued = GNUNET_YES;
1010 if (NULL != s_task)
1011 {
1013 s_task = NULL;
1014 }
1016 return rh;
1017}
1018
1019
1028static void
1029numeric_reverse (void *cls)
1030{
1032 char *result;
1033
1034 rh->task = NULL;
1035 result = no_resolve (rh->af,
1036 &rh[1],
1037 rh->data_len);
1039 "Resolver returns `%s'.\n",
1040 result);
1041 if (NULL != result)
1042 {
1043 rh->name_callback (rh->cls,
1044 result);
1046 }
1047 rh->name_callback (rh->cls,
1048 NULL);
1049 if (NULL != rh->task)
1050 {
1052 rh->task = NULL;
1053 }
1054 GNUNET_free (rh);
1055}
1056
1057
1071GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa,
1072 socklen_t salen,
1073 int do_resolve,
1076 void *cls)
1077{
1079 size_t ip_len;
1080 const void *ip;
1081
1082 if (GNUNET_OK != check_config ())
1083 {
1085 _ ("Resolver not configured correctly.\n"));
1086 return NULL;
1087 }
1088
1089 switch (sa->sa_family)
1090 {
1091 case AF_INET:
1092 GNUNET_assert (salen == sizeof(struct sockaddr_in));
1093 ip_len = sizeof(struct in_addr);
1094 ip = &((const struct sockaddr_in*) sa)->sin_addr;
1095 break;
1096
1097 case AF_INET6:
1098 GNUNET_assert (salen == sizeof(struct sockaddr_in6));
1099 ip_len = sizeof(struct in6_addr);
1100 ip = &((const struct sockaddr_in6*) sa)->sin6_addr;
1101 break;
1102
1103 default:
1104 GNUNET_break (0);
1105 return NULL;
1106 }
1107 rh = GNUNET_malloc (sizeof(struct GNUNET_RESOLVER_RequestHandle) + salen);
1108 rh->name_callback = callback;
1109 rh->cls = cls;
1110 rh->af = sa->sa_family;
1111 rh->id = ++last_request_id;
1113 GNUNET_memcpy (&rh[1],
1114 ip,
1115 ip_len);
1116 rh->data_len = ip_len;
1117 rh->direction = GNUNET_YES;
1119 if (GNUNET_NO == do_resolve)
1120 {
1122 rh);
1123 return rh;
1124 }
1127 rh);
1129 req_tail,
1130 rh);
1131 rh->was_queued = GNUNET_YES;
1132 if (NULL != s_task)
1133 {
1135 s_task = NULL;
1136 }
1138 return rh;
1139}
1140
1141
1147char *
1149{
1150 char hostname[GNUNET_OS_get_hostname_max_length () + 1];
1151
1152 if (0 != gethostname (hostname,
1153 sizeof(hostname) - 1))
1154 {
1156 "gethostname");
1157 return NULL;
1158 }
1160 "Resolving our FQDN `%s'\n",
1161 hostname);
1162#if HAVE_GETADDRINFO
1163 {
1164 struct addrinfo *ai;
1165 int ret;
1166 char *rval;
1167
1168 if (0 != (ret = getaddrinfo (hostname,
1169 NULL,
1170 NULL,
1171 &ai)))
1172 {
1174 _ ("Could not resolve our FQDN: %s\n"),
1175 gai_strerror (ret));
1176 return NULL;
1177 }
1178 if (NULL != ai->ai_canonname)
1179 rval = GNUNET_strdup (ai->ai_canonname);
1180 else
1181 rval = GNUNET_strdup (hostname);
1182 freeaddrinfo (ai);
1183 return rval;
1184 }
1185#elif HAVE_GETHOSTBYNAME2
1186 {
1187 struct hostent *host;
1188
1189 host = gethostbyname2 (hostname,
1190 AF_INET);
1191 if (NULL == host)
1192 host = gethostbyname2 (hostname,
1193 AF_INET6);
1194 if (NULL == host)
1195 {
1197 _ ("Could not resolve our FQDN: %s\n"),
1198 hstrerror (h_errno));
1199 return NULL;
1200 }
1201 return GNUNET_strdup (host->h_name);
1202 }
1203#elif HAVE_GETHOSTBYNAME
1204 {
1205 struct hostent *host;
1206
1207 host = gethostbyname (hostname);
1208 if (NULL == host)
1209 {
1211 _ ("Could not resolve our FQDN: %s\n"),
1212 hstrerror (h_errno));
1213 return NULL;
1214 }
1215 return GNUNET_strdup (host->h_name);
1216 }
1217#else
1218 /* fallback: just hope name is already FQDN */
1219 return GNUNET_strdup (hostname);
1220#endif
1221}
1222
1223
1237 void *cls)
1238{
1239 char hostname[GNUNET_OS_get_hostname_max_length () + 1];
1240
1241 if (0 != gethostname (hostname, sizeof(hostname) - 1))
1242 {
1244 "gethostname");
1245 return NULL;
1246 }
1248 "Resolving our hostname `%s'\n",
1249 hostname);
1250 return GNUNET_RESOLVER_ip_get (hostname,
1251 af,
1252 timeout,
1253 callback,
1254 cls);
1255}
1256
1257
1266void
1268{
1269 if (GNUNET_NO == rh->direction)
1271 "Asked to cancel request to resolve hostname `%s'.\n",
1272 (const char *) &rh[1]);
1273 if (NULL != rh->task)
1274 {
1276 rh->task = NULL;
1277 }
1278 if (GNUNET_NO == rh->was_transmitted)
1279 {
1280 if (GNUNET_YES == rh->was_queued)
1282 req_tail,
1283 rh);
1284 GNUNET_free (rh);
1286 return;
1287 }
1289 rh->was_transmitted = GNUNET_SYSERR; /* mark as cancelled */
1291}
1292
1293
1294/* end of resolver_api.c */
struct GNUNET_MQ_MessageHandlers handlers[]
Definition 003.c:1
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static int ret
Final status code.
Definition gnunet-arm.c:93
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition gnunet-arm.c:108
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition gnunet-arm.c:118
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
static struct MHD_Response * response
Our canonical response.
struct GNUNET_SCHEDULER_Task * shutdown_task
static int result
Global testing status.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition client.c:1060
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
void * cls
Closure for mv and cb.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
GNUNET_MQ_Error
Error codes for the queue.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition mq.c:700
#define GNUNET_OS_get_hostname_max_length()
Get maximum string length returned by gethostname()
#define GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST
Request DNS resolution.
#define GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE
Response to a DNS resolution request.
char * GNUNET_RESOLVER_local_fqdn_get()
Get local fully qualified af name.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get(const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
Convert a string to one or more IP addresses.
void GNUNET_RESOLVER_disconnect()
Destroy the connection to the resolver service.
void GNUNET_RESOLVER_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create the connection to the resolver service.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_resolve(int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *cls)
Looking our own hostname.
void(* GNUNET_RESOLVER_AddressCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Function called by the resolver for each address obtained from DNS.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_get(const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls)
Get an IP address as a string.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
void(* GNUNET_RESOLVER_HostnameCallback)(void *cls, const char *hostname)
Function called by the resolver for each hostname obtained from DNS.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1304
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1277
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:599
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static void reconnect(void)
Adjust exponential back-off and reconnect to the service.
static void numeric_resolution(void *cls)
We've been asked to lookup the address for a hostname and were given a valid numeric string.
static struct GNUNET_RESOLVER_RequestHandle * req_tail
Tail of DLL of requests.
static char * no_resolve(int af, const void *ip, socklen_t ip_len)
Convert IP address to string without DNS resolution.
static void check_disconnect()
Consider disconnecting if we have no further requests pending.
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static int check_config()
Check that the resolver service runs on localhost (or equivalent).
static const char * loopback[]
Possible hostnames for "loopback".
static void loopback_resolution(void *cls)
We've been asked to lookup the address for a hostname and were given a variant of "loopback".
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
static struct GNUNET_SCHEDULER_Task * s_task
Task ID of shutdown task; only present while we have a connection to the resolver service.
static uint32_t last_request_id
ID of the last request we sent to the service.
static struct GNUNET_TIME_Relative backoff
How long should we wait to reconnect?
static void handle_response(void *cls, const struct GNUNET_RESOLVER_ResponseMessage *msg)
Check validity of response with a hostname for a DNS lookup.
static void numeric_reverse(void *cls)
We've been asked to convert an address to a string without a reverse lookup, either because the clien...
static void process_requests()
Process pending requests to the resolver.
static const struct GNUNET_CONFIGURATION_Handle * resolver_cfg
Configuration.
static struct GNUNET_RESOLVER_RequestHandle * req_head
Head of DLL of requests.
static struct GNUNET_SCHEDULER_Task * r_task
Task for reconnecting.
static void handle_lookup_timeout(void *cls)
A DNS resolution timed out.
static int check_response(void *cls, const struct GNUNET_RESOLVER_ResponseMessage *msg)
Check validity of response with a hostname for a DNS lookup.
#define LOG(kind,...)
#define LOG_STRERROR(kind, syscall)
static void reconnect_task(void *cls)
Now try to reconnect to the resolver service.
Handle to a message queue.
Definition mq.c:87
Message handler for a specific message type.
Request for the resolver.
Definition resolver.h:44
Handle to a request given to the resolver.
struct GNUNET_SCHEDULER_Task * task
Task handle for making reply callbacks in numeric lookups asynchronous, and for timeout handling.
GNUNET_RESOLVER_HostnameCallback name_callback
Callback if this is a reverse lookup request, otherwise NULL.
int was_queued
Did we add this request to the queue?
struct GNUNET_RESOLVER_RequestHandle * next
Next entry in DLL of requests.
void * cls
Closure for the callbacks.
int was_transmitted
Has this request been transmitted to the service? GNUNET_YES if transmitted GNUNET_NO if not transmit...
size_t data_len
Length of the data that follows this struct.
GNUNET_RESOLVER_AddressCallback addr_callback
Callback if this is an name resolution request, otherwise NULL.
int af
Desired address family.
uint32_t id
Identifies the request.
struct GNUNET_TIME_Absolute timeout
When should this request time out?
struct GNUNET_RESOLVER_RequestHandle * prev
Previous entry in DLL of requests.
int received_response
GNUNET_YES if a response was received
int direction
Desired direction (IP to name or name to IP)
Entry in list of pending tasks.
Definition scheduler.c:136
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.

◆ MAX_HOSTNAME

#define MAX_HOSTNAME   1024

Maximum supported length for a hostname.

Definition at line 42 of file resolver_api.c.

Function Documentation

◆ check_config()

static int check_config ( )
static

Check that the resolver service runs on localhost (or equivalent).

Returns
GNUNET_OK if the resolver is properly configured, GNUNET_SYSERR otherwise.

Definition at line 191 of file resolver_api.c.

192{
193 char *hostname;
194 struct sockaddr_in v4;
195 struct sockaddr_in6 v6;
196
197 if (GNUNET_OK ==
199 "resolver",
200 "UNIXPATH"))
201 return GNUNET_OK;
202 memset (&v4, 0, sizeof(v4));
203 v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
204 v4.sin_family = AF_INET;
205#if HAVE_SOCKADDR_IN_SIN_LEN
206 v4.sin_len = sizeof(v4);
207#endif
208 memset (&v6, 0, sizeof(v6));
209 v6.sin6_family = AF_INET6;
210#if HAVE_SOCKADDR_IN_SIN_LEN
211 v6.sin6_len = sizeof(v6);
212#endif
213 if (GNUNET_OK !=
215 "resolver",
216 "HOSTNAME",
217 &hostname))
218 {
220 _ (
221 "Missing `%s' for `%s' in configuration, DNS resolution will be unavailable.\n"),
222 "HOSTNAME",
223 "resolver");
224 return GNUNET_SYSERR;
225 }
226 if ((1 == inet_pton (AF_INET, hostname, &v4)) ||
227 (1 == inet_pton (AF_INET6, hostname, &v6)))
228 {
229 GNUNET_free (hostname);
230 return GNUNET_OK;
231 }
232 for (unsigned int i = 0;
233 NULL != loopback[i];
234 i++)
235 if (0 == strcasecmp (loopback[i],
236 hostname))
237 {
238 GNUNET_free (hostname);
239 return GNUNET_OK;
240 }
242 _ (
243 "Missing `%s' or numeric IP address for `%s' of `%s' in configuration, DNS resolution will be unavailable.\n"),
244 "localhost",
245 "HOSTNAME",
246 "resolver");
247 GNUNET_free (hostname);
248 return GNUNET_SYSERR;
249}

References _, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_have_value(), GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_OK, GNUNET_SYSERR, LOG, loopback, and resolver_cfg.

Referenced by GNUNET_RESOLVER_hostname_get(), and GNUNET_RESOLVER_ip_get().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

Task executed on system shutdown.

Definition at line 306 of file resolver_api.c.

307{
308 (void) cls;
309 s_task = NULL;
312}

References backoff, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_RESOLVER_disconnect(), GNUNET_TIME_UNIT_MILLISECONDS, and s_task.

Here is the call graph for this function:

◆ check_disconnect()

static void check_disconnect ( )
static

Consider disconnecting if we have no further requests pending.

Definition at line 319 of file resolver_api.c.

320{
321 for (struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
322 NULL != rh;
323 rh = rh->next)
324 if (GNUNET_SYSERR != rh->was_transmitted)
325 return;
326 if (NULL != r_task)
327 {
329 r_task = NULL;
330 }
331 if (NULL != s_task)
332 return;
335 NULL);
336}

References GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_SYSERR, GNUNET_TIME_UNIT_MILLISECONDS, GNUNET_RESOLVER_RequestHandle::next, r_task, req_head, s_task, and shutdown_task.

Referenced by GNUNET_RESOLVER_request_cancel(), and reconnect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ no_resolve()

static char * no_resolve ( int  af,
const void *  ip,
socklen_t  ip_len 
)
static

Convert IP address to string without DNS resolution.

Parameters
afaddress family
ipthe address
ip_lennumber of bytes in ip
Returns
address as a string, NULL on error

Definition at line 348 of file resolver_api.c.

351{
352 char buf[INET6_ADDRSTRLEN];
353
354 switch (af)
355 {
356 case AF_INET:
357 if (ip_len != sizeof(struct in_addr))
358 return NULL;
359 if (NULL ==
360 inet_ntop (AF_INET,
361 ip,
362 buf,
363 sizeof(buf)))
364 {
366 "inet_ntop");
367 return NULL;
368 }
369 break;
370
371 case AF_INET6:
372 if (ip_len != sizeof(struct in6_addr))
373 return NULL;
374 if (NULL ==
375 inet_ntop (AF_INET6,
376 ip,
377 buf,
378 sizeof(buf)))
379 {
381 "inet_ntop");
382 return NULL;
383 }
384 break;
385
386 default:
387 GNUNET_break (0);
388 return NULL;
389 }
390 return GNUNET_strdup (buf);
391}

References GNUNET_RESOLVER_RequestHandle::af, GNUNET_break, GNUNET_ERROR_TYPE_WARNING, GNUNET_strdup, and LOG_STRERROR.

Referenced by handle_lookup_timeout(), handle_response(), and numeric_reverse().

Here is the caller graph for this function:

◆ reconnect()

static void reconnect ( void  )
static

Adjust exponential back-off and reconnect to the service.

Definition at line 828 of file resolver_api.c.

829{
831
832 if (NULL != r_task)
833 return;
834 GNUNET_assert (NULL == mq);
835 if (NULL != (rh = req_head))
836 {
837 switch (rh->was_transmitted)
838 {
839 case GNUNET_NO:
840 /* nothing more to do */
841 break;
842
843 case GNUNET_YES:
844 /* disconnected, transmit again! */
846 break;
847
848 case GNUNET_SYSERR:
849 /* request was cancelled, remove entirely */
851 req_tail,
852 rh);
853 GNUNET_free (rh);
855 break;
856
857 default:
858 GNUNET_assert (0);
859 break;
860 }
861 }
863 "Will try to connect to DNS service in %s\n",
865 GNUNET_YES));
866 GNUNET_assert (NULL != resolver_cfg);
869 NULL);
871}

References backoff, check_disconnect(), GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_STD_BACKOFF, GNUNET_YES, LOG, mq, r_task, reconnect_task(), req_head, req_tail, resolver_cfg, and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Referenced by callback_reconnect(), disconnect_and_schedule_reconnect(), disconnect_and_schedule_reconnect(), do_connect(), error_handler(), error_handler(), error_handler(), error_handler(), error_handler(), error_handler(), force_reconnect(), GNUNET_ABD_connect(), GNUNET_CADET_connect(), GNUNET_CADET_get_channel(), GNUNET_CADET_get_path(), GNUNET_CADET_list_peers(), GNUNET_CADET_list_tunnels(), GNUNET_CORE_connect(), GNUNET_CORE_monitor_start(), GNUNET_DNS_connect(), GNUNET_GNS_connect(), GNUNET_IDENTITY_connect(), GNUNET_MESSENGER_connect(), GNUNET_NAMECACHE_connect(), GNUNET_NAMESTORE_connect(), GNUNET_NAMESTORE_zone_monitor_start(), GNUNET_NAMESTORE_zone_monitor_start2(), GNUNET_NSE_connect(), GNUNET_PEERSTORE_connect(), GNUNET_PEERSTORE_monitor_start(), GNUNET_PILS_connect(), GNUNET_RECLAIM_connect(), GNUNET_RECLAIM_ticket_consume(), GNUNET_RPS_connect(), GNUNET_TRANSPORT_application_init(), GNUNET_TRANSPORT_communicator_connect(), GNUNET_TRANSPORT_monitor(), handle_address_change_notification(), handle_incoming_ack(), handle_monitor_end(), handle_mq_error(), handle_response(), mq_error_handler(), mq_error_handler(), mq_error_handler(), mq_error_handler(), mq_error_handler(), mq_error_handler(), mq_error_handler(), mq_error_handler(), process_requests(), reconnect(), reconnect(), reconnect_cbk(), reconnect_task(), reconnect_task(), reconnect_task(), reconnect_task(), reconnect_task(), reconnect_task(), reconnect_task(), reconnect_task(), and reschedule_connect().

Here is the call graph for this function:

◆ mq_error_handler()

static void mq_error_handler ( void *  cls,
enum GNUNET_MQ_Error  error 
)
static

Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue.

Not every message queue implementation supports an error handler.

Parameters
clsNULL
errorerror code

Definition at line 410 of file resolver_api.c.

412{
413 (void) cls;
415 mq = NULL;
417 "MQ error %d, reconnecting\n",
418 error);
419 reconnect ();
420}

References GNUNET_RESOLVER_RequestHandle::cls, GNUNET_ERROR_TYPE_DEBUG, GNUNET_MQ_destroy(), LOG, mq, and reconnect().

Referenced by reconnect_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_requests()

static void process_requests ( )
static

Process pending requests to the resolver.

Definition at line 427 of file resolver_api.c.

428{
430 struct GNUNET_MQ_Envelope *env;
432
433 if (NULL == mq)
434 {
435 reconnect ();
436 return;
437 }
438 if (NULL == rh)
439 {
440 /* nothing to do, release socket really soon if there is nothing
441 * else happening... */
442 if (NULL == s_task)
443 s_task =
446 NULL);
447 return;
448 }
449 if (GNUNET_NO != rh->was_transmitted)
450 return; /* waiting for reply */
452 rh->data_len,
454 msg->direction = htonl (rh->direction);
455 msg->af = htonl (rh->af);
456 msg->client_id = rh->id;
457 GNUNET_memcpy (&msg[1],
458 &rh[1],
459 rh->data_len);
461 "Transmitting DNS resolution request (ID %u) to DNS service\n",
462 rh->id);
464 env);
466}

References GNUNET_RESOLVER_RequestHandle::af, GNUNET_RESOLVER_RequestHandle::data_len, GNUNET_RESOLVER_RequestHandle::direction, env, GNUNET_ERROR_TYPE_DEBUG, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_UNIT_MILLISECONDS, GNUNET_YES, GNUNET_RESOLVER_RequestHandle::id, LOG, mq, msg, reconnect(), req_head, s_task, shutdown_task, and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Referenced by GNUNET_RESOLVER_hostname_get(), GNUNET_RESOLVER_ip_get(), handle_lookup_timeout(), handle_response(), and reconnect_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_response()

static int check_response ( void *  cls,
const struct GNUNET_RESOLVER_ResponseMessage msg 
)
static

Check validity of response with a hostname for a DNS lookup.

Parameters
clsNULL
msgmessage with the hostname

Definition at line 476 of file resolver_api.c.

478{
479 (void) cls;
480 (void) msg;
481
482 /* implemented in #handle_response() for now */
483 return GNUNET_OK;
484}

References GNUNET_RESOLVER_RequestHandle::cls, GNUNET_OK, and msg.

◆ handle_response()

static void handle_response ( void *  cls,
const struct GNUNET_RESOLVER_ResponseMessage msg 
)
static

Check validity of response with a hostname for a DNS lookup.

NOTE: right now rather messy, might want to use different message types for different response formats in the future.

Parameters
clsNULL
msgmessage with the response

Definition at line 496 of file resolver_api.c.

498{
500 uint16_t size;
501 char *nret;
502 uint32_t client_request_id = msg->client_id;
503
504 for (; rh != NULL; rh = rh->next)
505 {
506 if (rh->id == client_request_id)
507 break;
508 }
509
510 (void) cls;
511 if (NULL == rh)
512 {
513 /* Resolver service sent extra replies to query (after terminator)? Bad! */
514 GNUNET_break (0);
516 mq = NULL;
517 reconnect ();
518 return;
519 }
520 size = ntohs (msg->header.size);
521 if (size == sizeof(struct GNUNET_RESOLVER_ResponseMessage))
522 {
524 "Received empty response from DNS service\n");
525 /* message contains not data, just header; end of replies */
526 /* check if request was canceled */
528 {
529 /* no reverse lookup was successful, return IP as string */
530 if (NULL != rh->name_callback)
531 {
532 if (GNUNET_NO == rh->received_response)
533 {
534 nret = no_resolve (rh->af,
535 &rh[1],
536 rh->data_len);
537 rh->name_callback (rh->cls, nret);
538 GNUNET_free (nret);
539 }
540 /* finally, make termination call */
542 rh->name_callback (rh->cls,
543 NULL);
544 }
545 if ((NULL != rh->addr_callback) &&
547 rh->addr_callback (rh->cls,
548 NULL,
549 0);
550 }
554 return;
555 }
556 /* return reverse lookup results to caller */
557 if (NULL != rh->name_callback)
558 {
559 const char *hostname;
560
561 hostname = (const char *) &msg[1];
562 if (hostname[size - sizeof(struct GNUNET_RESOLVER_ResponseMessage) - 1] !=
563 '\0')
564 {
565 GNUNET_break (0);
567 rh->name_callback (rh->cls,
568 NULL);
572 mq = NULL;
573 reconnect ();
574 return;
575 }
577 "Resolver returns `%s' for IP `%s'.\n",
578 hostname,
579 GNUNET_a2s ((const void *) &rh[1],
580 rh->data_len));
582 rh->name_callback (rh->cls,
583 hostname);
585 }
586 /* return lookup results to caller */
587 if (NULL != rh->addr_callback)
588 {
589 struct sockaddr_in v4;
590 struct sockaddr_in6 v6;
591 const struct sockaddr *sa;
592 socklen_t salen;
593 const void *ip;
594 size_t ip_len;
595
596 ip = &msg[1];
597 ip_len = size - sizeof(struct GNUNET_RESOLVER_ResponseMessage);
598 if (ip_len == sizeof(struct in_addr))
599 {
600 memset (&v4, 0, sizeof(v4));
601 v4.sin_family = AF_INET;
602 v4.sin_addr = *(struct in_addr*) ip;
603#if HAVE_SOCKADDR_IN_SIN_LEN
604 v4.sin_len = sizeof(v4);
605#endif
606 salen = sizeof(v4);
607 sa = (const struct sockaddr *) &v4;
608 }
609 else if (ip_len == sizeof(struct in6_addr))
610 {
611 memset (&v6, 0, sizeof(v6));
612 v6.sin6_family = AF_INET6;
613 v6.sin6_addr = *(struct in6_addr*) ip;
614#if HAVE_SOCKADDR_IN_SIN_LEN
615 v6.sin6_len = sizeof(v6);
616#endif
617 salen = sizeof(v6);
618 sa = (const struct sockaddr *) &v6;
619 }
620 else
621 {
622 GNUNET_break (0);
624 rh->addr_callback (rh->cls,
625 NULL,
626 0);
630 mq = NULL;
631 reconnect ();
632 return;
633 }
635 "Received IP from DNS service\n");
637 rh->addr_callback (rh->cls,
638 sa,
639 salen);
640 }
641}

References GNUNET_RESOLVER_RequestHandle::addr_callback, GNUNET_RESOLVER_RequestHandle::af, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_RESOLVER_RequestHandle::data_len, GNUNET_a2s(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_MQ_destroy(), GNUNET_NO, GNUNET_RESOLVER_request_cancel(), GNUNET_SYSERR, GNUNET_YES, GNUNET_RESOLVER_RequestHandle::id, LOG, mq, msg, GNUNET_RESOLVER_RequestHandle::name_callback, GNUNET_RESOLVER_RequestHandle::next, no_resolve(), process_requests(), GNUNET_RESOLVER_RequestHandle::received_response, reconnect(), req_head, GNUNET_MessageHeader::size, size, and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Here is the call graph for this function:

◆ numeric_resolution()

static void numeric_resolution ( void *  cls)
static

We've been asked to lookup the address for a hostname and were given a valid numeric string.

Perform the callbacks for the numeric addresses.

Parameters
clsstruct GNUNET_RESOLVER_RequestHandle for the request

Definition at line 652 of file resolver_api.c.

653{
655 struct sockaddr_in v4;
656 struct sockaddr_in6 v6;
657 const char *hostname;
658
659 rh->task = NULL;
660 memset (&v4, 0, sizeof(v4));
661 v4.sin_family = AF_INET;
662#if HAVE_SOCKADDR_IN_SIN_LEN
663 v4.sin_len = sizeof(v4);
664#endif
665 memset (&v6, 0, sizeof(v6));
666 v6.sin6_family = AF_INET6;
667#if HAVE_SOCKADDR_IN_SIN_LEN
668 v6.sin6_len = sizeof(v6);
669#endif
670 hostname = (const char *) &rh[1];
671 if (((rh->af == AF_UNSPEC) ||
672 (rh->af == AF_INET)) &&
673 (1 == inet_pton (AF_INET,
674 hostname,
675 &v4.sin_addr)))
676 {
677 rh->addr_callback (rh->cls,
678 (const struct sockaddr *) &v4,
679 sizeof(v4));
680 if ((rh->af == AF_UNSPEC) &&
682 (1 == inet_pton (AF_INET6,
683 hostname,
684 &v6.sin6_addr)))
685 {
686 /* this can happen on some systems IF "hostname" is "localhost" */
687 rh->addr_callback (rh->cls,
688 (const struct sockaddr *) &v6,
689 sizeof(v6));
690 }
692 rh->addr_callback (rh->cls,
693 NULL,
694 0);
695 GNUNET_free (rh);
696 return;
697 }
698 if (((rh->af == AF_UNSPEC) ||
699 (rh->af == AF_INET6)) &&
700 (1 == inet_pton (AF_INET6,
701 hostname,
702 &v6.sin6_addr)))
703 {
704 rh->addr_callback (rh->cls,
705 (const struct sockaddr *) &v6,
706 sizeof(v6));
708 rh->addr_callback (rh->cls,
709 NULL,
710 0);
711 GNUNET_free (rh);
712 return;
713 }
714 /* why are we here? this task should not have been scheduled! */
715 GNUNET_assert (0);
716 GNUNET_free (rh);
717}

References GNUNET_RESOLVER_RequestHandle::addr_callback, GNUNET_RESOLVER_RequestHandle::af, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_assert, GNUNET_free, GNUNET_SYSERR, GNUNET_RESOLVER_RequestHandle::task, and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Referenced by GNUNET_RESOLVER_ip_get().

Here is the caller graph for this function:

◆ loopback_resolution()

static void loopback_resolution ( void *  cls)
static

We've been asked to lookup the address for a hostname and were given a variant of "loopback".

Perform the callbacks for the respective loopback numeric addresses.

Parameters
clsstruct GNUNET_RESOLVER_RequestHandle for the request

Definition at line 728 of file resolver_api.c.

729{
731 struct sockaddr_in v4;
732 struct sockaddr_in6 v6;
733
734 rh->task = NULL;
735 memset (&v4, 0, sizeof(v4));
736 v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
737 v4.sin_family = AF_INET;
738#if HAVE_SOCKADDR_IN_SIN_LEN
739 v4.sin_len = sizeof(v4);
740#endif
741 memset (&v6, 0, sizeof(v6));
742 v6.sin6_family = AF_INET6;
743#if HAVE_SOCKADDR_IN_SIN_LEN
744 v6.sin6_len = sizeof(v6);
745#endif
746 v6.sin6_addr = in6addr_loopback;
747 switch (rh->af)
748 {
749 case AF_INET:
750 rh->addr_callback (rh->cls,
751 (const struct sockaddr *) &v4,
752 sizeof(v4));
753 break;
754
755 case AF_INET6:
756 rh->addr_callback (rh->cls,
757 (const struct sockaddr *) &v6,
758 sizeof(v6));
759 break;
760
761 case AF_UNSPEC:
762 rh->addr_callback (rh->cls,
763 (const struct sockaddr *) &v6,
764 sizeof(v6));
765 rh->addr_callback (rh->cls,
766 (const struct sockaddr *) &v4,
767 sizeof(v4));
768
769 break;
770
771 default:
772 GNUNET_break (0);
773 break;
774 }
776 rh->addr_callback (rh->cls,
777 NULL,
778 0);
780 "Finished resolving hostname `%s'.\n",
781 (const char *) &rh[1]);
782 GNUNET_free (rh);
783}

References GNUNET_RESOLVER_RequestHandle::addr_callback, GNUNET_RESOLVER_RequestHandle::af, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_SYSERR, LOG, GNUNET_RESOLVER_RequestHandle::task, and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Referenced by GNUNET_RESOLVER_ip_get().

Here is the caller graph for this function:

◆ reconnect_task()

static void reconnect_task ( void *  cls)
static

Now try to reconnect to the resolver service.

Parameters
clsNULL

Definition at line 792 of file resolver_api.c.

793{
798 NULL),
800 };
801
802 (void) cls;
803 r_task = NULL;
804 if (NULL == req_head)
805 return; /* no work pending */
807 "Trying to connect to DNS service\n");
809 "resolver",
810 handlers,
812 NULL);
813 if (NULL == mq)
814 {
816 "Failed to connect, will try again later\n");
817 reconnect ();
818 return;
819 }
821}

References GNUNET_MQ_MessageHandler::cls, GNUNET_CLIENT_connect(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE, GNUNET_MQ_handler_end, GNUNET_MQ_hd_var_size, handlers, LOG, mq, mq_error_handler(), process_requests(), r_task, reconnect(), req_head, resolver_cfg, and response.

Referenced by reconnect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_lookup_timeout()

static void handle_lookup_timeout ( void *  cls)
static

A DNS resolution timed out.

Notify the application.

Parameters
clsthe struct GNUNET_RESOLVER_RequestHandle *

Definition at line 880 of file resolver_api.c.

881{
883
884 rh->task = NULL;
885 if (GNUNET_NO == rh->direction)
886 {
888 _ ("Timeout trying to resolve hostname `%s'.\n"),
889 (const char *) &rh[1]);
890 if (NULL != rh->addr_callback)
891 rh->addr_callback (rh->cls,
892 NULL,
893 0);
894 }
895 else
896 {
897#if ! defined(GNUNET_CULL_LOGGING)
898 char buf[INET6_ADDRSTRLEN];
899
901 _ ("Timeout trying to resolve IP address `%s'.\n"),
902 inet_ntop (rh->af,
903 (const void *) &rh[1],
904 buf,
905 sizeof(buf)));
906#endif
907 if (GNUNET_NO == rh->received_response)
908 {
909 char *nret;
910
911 nret = no_resolve (rh->af,
912 &rh[1],
913 rh->data_len);
914 if (NULL != rh->name_callback)
915 rh->name_callback (rh->cls, nret);
916 GNUNET_free (nret);
917 }
918 /* finally, make termination call */
919 if (NULL != rh->name_callback)
920 rh->name_callback (rh->cls,
921 NULL);
922 }
926}

References _, GNUNET_RESOLVER_RequestHandle::af, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_RESOLVER_RequestHandle::direction, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_NO, GNUNET_RESOLVER_request_cancel(), LOG, no_resolve(), process_requests(), GNUNET_RESOLVER_RequestHandle::task, and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Referenced by GNUNET_RESOLVER_hostname_get(), and GNUNET_RESOLVER_ip_get().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ numeric_reverse()

static void numeric_reverse ( void *  cls)
static

We've been asked to convert an address to a string without a reverse lookup, either because the client asked for it or because the DNS lookup hit a timeout.

Do the numeric conversion and invoke the callback.

Parameters
clsstruct GNUNET_RESOLVER_RequestHandle for the request

Definition at line 1030 of file resolver_api.c.

1031{
1033 char *result;
1034
1035 rh->task = NULL;
1036 result = no_resolve (rh->af,
1037 &rh[1],
1038 rh->data_len);
1040 "Resolver returns `%s'.\n",
1041 result);
1042 if (NULL != result)
1043 {
1044 rh->name_callback (rh->cls,
1045 result);
1047 }
1048 rh->name_callback (rh->cls,
1049 NULL);
1050 if (NULL != rh->task)
1051 {
1053 rh->task = NULL;
1054 }
1055 GNUNET_free (rh);
1056}

References GNUNET_RESOLVER_RequestHandle::af, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_RESOLVER_RequestHandle::data_len, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_SCHEDULER_cancel(), LOG, GNUNET_RESOLVER_RequestHandle::name_callback, no_resolve(), result, and GNUNET_RESOLVER_RequestHandle::task.

Referenced by GNUNET_RESOLVER_hostname_get().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ loopback

const char* loopback[]
static
Initial value:
= {
"localhost",
"ip6-localnet",
NULL
}

Possible hostnames for "loopback".

Definition at line 48 of file resolver_api.c.

48 {
49 "localhost",
50 "ip6-localnet",
51 NULL
52};

Referenced by check_config(), and GNUNET_RESOLVER_ip_get().

◆ resolver_cfg

const struct GNUNET_CONFIGURATION_Handle* resolver_cfg
static

Configuration.

Definition at line 58 of file resolver_api.c.

Referenced by check_config(), GNUNET_RESOLVER_connect(), reconnect(), and reconnect_task().

◆ mq

struct GNUNET_MQ_Handle* mq
static

Our connection to the resolver service, created on-demand, but then persists until error or shutdown.

Definition at line 64 of file resolver_api.c.

Referenced by add_service_handle(), adv_transmit(), cadet_mq_cancel_impl(), cadet_mq_destroy_impl(), cadet_mq_send_impl(), callback_client_connect(), check_peer_online(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), client_connect_cb(), connect_cb(), connect_cb(), connect_cb(), connect_handler(), connect_handler(), connect_notify(), connection_client_cancel_impl(), connection_client_destroy_impl(), connection_client_send_impl(), connects(), continue_writing(), core_connect_cb(), core_connect_cb(), core_connects(), core_mq_cancel_impl(), core_mq_destroy_impl(), core_mq_send_impl(), create_srv_handle(), do_send(), GCP_set_mq(), GNUNET_CADET_drop_message(), GNUNET_FS_indexing_send_list(), GNUNET_MQ_assoc_add(), GNUNET_MQ_assoc_get(), GNUNET_MQ_assoc_remove(), GNUNET_MQ_destroy(), GNUNET_MQ_destroy_notify(), GNUNET_MQ_destroy_notify_cancel(), GNUNET_MQ_env_get_options(), GNUNET_MQ_get_current_envelope(), GNUNET_MQ_get_last_envelope(), GNUNET_MQ_get_length(), GNUNET_MQ_impl_current(), GNUNET_MQ_impl_send_continue(), GNUNET_MQ_impl_send_in_flight(), GNUNET_MQ_impl_state(), GNUNET_MQ_inject_error(), GNUNET_MQ_inject_message(), GNUNET_MQ_queue_for_callbacks(), GNUNET_MQ_send(), GNUNET_MQ_send_cancel(), GNUNET_MQ_send_copy(), GNUNET_MQ_set_handlers_closure(), GNUNET_MQ_set_options(), GNUNET_MQ_unsent_head(), GNUNET_notification_context_add(), GNUNET_RESOLVER_disconnect(), GNUNET_TRANSPORT_communicator_mq_add(), GSC_KX_handle_client_monitor_peers(), GSF_peer_connect_handler(), handle_core_connect(), handle_core_connect(), handle_response(), handle_start(), handle_transport_notify_connect(), impl_send_continue(), mq_destroy(), mq_destroy(), mq_destroy(), mq_destroy_d(), mq_destroy_d(), mq_destroy_d(), mq_destroy_impl(), mq_destroy_kx(), mq_error_handler(), mq_send(), mq_send(), mq_send(), mq_send_d(), mq_send_d(), mq_send_d(), mq_send_impl(), mq_send_kx(), notify_connect(), notify_connect(), notify_connect(), path_info_iterator(), process_requests(), queue_destroy(), reconnect(), reconnect_task(), return_agpl(), return_agpl(), send_message(), send_msg_with_kx(), send_simple_cb(), send_simple_cb(), send_simple_cb(), send_to_channel(), send_tunnel_envelope(), service_mq_cancel(), service_mq_send(), set_mq(), and transmit_pending().

◆ req_head

◆ req_tail

◆ last_request_id

uint32_t last_request_id
static

ID of the last request we sent to the service.

Definition at line 79 of file resolver_api.c.

Referenced by GNUNET_RESOLVER_hostname_get(), and GNUNET_RESOLVER_ip_get().

◆ backoff

struct GNUNET_TIME_Relative backoff
static

How long should we wait to reconnect?

Definition at line 84 of file resolver_api.c.

Referenced by GNUNET_RESOLVER_connect(), reconnect(), and shutdown_task().

◆ r_task

struct GNUNET_SCHEDULER_Task* r_task
static

Task for reconnecting.

Definition at line 89 of file resolver_api.c.

Referenced by check_disconnect(), GNUNET_RESOLVER_disconnect(), reconnect(), and reconnect_task().

◆ s_task

struct GNUNET_SCHEDULER_Task* s_task
static

Task ID of shutdown task; only present while we have a connection to the resolver service.

Definition at line 95 of file resolver_api.c.

Referenced by check_disconnect(), GNUNET_RESOLVER_disconnect(), GNUNET_RESOLVER_hostname_get(), GNUNET_RESOLVER_ip_get(), process_requests(), and shutdown_task().