GNUnet 0.21.1
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
48static const char *loopback[] = {
49 "localhost",
50 "ip6-localnet",
51 NULL
52};
53
54
59
64static struct GNUNET_MQ_Handle *mq;
65
70
75
79static uint32_t last_request_id;
80
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
190static 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 {
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}
250
251
257void
259{
260 GNUNET_assert (NULL != cfg);
263}
264
265
269void
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
305static void
307{
308 (void) cls;
309 s_task = NULL;
312}
313
314
318static 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;
335 NULL);
336}
337
338
347static 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
397static void
398reconnect (void);
399
400
409static 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
426static 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 =
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
475static int
478{
479 (void) cls;
480 (void) msg;
481
482 /* implemented in #handle_response() for now */
483 return GNUNET_OK;
484}
485
486
495static void
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));
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);
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}
642
643
651static void
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}
718
719
727static void
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}
784
785
791static void
792reconnect_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 }
821}
822
823
827static 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);
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
879static void
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}
927
928
940GNUNET_RESOLVER_ip_get (const char *hostname,
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 }
1017 return rh;
1018}
1019
1020
1029static void
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}
1057
1058
1072GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa,
1073 socklen_t salen,
1074 int do_resolve,
1077 void *cls)
1078{
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 }
1139 return rh;
1140}
1141
1142
1148char *
1150{
1151 char hostname[GNUNET_OS_get_hostname_max_length () + 1];
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{
1240 char hostname[GNUNET_OS_get_hostname_max_length () + 1];
1241
1242 if (0 != gethostname (hostname, sizeof(hostname) - 1))
1243 {
1245 "gethostname");
1246 return NULL;
1247 }
1249 "Resolving our hostname `%s'\n",
1250 hostname);
1251 return GNUNET_RESOLVER_ip_get (hostname,
1252 af,
1253 timeout,
1254 callback,
1255 cls);
1256}
1257
1258
1267void
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);
1287 return;
1288 }
1290 rh->was_transmitted = GNUNET_SYSERR; /* mark as cancelled */
1292}
1293
1294
1295/* 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:94
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:109
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:119
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.
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.
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.
Definition: resolver_api.c:940
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.
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:981
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:1305
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:1278
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:570
#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: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 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 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 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.