GNUnet  0.20.0
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 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_protocols.h"
31 #include "resolver.h"
32 
33 #define LOG(kind, ...) GNUNET_log_from (kind, "util-resolver-api", __VA_ARGS__)
34 
35 #define LOG_STRERROR(kind, syscall) GNUNET_log_from_strerror (kind, \
36  "util-resolver-api", \
37  syscall)
38 
42 #define MAX_HOSTNAME 1024
43 
44 
48 static const char *loopback[] = {
49  "localhost",
50  "ip6-localnet",
51  NULL
52 };
53 
54 
59 
64 static struct GNUNET_MQ_Handle *mq;
65 
70 
75 
79 static uint32_t last_request_id;
80 
84 static struct GNUNET_TIME_Relative backoff;
85 
90 
96 
97 
104 {
109 
114 
120 
126 
130  void *cls;
131 
136 
142 
146  int af;
147 
151  uint32_t id;
152 
160 
165 
170 
175 
179  size_t data_len;
180 };
181 
182 
190 static int
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  {
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  {
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");
248  return GNUNET_SYSERR;
249 }
250 
251 
257 void
259 {
260  GNUNET_assert (NULL != cfg);
262  resolver_cfg = cfg;
263 }
264 
265 
269 void
271 {
273 
274  while (NULL != (rh = req_head))
275  {
278  req_tail,
279  rh);
280  GNUNET_free (rh);
281  }
282  if (NULL != mq)
283  {
285  "Disconnecting from DNS service\n");
287  mq = NULL;
288  }
289  if (NULL != r_task)
290  {
292  r_task = NULL;
293  }
294  if (NULL != s_task)
295  {
297  s_task = NULL;
298  }
299 }
300 
301 
305 static void
307 {
308  (void) cls;
309  s_task = NULL;
312 }
313 
314 
318 static void
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;
334  &shutdown_task,
335  NULL);
336 }
337 
338 
347 static char *
349  const void *ip,
350  socklen_t ip_len)
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 }
392 
393 
397 static void
398 reconnect (void);
399 
400 
409 static void
411  enum GNUNET_MQ_Error error)
412 {
413  (void) cls;
415  mq = NULL;
417  "MQ error %d, reconnecting\n",
418  error);
419  reconnect ();
420 }
421 
422 
426 static void
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 =
445  &shutdown_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 }
467 
468 
475 static int
477  const struct GNUNET_RESOLVER_ResponseMessage *msg)
478 {
479  (void) cls;
480  (void) msg;
481 
482  /* implemented in #handle_response() for now */
483  return GNUNET_OK;
484 }
485 
486 
495 static void
497  const struct GNUNET_RESOLVER_ResponseMessage *msg)
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 */
527  if (GNUNET_SYSERR != rh->was_transmitted)
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 */
541  if (GNUNET_SYSERR != rh->was_transmitted)
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  }
553  process_requests ();
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);
566  if (GNUNET_SYSERR != rh->was_transmitted)
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));
581  if (rh->was_transmitted != GNUNET_SYSERR)
582  rh->name_callback (rh->cls,
583  hostname);
584  rh->received_response = GNUNET_YES;
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);
623  if (GNUNET_SYSERR != rh->was_transmitted)
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");
636  if (GNUNET_SYSERR != rh->was_transmitted)
637  rh->addr_callback (rh->cls,
638  sa,
639  salen);
640  }
641 }
642 
643 
651 static void
653 {
654  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
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) &&
681  (GNUNET_SYSERR != rh->was_transmitted) &&
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  }
691  if (GNUNET_SYSERR != rh->was_transmitted)
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));
707  if (GNUNET_SYSERR != rh->was_transmitted)
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 }
718 
719 
727 static void
729 {
730  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
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  }
775  if (GNUNET_SYSERR != rh->was_transmitted)
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 }
784 
785 
791 static void
792 reconnect_task (void *cls)
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  }
820  process_requests ();
821 }
822 
823 
827 static void
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);
854  check_disconnect ();
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 }
872 
873 
879 static void
881 {
882  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
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  }
925  process_requests ();
926 }
927 
928 
941  int af,
944  void *callback_cls)
945 {
947  size_t slen;
948  struct in_addr v4;
949  struct in6_addr v6;
950 
951  slen = strlen (hostname) + 1;
952  if (slen + sizeof(struct GNUNET_RESOLVER_GetMessage) >=
954  {
955  GNUNET_break (0);
956  return NULL;
957  }
959  "Trying to resolve hostname `%s'.\n",
960  hostname);
961  rh = GNUNET_malloc (sizeof(struct GNUNET_RESOLVER_RequestHandle) + slen);
962  rh->af = af;
963  rh->id = ++last_request_id;
964  rh->addr_callback = callback;
965  rh->cls = callback_cls;
966  GNUNET_memcpy (&rh[1],
967  hostname,
968  slen);
969  rh->data_len = slen;
971  rh->direction = GNUNET_NO;
972  /* first, check if this is a numeric address */
973  if (((1 == inet_pton (AF_INET,
974  hostname,
975  &v4)) &&
976  ((af == AF_INET) ||
977  (af == AF_UNSPEC))) ||
978  ((1 == inet_pton (AF_INET6,
979  hostname,
980  &v6)) &&
981  ((af == AF_INET6) ||
982  (af == AF_UNSPEC))))
983  {
985  rh);
986  return rh;
987  }
988  /* then, check if this is a loopback address */
989  for (unsigned int i = 0;
990  NULL != loopback[i];
991  i++)
992  if (0 == strcasecmp (loopback[i],
993  hostname))
994  {
996  rh);
997  return rh;
998  }
999  if (GNUNET_OK != check_config ())
1000  {
1001  GNUNET_free (rh);
1002  return NULL;
1003  }
1006  rh);
1008  req_tail,
1009  rh);
1010  rh->was_queued = GNUNET_YES;
1011  if (NULL != s_task)
1012  {
1014  s_task = NULL;
1015  }
1016  process_requests ();
1017  return rh;
1018 }
1019 
1020 
1029 static void
1030 numeric_reverse (void *cls)
1031 {
1032  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
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);
1046  GNUNET_free (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 }
1057 
1058 
1072 GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa,
1073  socklen_t salen,
1074  int do_resolve,
1077  void *cls)
1078 {
1079  struct GNUNET_RESOLVER_RequestHandle *rh;
1080  size_t ip_len;
1081  const void *ip;
1082 
1083  if (GNUNET_OK != check_config ())
1084  {
1086  _ ("Resolver not configured correctly.\n"));
1087  return NULL;
1088  }
1089 
1090  switch (sa->sa_family)
1091  {
1092  case AF_INET:
1093  GNUNET_assert (salen == sizeof(struct sockaddr_in));
1094  ip_len = sizeof(struct in_addr);
1095  ip = &((const struct sockaddr_in*) sa)->sin_addr;
1096  break;
1097 
1098  case AF_INET6:
1099  GNUNET_assert (salen == sizeof(struct sockaddr_in6));
1100  ip_len = sizeof(struct in6_addr);
1101  ip = &((const struct sockaddr_in6*) sa)->sin6_addr;
1102  break;
1103 
1104  default:
1105  GNUNET_break (0);
1106  return NULL;
1107  }
1108  rh = GNUNET_malloc (sizeof(struct GNUNET_RESOLVER_RequestHandle) + salen);
1109  rh->name_callback = callback;
1110  rh->cls = cls;
1111  rh->af = sa->sa_family;
1112  rh->id = ++last_request_id;
1114  GNUNET_memcpy (&rh[1],
1115  ip,
1116  ip_len);
1117  rh->data_len = ip_len;
1118  rh->direction = GNUNET_YES;
1120  if (GNUNET_NO == do_resolve)
1121  {
1123  rh);
1124  return rh;
1125  }
1128  rh);
1130  req_tail,
1131  rh);
1132  rh->was_queued = GNUNET_YES;
1133  if (NULL != s_task)
1134  {
1136  s_task = NULL;
1137  }
1138  process_requests ();
1139  return rh;
1140 }
1141 
1142 
1148 char *
1150 {
1152 
1153  if (0 != gethostname (hostname,
1154  sizeof(hostname) - 1))
1155  {
1157  "gethostname");
1158  return NULL;
1159  }
1161  "Resolving our FQDN `%s'\n",
1162  hostname);
1163 #if HAVE_GETADDRINFO
1164  {
1165  struct addrinfo *ai;
1166  int ret;
1167  char *rval;
1168 
1169  if (0 != (ret = getaddrinfo (hostname,
1170  NULL,
1171  NULL,
1172  &ai)))
1173  {
1175  _ ("Could not resolve our FQDN: %s\n"),
1176  gai_strerror (ret));
1177  return NULL;
1178  }
1179  if (NULL != ai->ai_canonname)
1180  rval = GNUNET_strdup (ai->ai_canonname);
1181  else
1182  rval = GNUNET_strdup (hostname);
1183  freeaddrinfo (ai);
1184  return rval;
1185  }
1186 #elif HAVE_GETHOSTBYNAME2
1187  {
1188  struct hostent *host;
1189 
1190  host = gethostbyname2 (hostname,
1191  AF_INET);
1192  if (NULL == host)
1193  host = gethostbyname2 (hostname,
1194  AF_INET6);
1195  if (NULL == host)
1196  {
1198  _ ("Could not resolve our FQDN: %s\n"),
1199  hstrerror (h_errno));
1200  return NULL;
1201  }
1202  return GNUNET_strdup (host->h_name);
1203  }
1204 #elif HAVE_GETHOSTBYNAME
1205  {
1206  struct hostent *host;
1207 
1208  host = gethostbyname (hostname);
1209  if (NULL == host)
1210  {
1212  _ ("Could not resolve our FQDN: %s\n"),
1213  hstrerror (h_errno));
1214  return NULL;
1215  }
1216  return GNUNET_strdup (host->h_name);
1217  }
1218 #else
1219  /* fallback: just hope name is already FQDN */
1220  return GNUNET_strdup (hostname);
1221 #endif
1222 }
1223 
1224 
1238  void *cls)
1239 {
1241 
1242  if (0 != gethostname (hostname, sizeof(hostname) - 1))
1243  {
1245  "gethostname");
1246  return NULL;
1247  }
1249  "Resolving our hostname `%s'\n",
1250  hostname);
1252  af,
1253  timeout,
1254  callback,
1255  cls);
1256 }
1257 
1258 
1267 void
1269 {
1270  if (GNUNET_NO == rh->direction)
1272  "Asked to cancel request to resolve hostname `%s'.\n",
1273  (const char *) &rh[1]);
1274  if (NULL != rh->task)
1275  {
1277  rh->task = NULL;
1278  }
1279  if (GNUNET_NO == rh->was_transmitted)
1280  {
1281  if (GNUNET_YES == rh->was_queued)
1283  req_tail,
1284  rh);
1285  GNUNET_free (rh);
1286  check_disconnect ();
1287  return;
1288  }
1290  rh->was_transmitted = GNUNET_SYSERR; /* mark as cancelled */
1291  check_disconnect ();
1292 }
1293 
1294 
1295 /* end of resolver_api.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
static struct MHD_Response * response
Our canonical response.
static int result
Global testing status.
static char * hostname
Our hostname; we give this to all the peers we start.
static char buf[2048]
Constants for network protocols.
Functions related to doing DNS lookups.
#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:1057
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.
@ 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:304
#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.
Definition: gnunet_mq_lib.h:63
#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:683
#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.
void GNUNET_RESOLVER_disconnect()
Destroy the connection to the resolver service.
Definition: resolver_api.c:270
void GNUNET_RESOLVER_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create the connection to the resolver service.
Definition: resolver_api.c:258
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.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
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:940
void(* GNUNET_RESOLVER_HostnameCallback)(void *cls, const char *hostname)
Function called by the resolver for each hostname obtained from DNS.
char * GNUNET_RESOLVER_local_fqdn_get()
Get local fully qualified af name.
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.
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:1299
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
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:1272
#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
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:569
#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:178
static void reconnect(void)
Adjust exponential back-off and reconnect to the service.
Definition: resolver_api.c:828
static void numeric_resolution(void *cls)
We've been asked to lookup the address for a hostname and were given a valid numeric string.
Definition: resolver_api.c:652
static struct GNUNET_RESOLVER_RequestHandle * req_tail
Tail of DLL of requests.
Definition: resolver_api.c:74
static void check_disconnect()
Consider disconnecting if we have no further requests pending.
Definition: resolver_api.c:319
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:64
static int check_config()
Check that the resolver service runs on localhost (or equivalent).
Definition: resolver_api.c:191
static const char * loopback[]
Possible hostnames for "loopback".
Definition: resolver_api.c:48
static void loopback_resolution(void *cls)
We've been asked to lookup the address for a hostname and were given a variant of "loopback".
Definition: resolver_api.c:728
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:348
static void shutdown_task(void *cls)
Task executed on system shutdown.
Definition: resolver_api.c:306
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:410
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:95
static uint32_t last_request_id
ID of the last request we sent to the service.
Definition: resolver_api.c:79
static struct GNUNET_TIME_Relative backoff
How long should we wait to reconnect?
Definition: resolver_api.c:84
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:496
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.
Definition: resolver_api.c:427
static const struct GNUNET_CONFIGURATION_Handle * resolver_cfg
Configuration.
Definition: resolver_api.c:58
static struct GNUNET_RESOLVER_RequestHandle * req_head
Head of DLL of requests.
Definition: resolver_api.c:69
static struct GNUNET_SCHEDULER_Task * r_task
Task for reconnecting.
Definition: resolver_api.c:89
static void handle_lookup_timeout(void *cls)
A DNS resolution timed out.
Definition: resolver_api.c:880
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:476
#define LOG(kind,...)
Definition: resolver_api.c:33
#define LOG_STRERROR(kind, syscall)
Definition: resolver_api.c:35
static void reconnect_task(void *cls)
Now try to reconnect to the resolver service.
Definition: resolver_api.c:792
Handle to a message queue.
Definition: mq.c:87
Message handler for a specific message type.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Request for the resolver.
Definition: resolver.h:44
Handle to a request given to the resolver.
Definition: resolver_api.c:104
struct GNUNET_SCHEDULER_Task * task
Task handle for making reply callbacks in numeric lookups asynchronous, and for timeout handling.
Definition: resolver_api.c:141
GNUNET_RESOLVER_HostnameCallback name_callback
Callback if this is a reverse lookup request, otherwise NULL.
Definition: resolver_api.c:125
int was_queued
Did we add this request to the queue?
Definition: resolver_api.c:164
struct GNUNET_RESOLVER_RequestHandle * next
Next entry in DLL of requests.
Definition: resolver_api.c:108
void * cls
Closure for the callbacks.
Definition: resolver_api.c:130
int was_transmitted
Has this request been transmitted to the service? GNUNET_YES if transmitted GNUNET_NO if not transmit...
Definition: resolver_api.c:159
size_t data_len
Length of the data that follows this struct.
Definition: resolver_api.c:179
GNUNET_RESOLVER_AddressCallback addr_callback
Callback if this is an name resolution request, otherwise NULL.
Definition: resolver_api.c:119
int af
Desired address family.
Definition: resolver_api.c:146
uint32_t id
Identifies the request.
Definition: resolver_api.c:151
struct GNUNET_TIME_Absolute timeout
When should this request time out?
Definition: resolver_api.c:135
struct GNUNET_RESOLVER_RequestHandle * prev
Previous entry in DLL of requests.
Definition: resolver_api.c:113
int received_response
GNUNET_YES if a response was received
Definition: resolver_api.c:174
int direction
Desired direction (IP to name or name to IP)
Definition: resolver_api.c:169
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.