GNUnet  0.10.x
resolver_api.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009-2018 GNUnet e.V.
4 
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.
9 
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.
14 
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/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_protocols.h"
30 #include "resolver.h"
31 
32 #define LOG(kind,...) GNUNET_log_from (kind, "util-resolver-api", __VA_ARGS__)
33 
34 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-resolver-api", syscall)
35 
39 #define MAX_HOSTNAME 1024
40 
41 
45 static const char *loopback[] = {
46  "localhost",
47  "ip6-localnet",
48  NULL
49 };
50 
51 
56 
61 static struct GNUNET_MQ_Handle *mq;
62 
67 
72 
76 static uint32_t last_request_id;
77 
82 
87 
93 
94 
101 {
102 
107 
112 
118 
124 
128  void *cls;
129 
134 
140 
144  int af;
145 
149  uint32_t id;
150 
158 
163 
168 
173 
177  size_t data_len;
178 };
179 
180 
188 static int
190 {
191  char *hostname;
192  struct sockaddr_in v4;
193  struct sockaddr_in6 v6;
194 
195  if (GNUNET_OK ==
196  GNUNET_CONFIGURATION_have_value (resolver_cfg,
197  "resolver",
198  "UNIXPATH"))
199  return GNUNET_OK;
200  memset (&v4, 0, sizeof (v4));
201  v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
202  v4.sin_family = AF_INET;
203 #if HAVE_SOCKADDR_IN_SIN_LEN
204  v4.sin_len = sizeof (v4);
205 #endif
206  memset (&v6, 0, sizeof (v6));
207  v6.sin6_family = AF_INET6;
208 #if HAVE_SOCKADDR_IN_SIN_LEN
209  v6.sin6_len = sizeof (v6);
210 #endif
211  if (GNUNET_OK !=
213  "resolver",
214  "HOSTNAME",
215  &hostname))
216  {
218  _("Missing `%s' for `%s' in configuration, DNS resolution will be unavailable.\n"),
219  "HOSTNAME",
220  "resolver");
221  return GNUNET_SYSERR;
222  }
223  if ( (1 == inet_pton (AF_INET, hostname, &v4)) ||
224  (1 == inet_pton (AF_INET6, hostname, &v6)) )
225  {
226  GNUNET_free (hostname);
227  return GNUNET_OK;
228  }
229  for (unsigned int i = 0;
230  NULL != loopback[i];
231  i++)
232  if (0 == strcasecmp (loopback[i],
233  hostname))
234  {
235  GNUNET_free (hostname);
236  return GNUNET_OK;
237  }
239  _("Missing `%s' or numeric IP address for `%s' of `%s' in configuration, DNS resolution will be unavailable.\n"),
240  "localhost",
241  "HOSTNAME",
242  "resolver");
243  GNUNET_free (hostname);
244  return GNUNET_SYSERR;
245 }
246 
247 
253 void
255 {
256  GNUNET_assert (NULL != cfg);
258  resolver_cfg = cfg;
259 }
260 
261 
265 void
267 {
269 
270  while (NULL != (rh = req_head))
271  {
273  GNUNET_CONTAINER_DLL_remove (req_head,
274  req_tail,
275  rh);
276  GNUNET_free (rh);
277  }
278  if (NULL != mq)
279  {
281  "Disconnecting from DNS service\n");
282  GNUNET_MQ_destroy (mq);
283  mq = NULL;
284  }
285  if (NULL != r_task)
286  {
287  GNUNET_SCHEDULER_cancel (r_task);
288  r_task = NULL;
289  }
290  if (NULL != s_task)
291  {
292  GNUNET_SCHEDULER_cancel (s_task);
293  s_task = NULL;
294  }
295 }
296 
297 
301 static void
303 {
304  (void) cls;
305  s_task = NULL;
308 }
309 
310 
314 static void
316 {
317  for (struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
318  NULL != rh;
319  rh = rh->next)
320  if (GNUNET_SYSERR != rh->was_transmitted)
321  return;
322  if (NULL != r_task)
323  {
324  GNUNET_SCHEDULER_cancel (r_task);
325  r_task = NULL;
326  }
327  if (NULL != s_task)
328  return;
330  &shutdown_task,
331  NULL);
332 }
333 
334 
343 static char *
345  const void *ip,
346  socklen_t ip_len)
347 {
348  char buf[INET6_ADDRSTRLEN];
349 
350  switch (af)
351  {
352  case AF_INET:
353  if (ip_len != sizeof (struct in_addr))
354  return NULL;
355  if (NULL ==
356  inet_ntop (AF_INET,
357  ip,
358  buf,
359  sizeof (buf)))
360  {
362  "inet_ntop");
363  return NULL;
364  }
365  break;
366  case AF_INET6:
367  if (ip_len != sizeof (struct in6_addr))
368  return NULL;
369  if (NULL ==
370  inet_ntop (AF_INET6,
371  ip,
372  buf,
373  sizeof (buf)))
374  {
376  "inet_ntop");
377  return NULL;
378  }
379  break;
380  default:
381  GNUNET_break (0);
382  return NULL;
383  }
384  return GNUNET_strdup (buf);
385 }
386 
387 
391 static void
392 reconnect (void);
393 
394 
403 static void
405  enum GNUNET_MQ_Error error)
406 {
407  (void) cls;
408  GNUNET_MQ_destroy (mq);
409  mq = NULL;
411  "MQ error %d, reconnecting\n",
412  error);
413  reconnect ();
414 }
415 
416 
420 static void
422 {
424  struct GNUNET_MQ_Envelope *env;
426 
427  if (NULL == mq)
428  {
429  reconnect ();
430  return;
431  }
432  if (NULL == rh)
433  {
434  /* nothing to do, release socket really soon if there is nothing
435  * else happening... */
436  if (NULL == s_task)
437  s_task =
439  &shutdown_task,
440  NULL);
441  return;
442  }
443  if (GNUNET_NO != rh->was_transmitted)
444  return; /* waiting for reply */
445  env = GNUNET_MQ_msg_extra (msg,
446  rh->data_len,
448  msg->direction = htonl (rh->direction);
449  msg->af = htonl (rh->af);
450  msg->client_id = rh->id;
451  GNUNET_memcpy (&msg[1],
452  &rh[1],
453  rh->data_len);
455  "Transmitting DNS resolution request (ID %u) to DNS service\n",
456  rh->id);
457  GNUNET_MQ_send (mq,
458  env);
460 }
461 
462 
469 static int
471  const struct GNUNET_RESOLVER_ResponseMessage *msg)
472 {
473  (void) cls;
474  (void) msg;
475 
476  /* implemented in #handle_response() for now */
477  return GNUNET_OK;
478 }
479 
480 
489 static void
491  const struct GNUNET_RESOLVER_ResponseMessage *msg)
492 {
494  uint16_t size;
495  char *nret;
496  uint32_t client_request_id = msg->client_id;
497 
498  for (; rh != NULL; rh = rh->next)
499  {
500  if (rh->id == client_request_id)
501  break;
502  }
503 
504  (void) cls;
505  if (NULL == rh)
506  {
507  /* Resolver service sent extra replies to query (after terminator)? Bad! */
508  GNUNET_break (0);
509  GNUNET_MQ_destroy (mq);
510  mq = NULL;
511  reconnect ();
512  return;
513  }
514  size = ntohs (msg->header.size);
515  if (size == sizeof (struct GNUNET_RESOLVER_ResponseMessage))
516  {
518  "Received empty response from DNS service\n");
519  /* message contains not data, just header; end of replies */
520  /* check if request was canceled */
521  if (GNUNET_SYSERR != rh->was_transmitted)
522  {
523  /* no reverse lookup was successful, return IP as string */
524  if (NULL != rh->name_callback)
525  {
526  if (GNUNET_NO == rh->received_response)
527  {
528  nret = no_resolve (rh->af,
529  &rh[1],
530  rh->data_len);
531  rh->name_callback (rh->cls, nret);
532  GNUNET_free (nret);
533  }
534  /* finally, make termination call */
535  if (GNUNET_SYSERR != rh->was_transmitted)
536  rh->name_callback (rh->cls,
537  NULL);
538  }
539  if ( (NULL != rh->addr_callback) &&
540  (GNUNET_SYSERR != rh->was_transmitted) )
541  rh->addr_callback (rh->cls,
542  NULL,
543  0);
544  }
547  process_requests ();
548  return;
549  }
550  /* return reverse lookup results to caller */
551  if (NULL != rh->name_callback)
552  {
553  const char *hostname;
554 
555  hostname = (const char *) &msg[1];
556  if (hostname[size - sizeof (struct GNUNET_RESOLVER_ResponseMessage) - 1] != '\0')
557  {
558  GNUNET_break (0);
559  if (GNUNET_SYSERR != rh->was_transmitted)
560  rh->name_callback (rh->cls,
561  NULL);
564  GNUNET_MQ_destroy (mq);
565  mq = NULL;
566  reconnect ();
567  return;
568  }
570  "Resolver returns `%s' for IP `%s'.\n",
571  hostname,
572  GNUNET_a2s ((const void *) &rh[1],
573  rh->data_len));
574  if (rh->was_transmitted != GNUNET_SYSERR)
575  rh->name_callback (rh->cls,
576  hostname);
577  rh->received_response = GNUNET_YES;
578  }
579  /* return lookup results to caller */
580  if (NULL != rh->addr_callback)
581  {
582  struct sockaddr_in v4;
583  struct sockaddr_in6 v6;
584  const struct sockaddr *sa;
585  socklen_t salen;
586  const void *ip;
587  size_t ip_len;
588 
589  ip = &msg[1];
590  ip_len = size - sizeof (struct GNUNET_RESOLVER_ResponseMessage);
591  if (ip_len == sizeof (struct in_addr))
592  {
593  memset (&v4, 0, sizeof (v4));
594  v4.sin_family = AF_INET;
595  v4.sin_addr = *(struct in_addr*) ip;
596 #if HAVE_SOCKADDR_IN_SIN_LEN
597  v4.sin_len = sizeof (v4);
598 #endif
599  salen = sizeof (v4);
600  sa = (const struct sockaddr *) &v4;
601  }
602  else if (ip_len == sizeof (struct in6_addr))
603  {
604  memset (&v6, 0, sizeof (v6));
605  v6.sin6_family = AF_INET6;
606  v6.sin6_addr = *(struct in6_addr*) ip;
607 #if HAVE_SOCKADDR_IN_SIN_LEN
608  v6.sin6_len = sizeof (v6);
609 #endif
610  salen = sizeof (v6);
611  sa = (const struct sockaddr *) &v6;
612  }
613  else
614  {
615  GNUNET_break (0);
616  if (GNUNET_SYSERR != rh->was_transmitted)
617  rh->addr_callback (rh->cls,
618  NULL,
619  0);
622  GNUNET_MQ_destroy (mq);
623  mq = NULL;
624  reconnect ();
625  return;
626  }
628  "Received IP from DNS service\n");
629  if (GNUNET_SYSERR != rh->was_transmitted)
630  rh->addr_callback (rh->cls,
631  sa,
632  salen);
633  }
634 }
635 
636 
644 static void
646 {
647  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
648  struct sockaddr_in v4;
649  struct sockaddr_in6 v6;
650  const char *hostname;
651 
652  rh->task = NULL;
653  memset (&v4, 0, sizeof (v4));
654  v4.sin_family = AF_INET;
655 #if HAVE_SOCKADDR_IN_SIN_LEN
656  v4.sin_len = sizeof (v4);
657 #endif
658  memset (&v6, 0, sizeof (v6));
659  v6.sin6_family = AF_INET6;
660 #if HAVE_SOCKADDR_IN_SIN_LEN
661  v6.sin6_len = sizeof (v6);
662 #endif
663  hostname = (const char *) &rh[1];
664  if ( ( (rh->af == AF_UNSPEC) ||
665  (rh->af == AF_INET) ) &&
666  (1 == inet_pton (AF_INET,
667  hostname,
668  &v4.sin_addr)) )
669  {
670  rh->addr_callback (rh->cls,
671  (const struct sockaddr *) &v4,
672  sizeof (v4));
673  if ( (rh->af == AF_UNSPEC) &&
674  (GNUNET_SYSERR != rh->was_transmitted) &&
675  (1 == inet_pton (AF_INET6,
676  hostname,
677  &v6.sin6_addr)) )
678  {
679  /* this can happen on some systems IF "hostname" is "localhost" */
680  rh->addr_callback (rh->cls,
681  (const struct sockaddr *) &v6,
682  sizeof (v6));
683  }
684  if (GNUNET_SYSERR != rh->was_transmitted)
685  rh->addr_callback (rh->cls,
686  NULL,
687  0);
688  GNUNET_free (rh);
689  return;
690  }
691  if ( ( (rh->af == AF_UNSPEC) ||
692  (rh->af == AF_INET6) ) &&
693  (1 == inet_pton (AF_INET6,
694  hostname,
695  &v6.sin6_addr) ) )
696  {
697  rh->addr_callback (rh->cls,
698  (const struct sockaddr *) &v6,
699  sizeof (v6));
700  if (GNUNET_SYSERR != rh->was_transmitted)
701  rh->addr_callback (rh->cls,
702  NULL,
703  0);
704  GNUNET_free (rh);
705  return;
706  }
707  /* why are we here? this task should not have been scheduled! */
708  GNUNET_assert (0);
709  GNUNET_free (rh);
710 }
711 
712 
720 static void
722 {
723  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
724  struct sockaddr_in v4;
725  struct sockaddr_in6 v6;
726 
727  rh->task = NULL;
728  memset (&v4, 0, sizeof (v4));
729  v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
730  v4.sin_family = AF_INET;
731 #if HAVE_SOCKADDR_IN_SIN_LEN
732  v4.sin_len = sizeof (v4);
733 #endif
734  memset (&v6, 0, sizeof (v6));
735  v6.sin6_family = AF_INET6;
736 #if HAVE_SOCKADDR_IN_SIN_LEN
737  v6.sin6_len = sizeof (v6);
738 #endif
739  v6.sin6_addr = in6addr_loopback;
740  switch (rh->af)
741  {
742  case AF_INET:
743  rh->addr_callback (rh->cls,
744  (const struct sockaddr *) &v4,
745  sizeof (v4));
746  break;
747  case AF_INET6:
748  rh->addr_callback (rh->cls,
749  (const struct sockaddr *) &v6,
750  sizeof (v6));
751  break;
752  case AF_UNSPEC:
753  rh->addr_callback (rh->cls,
754  (const struct sockaddr *) &v6,
755  sizeof (v6));
756  rh->addr_callback (rh->cls,
757  (const struct sockaddr *) &v4,
758  sizeof (v4));
759 
760  break;
761  default:
762  GNUNET_break (0);
763  break;
764  }
765  if (GNUNET_SYSERR != rh->was_transmitted)
766  rh->addr_callback (rh->cls,
767  NULL,
768  0);
770  "Finished resolving hostname `%s'.\n",
771  (const char *) &rh[1]);
772  GNUNET_free (rh);
773 }
774 
775 
781 static void
783 {
784  struct GNUNET_MQ_MessageHandler handlers[] = {
788  NULL),
790  };
791 
792  (void) cls;
793  r_task = NULL;
794  if (NULL == req_head)
795  return; /* no work pending */
797  "Trying to connect to DNS service\n");
798  mq = GNUNET_CLIENT_connect (resolver_cfg,
799  "resolver",
800  handlers,
802  NULL);
803  if (NULL == mq)
804  {
806  "Failed to connect, will try again later\n");
807  reconnect ();
808  return;
809  }
810  process_requests ();
811 }
812 
813 
817 static void
819 {
821 
822  if (NULL != r_task)
823  return;
824  GNUNET_assert (NULL == mq);
825  if (NULL != (rh = req_head))
826  {
827  switch (rh->was_transmitted)
828  {
829  case GNUNET_NO:
830  /* nothing more to do */
831  break;
832  case GNUNET_YES:
833  /* disconnected, transmit again! */
835  break;
836  case GNUNET_SYSERR:
837  /* request was cancelled, remove entirely */
838  GNUNET_CONTAINER_DLL_remove (req_head,
839  req_tail,
840  rh);
841  GNUNET_free (rh);
842  check_disconnect ();
843  break;
844  default:
845  GNUNET_assert (0);
846  break;
847  }
848  }
850  "Will try to connect to DNS service in %s\n",
852  GNUNET_YES));
853  GNUNET_assert (NULL != resolver_cfg);
856  NULL);
858 }
859 
860 
866 static void
868 {
869  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
870 
871  rh->task = NULL;
872  if (GNUNET_NO == rh->direction)
873  {
875  _("Timeout trying to resolve hostname `%s'.\n"),
876  (const char *) &rh[1]);
877  if (NULL != rh->addr_callback)
878  rh->addr_callback (rh->cls,
879  NULL,
880  0);
881  }
882  else
883  {
884 #if !defined(GNUNET_CULL_LOGGING)
885  char buf[INET6_ADDRSTRLEN];
886 
888  _("Timeout trying to resolve IP address `%s'.\n"),
889  inet_ntop (rh->af,
890  (const void *) &rh[1],
891  buf,
892  sizeof(buf)));
893 #endif
894  if (GNUNET_NO == rh->received_response)
895  {
896  char *nret;
897 
898  nret = no_resolve (rh->af,
899  &rh[1],
900  rh->data_len);
901  if (NULL != rh->name_callback)
902  rh->name_callback (rh->cls, nret);
903  GNUNET_free (nret);
904  }
905  /* finally, make termination call */
906  if (NULL != rh->name_callback)
907  rh->name_callback (rh->cls,
908  NULL);
909  }
912  process_requests ();
913 }
914 
915 
928  int af,
931  void *callback_cls)
932 {
934  size_t slen;
935  struct in_addr v4;
936  struct in6_addr v6;
937 
938  slen = strlen (hostname) + 1;
939  if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >=
941  {
942  GNUNET_break (0);
943  return NULL;
944  }
946  "Trying to resolve hostname `%s'.\n",
947  hostname);
948  rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen);
949  rh->af = af;
950  rh->id = ++last_request_id;
951  rh->addr_callback = callback;
952  rh->cls = callback_cls;
953  GNUNET_memcpy (&rh[1],
954  hostname,
955  slen);
956  rh->data_len = slen;
958  rh->direction = GNUNET_NO;
959  /* first, check if this is a numeric address */
960  if ( ( (1 == inet_pton (AF_INET,
961  hostname,
962  &v4)) &&
963  ( (af == AF_INET) ||
964  (af == AF_UNSPEC) ) ) ||
965  ( (1 == inet_pton (AF_INET6,
966  hostname,
967  &v6)) &&
968  ( (af == AF_INET6) ||
969  (af == AF_UNSPEC)) ) )
970  {
972  rh);
973  return rh;
974  }
975  /* then, check if this is a loopback address */
976  for (unsigned int i = 0;
977  NULL != loopback[i];
978  i++)
979  if (0 == strcasecmp (loopback[i],
980  hostname))
981  {
983  rh);
984  return rh;
985  }
986  if (GNUNET_OK != check_config ())
987  {
988  GNUNET_free (rh);
989  return NULL;
990  }
991  rh->task = GNUNET_SCHEDULER_add_delayed (timeout,
993  rh);
995  req_tail,
996  rh);
997  rh->was_queued = GNUNET_YES;
998  if (NULL != s_task)
999  {
1000  GNUNET_SCHEDULER_cancel (s_task);
1001  s_task = NULL;
1002  }
1003  process_requests ();
1004  return rh;
1005 }
1006 
1007 
1016 static void
1018 {
1019  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
1020  char *result;
1021 
1022  rh->task = NULL;
1023  result = no_resolve (rh->af,
1024  &rh[1],
1025  rh->data_len);
1027  "Resolver returns `%s'.\n",
1028  result);
1029  if (NULL != result)
1030  {
1031  rh->name_callback (rh->cls,
1032  result);
1033  GNUNET_free (result);
1034  }
1035  rh->name_callback (rh->cls,
1036  NULL);
1037  if (NULL != rh->task)
1038  {
1040  rh->task = NULL;
1041  }
1042  GNUNET_free (rh);
1043 }
1044 
1045 
1059 GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa,
1060  socklen_t salen,
1061  int do_resolve,
1064  void *cls)
1065 {
1066  struct GNUNET_RESOLVER_RequestHandle *rh;
1067  size_t ip_len;
1068  const void *ip;
1069 
1070  if (GNUNET_OK != check_config ())
1071  {
1073  _("Resolver not configured correctly.\n"));
1074  return NULL;
1075  }
1076 
1077  switch (sa->sa_family)
1078  {
1079  case AF_INET:
1080  GNUNET_assert (salen == sizeof (struct sockaddr_in));
1081  ip_len = sizeof (struct in_addr);
1082  ip = &((const struct sockaddr_in*)sa)->sin_addr;
1083  break;
1084  case AF_INET6:
1085  GNUNET_assert (salen == sizeof (struct sockaddr_in6));
1086  ip_len = sizeof (struct in6_addr);
1087  ip = &((const struct sockaddr_in6*)sa)->sin6_addr;
1088  break;
1089  default:
1090  GNUNET_break (0);
1091  return NULL;
1092  }
1093  rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + salen);
1094  rh->name_callback = callback;
1095  rh->cls = cls;
1096  rh->af = sa->sa_family;
1097  rh->id = ++last_request_id;
1098  rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1099  GNUNET_memcpy (&rh[1],
1100  ip,
1101  ip_len);
1102  rh->data_len = ip_len;
1103  rh->direction = GNUNET_YES;
1105  if (GNUNET_NO == do_resolve)
1106  {
1108  rh);
1109  return rh;
1110  }
1111  rh->task = GNUNET_SCHEDULER_add_delayed (timeout,
1113  rh);
1115  req_tail,
1116  rh);
1117  rh->was_queued = GNUNET_YES;
1118  if (NULL != s_task)
1119  {
1120  GNUNET_SCHEDULER_cancel (s_task);
1121  s_task = NULL;
1122  }
1123  process_requests ();
1124  return rh;
1125 }
1126 
1127 
1133 char *
1135 {
1137 
1138  if (0 != gethostname (hostname,
1139  sizeof (hostname) - 1))
1140  {
1142  "gethostname");
1143  return NULL;
1144  }
1146  "Resolving our FQDN `%s'\n",
1147  hostname);
1148 #if HAVE_GETADDRINFO
1149  {
1150  struct addrinfo *ai;
1151  int ret;
1152  char *rval;
1153 
1154  if (0 != (ret = getaddrinfo (hostname,
1155  NULL,
1156  NULL,
1157  &ai)))
1158  {
1160  _("Could not resolve our FQDN: %s\n"),
1161  gai_strerror (ret));
1162  return NULL;
1163  }
1164  if (NULL != ai->ai_canonname)
1165  rval = GNUNET_strdup (ai->ai_canonname);
1166  else
1167  rval = GNUNET_strdup (hostname);
1168  freeaddrinfo (ai);
1169  return rval;
1170  }
1171 #elif HAVE_GETHOSTBYNAME2
1172  {
1173  struct hostent *host;
1174 
1175  host = gethostbyname2 (hostname,
1176  AF_INET);
1177  if (NULL == host)
1178  host = gethostbyname2 (hostname,
1179  AF_INET6);
1180  if (NULL == host)
1181  {
1183  _("Could not resolve our FQDN: %s\n"),
1184  hstrerror (h_errno));
1185  return NULL;
1186  }
1187  return GNUNET_strdup (host->h_name);
1188  }
1189 #elif HAVE_GETHOSTBYNAME
1190  {
1191  struct hostent *host;
1192 
1193  host = gethostbyname (hostname);
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 #else
1204  /* fallback: just hope name is already FQDN */
1205  return GNUNET_strdup (hostname);
1206 #endif
1207 }
1208 
1209 
1223  void *cls)
1224 {
1226 
1227  if (0 != gethostname (hostname, sizeof (hostname) - 1))
1228  {
1230  "gethostname");
1231  return NULL;
1232  }
1234  "Resolving our hostname `%s'\n",
1235  hostname);
1236  return GNUNET_RESOLVER_ip_get (hostname,
1237  af,
1238  timeout,
1239  callback,
1240  cls);
1241 }
1242 
1243 
1252 void
1254 {
1255  if (GNUNET_NO == rh->direction)
1257  "Asked to cancel request to resolve hostname `%s'.\n",
1258  (const char *) &rh[1]);
1259  if (NULL != rh->task)
1260  {
1261  GNUNET_SCHEDULER_cancel (rh->task);
1262  rh->task = NULL;
1263  }
1264  if (GNUNET_NO == rh->was_transmitted)
1265  {
1266  if (GNUNET_YES == rh->was_queued)
1267  GNUNET_CONTAINER_DLL_remove (req_head,
1268  req_tail,
1269  rh);
1270  GNUNET_free (rh);
1271  check_disconnect ();
1272  return;
1273  }
1274  GNUNET_assert (GNUNET_YES == rh->was_transmitted);
1275  rh->was_transmitted = GNUNET_SYSERR; /* mark as cancelled */
1276  check_disconnect ();
1277 }
1278 
1279 
1280 /* end of resolver_api.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct GNUNET_SCHEDULER_Task * r_task
Task for reconnecting.
Definition: resolver_api.c:86
int32_t direction
GNUNET_YES to get hostname from IP, GNUNET_NO to get IP from hostname.
Definition: resolver.h:54
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
static struct GNUNET_TIME_Relative backoff
How long should we wait to reconnect?
Definition: resolver_api.c:81
static struct GNUNET_RESOLVER_RequestHandle * req_tail
Tail of DLL of requests.
Definition: resolver_api.c:71
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:901
static void reconnect_task(void *cls)
Now try to reconnect to the resolver service.
Definition: resolver_api.c:782
GNUNET_RESOLVER_AddressCallback addr_callback
Callback if this is an name resolution request, otherwise NULL.
Definition: resolver_api.c:117
GNUNET_MQ_Error
Error codes for the queue.
struct GNUNET_RESOLVER_RequestHandle * prev
Previous entry in DLL of requests.
Definition: resolver_api.c:111
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:245
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void numeric_resolution(void *cls)
We&#39;ve been asked to lookup the address for a hostname and were given a valid numeric string...
Definition: resolver_api.c:645
static const struct GNUNET_CONFIGURATION_Handle * resolver_cfg
Configuration.
Definition: resolver_api.c:55
#define GNUNET_NO
Definition: gnunet_common.h:81
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.
Definition: resolver_api.c:927
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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...
Definition: resolver_api.c:404
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
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.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
static void process_requests()
Process pending requests to the resolver.
Definition: resolver_api.c:421
uint32_t client_id
identifies the request this message responds to.
Definition: resolver.h:84
#define LOG_STRERROR(kind, syscall)
Definition: resolver_api.c:34
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE.
Definition: resolver.h:78
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define LOG(kind,...)
Definition: resolver_api.c:32
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
GNUNET_RESOLVER_HostnameCallback name_callback
Callback if this is a reverse lookup request, otherwise NULL.
Definition: resolver_api.c:123
static void numeric_reverse(void *cls)
We&#39;ve been asked to convert an address to a string without a reverse lookup, either because the clien...
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
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:1246
#define GNUNET_memcpy(dst, src, n)
static const char * loopback[]
Possible hostnames for "loopback".
Definition: resolver_api.c:45
#define GNUNET_OS_get_hostname_max_length()
Get maximum string length returned by gethostname()
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
static uint32_t last_request_id
ID of the last request we sent to the service.
Definition: resolver_api.c:76
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:1273
int 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.
char * GNUNET_RESOLVER_local_fqdn_get()
Get local fully qualified af name.
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:727
int af
Desired address family.
Definition: resolver_api.c:144
void(* GNUNET_RESOLVER_AddressCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Function called by the resolver for each address obtained from DNS.
static char buf[2048]
static int result
Global testing status.
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)...
#define GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE
Response to a DNS resolution request.
struct GNUNET_TIME_Absolute timeout
When should this request time out?
Definition: resolver_api.c:133
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
Message handler for a specific message type.
struct GNUNET_RESOLVER_RequestHandle * next
Next entry in DLL of requests.
Definition: resolver_api.c:106
int 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.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
int was_transmitted
Has this request been transmitted to the service? GNUNET_YES if transmitted GNUNET_YES if not transmi...
Definition: resolver_api.c:157
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.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
GUID host
struct GNUNET_SCHEDULER_Task * task
Task handle for making reply callbacks in numeric lookups asynchronous, and for timeout handling...
Definition: resolver_api.c:139
Handle to a request given to the resolver.
Definition: resolver_api.c:100
static void shutdown_task(void *cls)
Task executed on system shutdown.
Definition: resolver_api.c:302
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
int was_queued
Did we add this request to the queue?
Definition: resolver_api.c:162
void(* GNUNET_RESOLVER_HostnameCallback)(void *cls, const char *hostname)
Function called by the resolver for each hostname obtained from DNS.
static struct GNUNET_SCHEDULER_Task * s_task
Task ID of shutdown task; only present while we have a connection to the resolver service...
Definition: resolver_api.c:92
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
Handle to a message queue.
Definition: mq.c:85
int32_t af
Address family to use (AF_INET, AF_INET6 or AF_UNSPEC).
Definition: resolver.h:59
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown...
Definition: resolver_api.c:61
static void loopback_resolution(void *cls)
We&#39;ve been asked to lookup the address for a hostname and were given a variant of "loopback"...
Definition: resolver_api.c:721
static char * hostname
Our hostname; we give this to all the peers we start.
static int check_config()
Check that the resolver service runs on localhost (or equivalent).
Definition: resolver_api.c:189
configuration data
Definition: configuration.c:85
#define GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST
Request DNS resolution.
void GNUNET_RESOLVER_disconnect()
Destroy the connection to the resolver service.
Definition: resolver_api.c:266
uint32_t client_id
identifies the request and is contained in the response message.
Definition: resolver.h:65
static struct GNUNET_RESOLVER_RequestHandle * req_head
Head of DLL of requests.
Definition: resolver_api.c:66
static int inet_pton(int af, const char *cp, struct in_addr *buf)
Convert IPv4 address from text to binary form.
Entry in list of pending tasks.
Definition: scheduler.c:134
static void handle_response(void *cls, const struct GNUNET_RESOLVER_ResponseMessage *msg)
Check validity of response with a hostname for a DNS lookup.
Definition: resolver_api.c:490
static struct MHD_Response * response
Our canonical response.
void * cls
Closure for the callbacks.
Definition: resolver_api.c:128
static void check_disconnect()
Consider disconnecting if we have no further requests pending.
Definition: resolver_api.c:315
Time for absolute times used by GNUnet, in microseconds.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:824
#define GNUNET_YES
Definition: gnunet_common.h:80
static char * no_resolve(int af, const void *ip, socklen_t ip_len)
Convert IP address to string without DNS resolution.
Definition: resolver_api.c:344
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:353
size_t data_len
Length of the data that follows this struct.
Definition: resolver_api.c:177
Request for the resolver.
Definition: resolver.h:43
uint32_t id
Identifies the request.
Definition: resolver_api.c:149
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
int direction
Desired direction (IP to name or name to IP)
Definition: resolver_api.c:167
int received_response
GNUNET_YES if a response was received
Definition: resolver_api.c:172
void GNUNET_RESOLVER_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create the connection to the resolver service.
Definition: resolver_api.c:254
#define GNUNET_malloc(size)
Wrapper around malloc.
static void handle_lookup_timeout(void *cls)
A DNS resolution timed out.
Definition: resolver_api.c:867
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
static int check_response(void *cls, const struct GNUNET_RESOLVER_ResponseMessage *msg)
Check validity of response with a hostname for a DNS lookup.
Definition: resolver_api.c:470
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
static void reconnect(void)
Adjust exponential back-off and reconnect to the service.
Definition: resolver_api.c:818