GNUnet 0.24.4-talerdev.1-15-g77b7ed1a6
 
Loading...
Searching...
No Matches
gnunet-service-gns_resolver.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 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#if HAVE_LIBIDN2
29#if HAVE_IDN2_H
30#include <idn2.h>
31#elif HAVE_IDN2_IDN2_H
32#include <idn2/idn2.h>
33#endif
34#elif HAVE_LIBIDN
35#if HAVE_IDNA_H
36#include <idna.h>
37#elif HAVE_IDN_IDNA_H
38#include <idn/idna.h>
39#endif
40#endif
41#include "gnunet_util_lib.h"
42#include "gnunet_dht_service.h"
47#include "gnunet_gns_service.h"
48#include "gnunet-service-gns.h"
52
53
57#define DHT_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
58 GNUNET_TIME_UNIT_SECONDS, 60)
59
63#define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
64 GNUNET_TIME_UNIT_SECONDS, 15)
65
69#define DHT_GNS_REPLICATION_LEVEL 10
70
71
76struct AuthorityChain;
77
78
85{
90
95
100
107
112
116 unsigned int num_results;
117};
118
119
124struct GNS_ResolverHandle;
125
126
208
209
214{
219
224
228 const void *data;
229
235
239 size_t data_size;
240
244 uint32_t record_type;
245};
246
247
397
398
419
420
425
430
435
439static unsigned long long max_allowed_background_queries;
440
445
450
454static struct CacheOps *co_head;
455
459static struct CacheOps *co_tail;
460
464static int disable_cache;
465
469static const struct GNUNET_CONFIGURATION_Handle *cfg;
470
471
472/* ************************** Resolution **************************** */
473
481static char *
483 char *name)
484{
485 char *ret;
486 size_t s_len = strlen (name);
487
488 if (0 != strcmp (&name[s_len - 2],
489 ".+"))
490 return name; /* did not end in ".+" */
493 "%.*s.%s",
494 (int) (s_len - 2),
495 name,
499 return ret;
500}
501
502
509static void
511{
512 struct GNS_ResolverHandle *rh = cls;
513
514 rh->task_id = NULL;
516}
517
518
524static void
526{
527 rh->proc (rh->proc_cls,
528 0,
529 NULL);
530 GNUNET_assert (NULL == rh->task_id);
532 rh);
533}
534
535
541static void
543{
544 struct GNS_ResolverHandle *rh = cls;
545
546 rh->task_id = NULL;
547 fail_resolution (rh);
548}
549
550
556static int
558{
559 struct protoent *pe = getprotobyname (name);
560 if (pe == NULL)
561 {
563 }
564 return pe->p_proto;
565}
566
567
574static int
575resolver_getservbyname (const char *name, const char *proto)
576{
577 struct servent *se = getservbyname (name, proto);
578 if (se == NULL)
579 {
581 }
582 return se->s_port;
583}
584
585
604static char *
606{
607 const char *rp;
608 const char *dot;
609 size_t len;
610 char *ret;
611 char *srv_name;
612 char *proto_name;
613 int protocol;
614 int service;
615
616 if (0 == rh->name_resolution_pos)
617 return NULL;
618 dot = memrchr (rh->name,
619 (int) '.',
621 if (NULL == dot)
622 {
623 /* done, this was the last one */
624 len = rh->name_resolution_pos;
625 rp = rh->name;
626 rh->name_resolution_pos = 0;
627 }
628 else if ('_' == dot[1])
629 {
638 len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
639 }
640 else
641 {
642 /* advance by one label */
643 len = rh->name_resolution_pos - (dot - rh->name) - 1;
644 rp = dot + 1;
645 rh->name_resolution_pos = dot - rh->name;
646 }
647 rh->protocol = 0;
648 rh->service = 0;
649 rh->prefix = NULL;
650 ret = GNUNET_strndup (rp, len);
655 if (('_' == rh->name[0]) &&
656 (NULL != (dot = memrchr (rh->name,
657 (int) '.',
658 rh->name_resolution_pos))) &&
659 ('_' == dot[1]) &&
660 (NULL == memrchr (rh->name,
661 (int) '.',
662 dot - rh->name)))
663 {
664 srv_name = GNUNET_strndup (&rh->name[1],
665 (dot - rh->name) - 1);
666 proto_name = GNUNET_strndup (&dot[2],
667 rh->name_resolution_pos - (dot - rh->name)
668 - 2);
669 protocol = resolver_getprotobyname (proto_name);
670 if (0 == protocol)
671 {
673 _ (
674 "Protocol `%s' unknown, skipping labels as BOX retain as SBOX.\n"),
675 proto_name);
676 GNUNET_free (proto_name);
677 GNUNET_free (srv_name);
679 rh->name_resolution_pos = 0;
680 return ret;
681 }
683 proto_name);
684 if (0 == service)
685 {
687 _ (
688 "Service `%s' unknown for protocol `%s', trying as number.\n"),
689 srv_name,
690 proto_name);
691 if (1 != sscanf (srv_name, "%u", &rh->service))
692 {
694 _ (
695 "Service `%s' not a port, skipping service labels as BOX retain as SBOX.\n"),
696 srv_name);
697 GNUNET_free (proto_name);
698 GNUNET_free (srv_name);
700 rh->name_resolution_pos = 0;
701 return ret;
702 }
703 }
704 else
705 {
706 rh->service = ntohs (service);
707 }
708 rh->protocol = protocol;
709 GNUNET_free (proto_name);
710 GNUNET_free (srv_name);
711 }
718 if ((NULL != (dot = memrchr (rh->name,
719 (int) '.',
720 rh->name_resolution_pos)) && '_' == dot[1]) ||
721 ((NULL == memrchr (rh->name,
722 (int) '.',
723 rh->name_resolution_pos)) && '_' == rh->name[0]))
724 {
726 rh->name_resolution_pos = 0;
727 }
728 return ret;
729}
730
731
737static void
739{
740 struct DnsResult *pos;
741 unsigned int n;
742 unsigned int i;
743
744 n = 0;
745 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
746 n++;
747 {
748 struct GNUNET_GNSRECORD_Data rd[n];
749
750 i = 0;
751 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
752 {
753 rd[i].data = pos->data;
754 rd[i].data_size = pos->data_size;
755 rd[i].record_type = pos->record_type;
763 if (0 == pos->expiration_time)
764 {
766 rd[i].expiration_time = 0;
767 }
768 else
769 {
771 }
772 i++;
773 }
774 GNUNET_assert (i == n);
776 "Transmitting standard DNS result with %u records\n",
777 n);
778 rh->proc (rh->proc_cls,
779 n,
780 rd);
781 }
783}
784
785
795static void
797 uint64_t expiration_time,
798 uint32_t record_type,
799 size_t data_size,
800 const void *data)
801{
802 struct DnsResult *res;
803
804 res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
805 res->expiration_time = expiration_time;
806 res->data_size = data_size;
807 res->record_type = record_type;
808 res->data = &res[1];
809 GNUNET_memcpy (&res[1],
810 data,
811 data_size);
813 rh->dns_result_tail,
814 res);
815}
816
817
826static void
828 const struct sockaddr *addr,
829 socklen_t addrlen)
830{
831 struct GNS_ResolverHandle *rh = cls;
832 const struct sockaddr_in *sa4;
833 const struct sockaddr_in6 *sa6;
834
835 if (NULL == addr)
836 {
837 rh->std_resolve = NULL;
839 return;
840 }
842 "Received %u bytes of DNS IP data\n",
843 addrlen);
844 switch (addr->sa_family)
845 {
846 case AF_INET:
847 sa4 = (const struct sockaddr_in *) addr;
848 add_dns_result (rh,
849 0 /* expiration time is unknown */,
851 sizeof(struct in_addr),
852 &sa4->sin_addr);
853 break;
854
855 case AF_INET6:
856 sa6 = (const struct sockaddr_in6 *) addr;
857 add_dns_result (rh,
858 0 /* expiration time is unknown */,
860 sizeof(struct in6_addr),
861 &sa6->sin6_addr);
862 break;
863
864 default:
865 GNUNET_break (0);
866 break;
867 }
868}
869
870
876static void
877recursive_resolution (void *cls);
878
879
886static void
887start_resolver_lookup (void *cls);
888
889
898static void
900 const struct GNUNET_TUN_DnsHeader *dns,
901 size_t dns_len)
902{
903 struct GNS_ResolverHandle *rh = cls;
905 const struct GNUNET_DNSPARSER_Record *rec;
906 unsigned int rd_count;
907
908 if (NULL == dns)
909 {
910 rh->dns_request = NULL;
912 rh->task_id = NULL;
913 fail_resolution (rh);
914 return;
915 }
916 if (rh->original_dns_id != dns->id)
917 {
918 /* DNS answer, but for another query */
919 return;
920 }
921 p = GNUNET_DNSPARSER_parse ((const char *) dns,
922 dns_len);
923 if (NULL == p)
924 {
926 _ ("Failed to parse DNS response\n"));
927 return;
928 }
929
930 /* We got a result from DNS */
932 "Received DNS response for `%s' with %u answers\n",
933 rh->ac_tail->label,
934 (unsigned int) p->num_answers);
935 if ((p->num_answers > 0) &&
936 (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
938 {
939 int af;
940
942 "Got CNAME `%s' from DNS for `%s'\n",
943 p->answers[0].data.hostname,
944 rh->name);
945 if (NULL != rh->std_resolve)
946 {
948 "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
949 rh->name);
951 }
952 GNUNET_free (rh->name);
953 rh->name = GNUNET_strdup (p->answers[0].data.hostname);
954 rh->name_resolution_pos = strlen (rh->name);
955 switch (rh->record_type)
956 {
958 af = AF_INET;
959 break;
960
962 af = AF_INET6;
963 break;
964
965 default:
966 af = AF_UNSPEC;
967 break;
968 }
969 if (NULL != rh->leho)
970 add_dns_result (rh,
971 GNUNET_TIME_UNIT_HOURS.rel_value_us,
973 strlen (rh->leho),
974 rh->leho);
976 af,
979 rh);
982 rh->dns_request = NULL;
983 return;
984 }
985
986 /* convert from (parsed) DNS to (binary) GNS format! */
987 rd_count = p->num_answers + p->num_authority_records
988 + p->num_additional_records;
989 {
990 struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
991 int skip;
992 char buf[UINT16_MAX];
993 char *name_ace;
994 size_t buf_off;
995 size_t buf_start;
996
997 buf_off = 0;
998 skip = 0;
999 memset (rd,
1000 0,
1001 sizeof(rd));
1002 for (unsigned int i = 0; i < rd_count; i++)
1003 {
1004 if (i < p->num_answers)
1005 rec = &p->answers[i];
1006 else if (i < p->num_answers + p->num_authority_records)
1007 rec = &p->authority_records[i - p->num_answers];
1008 else
1009 rec = &p->additional_records[i - p->num_answers
1010 - p->num_authority_records];
1011 /* As we copied the full DNS name to 'rh->ac_tail->label', this
1012 should be the correct check to see if this record is actually
1013 a record for our label...
1014 However, DNSPARSER will convert the ACE name to UTF-8 so
1015 we must convert back.
1016 */
1017 if (IDNA_SUCCESS != idna_to_ascii_8z (rec->name,
1018 &name_ace,
1019 IDNA_ALLOW_UNASSIGNED))
1020 {
1022 _ ("Name `%s' cannot be converted to IDNA."),
1023 rec->name);
1024 continue;
1025 }
1026
1027 if (0 != strcmp (name_ace,
1028 rh->ac_tail->label))
1029 {
1031 "Dropping record `%s', does not match desired name `%s'\n",
1032 rec->name,
1033 rh->ac_tail->label);
1034 skip++;
1035 continue;
1036 }
1037 rd[i - skip].record_type = rec->type;
1039 switch (rec->type)
1040 {
1042 if (rec->data.raw.data_len != sizeof(struct in_addr))
1043 {
1044 GNUNET_break_op (0);
1045 skip++;
1046 continue;
1047 }
1048 rd[i - skip].data_size = rec->data.raw.data_len;
1049 rd[i - skip].data = rec->data.raw.data;
1050 break;
1051
1053 if (rec->data.raw.data_len != sizeof(struct in6_addr))
1054 {
1055 GNUNET_break_op (0);
1056 skip++;
1057 continue;
1058 }
1059 rd[i - skip].data_size = rec->data.raw.data_len;
1060 rd[i - skip].data = rec->data.raw.data;
1061 break;
1062
1066 buf_start = buf_off;
1067 if (GNUNET_OK !=
1069 sizeof(buf),
1070 &buf_off,
1071 rec->data.hostname))
1072 {
1073 GNUNET_break (0);
1074 skip++;
1075 continue;
1076 }
1077 rd[i - skip].data_size = buf_off - buf_start;
1078 rd[i - skip].data = &buf[buf_start];
1079 break;
1080
1082 buf_start = buf_off;
1083 if (GNUNET_OK !=
1085 sizeof(buf),
1086 &buf_off,
1087 rec->data.soa))
1088 {
1089 GNUNET_break (0);
1090 skip++;
1091 continue;
1092 }
1093 rd[i - skip].data_size = buf_off - buf_start;
1094 rd[i - skip].data = &buf[buf_start];
1095 break;
1096
1098 buf_start = buf_off;
1099 if (GNUNET_OK !=
1101 sizeof(buf),
1102 &buf_off,
1103 rec->data.mx))
1104 {
1105 GNUNET_break (0);
1106 skip++;
1107 continue;
1108 }
1109 rd[i - skip].data_size = buf_off - buf_start;
1110 rd[i - skip].data = &buf[buf_start];
1111 break;
1112
1114 buf_start = buf_off;
1115 if (GNUNET_OK !=
1117 sizeof(buf),
1118 &buf_off,
1119 rec->data.srv))
1120 {
1121 GNUNET_break (0);
1122 skip++;
1123 continue;
1124 }
1125 rd[i - skip].data_size = buf_off - buf_start;
1126 rd[i - skip].data = &buf[buf_start];
1127 break;
1128
1130 buf_start = buf_off;
1131 if (GNUNET_OK !=
1133 sizeof(buf),
1134 &buf_off,
1135 rec->data.uri))
1136 {
1137 GNUNET_break (0);
1138 skip++;
1139 continue;
1140 }
1141 rd[i - skip].data_size = buf_off - buf_start;
1142 rd[i - skip].data = &buf[buf_start];
1143 break;
1144
1145 default:
1147 _ ("Skipping record of unsupported type %d\n"),
1148 rec->type);
1149 skip++;
1150 continue;
1151 }
1152 } /* end of for all records in answer */
1153 if (NULL != rh->leho)
1154 {
1158 rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1159 rd[rd_count - skip].data = rh->leho;
1160 rd[rd_count - skip].data_size = strlen (rh->leho);
1161 skip--; /* skip one LESS */
1163 "Adding LEHO %s\n",
1164 rh->leho);
1165 }
1167 "Returning DNS response for `%s' with %u answers\n",
1168 rh->ac_tail->label,
1169 (unsigned int) (rd_count - skip));
1170 rh->proc (rh->proc_cls,
1171 rd_count - skip,
1172 rd);
1174 rh->dns_request = NULL;
1175 }
1176
1177
1179 if (NULL != rh->task_id)
1180 GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1182 rh);
1183}
1184
1185
1194static void
1196{
1197 struct AuthorityChain *ac;
1198 struct GNUNET_DNSPARSER_Query *query;
1199 struct GNUNET_DNSPARSER_Packet *p;
1200 char *dns_request;
1201 size_t dns_request_length;
1202 int ret;
1203
1204 ac = rh->ac_tail;
1205 GNUNET_assert (NULL != ac);
1207 "Starting DNS lookup for `%s'\n",
1208 ac->label);
1210 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1211 query->name = GNUNET_strdup (ac->label);
1212 query->type = rh->record_type;
1215 p->queries = query;
1216 p->num_queries = 1;
1218 UINT16_MAX);
1219 p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1220 p->flags.recursion_desired = 1;
1222 1024,
1223 &dns_request,
1224 &dns_request_length);
1225 if (GNUNET_OK != ret)
1226 {
1227 GNUNET_break (0);
1228 rh->proc (rh->proc_cls,
1229 0,
1230 NULL);
1231 GNUNET_assert (NULL == rh->task_id);
1233 rh);
1234 }
1235 else
1236 {
1237 rh->original_dns_id = p->id;
1239 GNUNET_assert (NULL == rh->dns_request);
1240 if (IDNA_SUCCESS != idna_to_unicode_8z8z (ac->label,
1241 &rh->leho,
1242 IDNA_ALLOW_UNASSIGNED))
1243 {
1244 GNUNET_break (0);
1245 rh->proc (rh->proc_cls,
1246 0,
1247 NULL);
1248 GNUNET_assert (NULL == rh->task_id);
1250 rh);
1251 }
1254 dns_request,
1255 dns_request_length,
1257 rh);
1260 rh);
1261 }
1262 if (GNUNET_SYSERR != ret)
1263 GNUNET_free (dns_request);
1265}
1266
1267
1276static void
1278 const char *rname)
1279{
1280 size_t nlen;
1281 char *res;
1282 const char *tld;
1283 struct AuthorityChain *ac;
1284 int af;
1285 struct GNUNET_CRYPTO_PublicKey zone;
1286
1288 "Handling GNS REDIRECT result `%s'\n",
1289 rname);
1290 nlen = strlen (rname);
1291 tld = GNS_get_tld (rname);
1292 if (0 == strcmp ("+", tld))
1293 {
1294 /* REDIRECT resolution continues relative to current domain */
1295 if (0 == rh->name_resolution_pos)
1296 {
1297 res = GNUNET_strndup (rname, nlen - 2);
1298 rh->name_resolution_pos = nlen - 2;
1299 }
1300 else
1301 {
1303 "%.*s.%.*s",
1304 (int) rh->name_resolution_pos,
1305 rh->name,
1306 (int) (nlen - 2),
1307 rname);
1308 rh->name_resolution_pos = strlen (res);
1309 }
1310 GNUNET_free (rh->name);
1311 rh->name = res;
1312 ac = GNUNET_new (struct AuthorityChain);
1313 ac->rh = rh;
1318 /* add AC to tail */
1320 rh->ac_tail,
1321 ac);
1323 rh);
1324 return;
1325 }
1326 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1327 {
1328 /* REDIRECT resolution continues relative to current domain */
1329 if (0 == rh->name_resolution_pos)
1330 {
1332 "%.*s",
1333 (int) (strlen (rname) - (strlen (tld) + 1)),
1334 rname);
1335 }
1336 else
1337 {
1339 "%.*s.%.*s",
1340 (int) rh->name_resolution_pos,
1341 rh->name,
1342 (int) (strlen (rname) - (strlen (tld) + 1)),
1343 rname);
1344 }
1345 rh->name_resolution_pos = strlen (res);
1346 GNUNET_free (rh->name);
1347 rh->name = res;
1348 ac = GNUNET_new (struct AuthorityChain);
1349 ac->rh = rh;
1351 ac->authority_info.gns_authority = zone;
1353 /* add AC to tail */
1355 rh->ac_tail,
1356 ac);
1358 rh);
1359 return;
1360 }
1361
1363 "Got REDIRECT `%s' from GNS for `%s'\n",
1364 rname,
1365 rh->name);
1366 if (NULL != rh->std_resolve)
1367 {
1369 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1370 rh->name);
1372 }
1373 /* name is absolute, go to DNS */
1374 GNUNET_free (rh->name);
1375 rh->name = GNUNET_strdup (rname);
1376 rh->name_resolution_pos = strlen (rh->name);
1377 switch (rh->record_type)
1378 {
1380 af = AF_INET;
1381 break;
1382
1384 af = AF_INET6;
1385 break;
1386
1387 default:
1388 af = AF_UNSPEC;
1389 break;
1390 }
1392 "Doing standard DNS lookup for `%s'\n",
1393 rh->name);
1394
1396 af,
1399 rh);
1400}
1401
1402
1411static void
1413 const char *cname)
1414{
1415 int af;
1416
1417 GNUNET_free (rh->name);
1418 rh->name = GNUNET_strdup (cname);
1419 rh->name_resolution_pos = strlen (rh->name);
1420 switch (rh->record_type)
1421 {
1423 af = AF_INET;
1424 break;
1425
1427 af = AF_INET6;
1428 break;
1429
1430 default:
1431 af = AF_UNSPEC;
1432 break;
1433 }
1435 "Doing standard DNS lookup for `%s'\n",
1436 rh->name);
1437
1439 af,
1442 rh);
1443}
1444
1445
1453static void
1455 unsigned int rd_count,
1456 const struct GNUNET_GNSRECORD_Data *rd);
1457
1458
1466static void
1468{
1469 struct GNS_ResolverHandle *rh = ac->rh;
1470
1471 if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1473 return; /* more pending and none found yet */
1475 {
1477 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1479 fail_resolution (rh);
1480 return;
1481 }
1483 return; /* already running, do not launch again! */
1484 /* recurse */
1487 "Will continue resolution using DNS to resolve `%s'\n",
1488 ac->label);
1489 GNUNET_assert (NULL == rh->task_id);
1491 rh);
1492}
1493
1494
1503static void
1505 unsigned int rd_count,
1506 const struct GNUNET_GNSRECORD_Data *rd)
1507{
1508 struct Gns2DnsPending *gp = cls;
1509 struct AuthorityChain *ac = gp->ac;
1510
1513 gp);
1514 /* enable cleanup of 'rh' handle that automatically comes after we return,
1515 and which expects 'rh' to be in the #rlh_head DLL. */
1516 if (NULL != gp->rh)
1517 {
1519 rlh_tail,
1520 gp->rh);
1521 gp->rh = NULL;
1522 }
1523 GNUNET_free (gp);
1525 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1526 rd_count);
1527 /* find suitable A/AAAA record */
1528 for (unsigned int j = 0; j < rd_count; j++)
1529 {
1530 switch (rd[j].record_type)
1531 {
1533 {
1534 struct sockaddr_in v4;
1535
1536 if (sizeof(struct in_addr) != rd[j].data_size)
1537 {
1538 GNUNET_break_op (0);
1539 continue;
1540 }
1541 memset (&v4,
1542 0,
1543 sizeof(v4));
1544 v4.sin_family = AF_INET;
1545 v4.sin_port = htons (53);
1546#if HAVE_SOCKADDR_IN_SIN_LEN
1547 v4.sin_len = (u_char) sizeof(v4);
1548#endif
1549 GNUNET_memcpy (&v4.sin_addr,
1550 rd[j].data,
1551 sizeof(struct in_addr));
1552 if (GNUNET_OK ==
1555 (const struct sockaddr *) &v4))
1557 break;
1558 }
1559
1561 {
1562 struct sockaddr_in6 v6;
1563
1564 if (sizeof(struct in6_addr) != rd[j].data_size)
1565 {
1566 GNUNET_break_op (0);
1567 continue;
1568 }
1569 /* FIXME: might want to check if we support IPv6 here,
1570 and otherwise skip this one and hope we find another */
1571 memset (&v6,
1572 0,
1573 sizeof(v6));
1574 v6.sin6_family = AF_INET6;
1575 v6.sin6_port = htons (53);
1576#if HAVE_SOCKADDR_IN_SIN_LEN
1577 v6.sin6_len = (u_char) sizeof(v6);
1578#endif
1579 GNUNET_memcpy (&v6.sin6_addr,
1580 rd[j].data,
1581 sizeof(struct in6_addr));
1582 if (GNUNET_OK ==
1585 (const struct sockaddr *) &v6))
1587 break;
1588 }
1589
1590 default:
1591 break;
1592 }
1593 }
1595}
1596
1597
1605static void
1607 const struct sockaddr *addr,
1608 socklen_t addrlen)
1609{
1610 struct Gns2DnsPending *gp = cls;
1611 struct AuthorityChain *ac = gp->ac;
1612 struct sockaddr_storage ss;
1613 struct sockaddr_in *v4;
1614 struct sockaddr_in6 *v6;
1615
1616 if (NULL == addr)
1617 {
1618 /* DNS resolution finished */
1619 if (0 == gp->num_results)
1621 "Failed to use DNS to resolve name of DNS resolver\n");
1624 gp);
1625 GNUNET_free (gp);
1627 return;
1628 }
1629 GNUNET_memcpy (&ss,
1630 addr,
1631 addrlen);
1632 switch (ss.ss_family)
1633 {
1634 case AF_INET:
1635 v4 = (struct sockaddr_in *) &ss;
1636 v4->sin_port = htons (53);
1637 gp->num_results++;
1638 break;
1639
1640 case AF_INET6:
1641 v6 = (struct sockaddr_in6 *) &ss;
1642 v6->sin6_port = htons (53);
1643 gp->num_results++;
1644 break;
1645
1646 default:
1648 "Unsupported AF %d\n",
1649 ss.ss_family);
1650 return;
1651 }
1652 if (GNUNET_OK ==
1654 (struct sockaddr *) &ss))
1656}
1657
1658
1665static void
1672
1673
1680static void
1682 const struct GNUNET_GNSRECORD_Data *rd)
1683{
1684 char *cname;
1685 size_t off;
1686
1687 off = 0;
1689 rd->data_size,
1690 &off);
1691 if ((NULL == cname) ||
1692 (off != rd->data_size))
1693 {
1694 GNUNET_break_op (0); /* record not well-formed */
1695 GNUNET_free (cname);
1696 fail_resolution (rh);
1697 return;
1698 }
1700 cname);
1701 GNUNET_free (cname);
1702}
1703
1704
1711static void
1713 const struct GNUNET_GNSRECORD_Data *rd)
1714{
1715 struct AuthorityChain *ac;
1716 struct GNUNET_CRYPTO_PublicKey auth;
1717
1718 /* delegation to another zone */
1720 rd->data_size,
1721 rd->record_type,
1722 &auth))
1723 {
1724 GNUNET_break_op (0);
1725 fail_resolution (rh);
1726 return;
1727 }
1728 /* expand authority chain */
1729 ac = GNUNET_new (struct AuthorityChain);
1730 ac->rh = rh;
1732 ac->authority_info.gns_authority = auth;
1734 /* add AC to tail */
1736 rh->ac_tail,
1737 ac);
1738 /* recurse */
1740 rh);
1741}
1742
1743
1754static int
1756 unsigned int rd_count,
1757 const struct GNUNET_GNSRECORD_Data *rd)
1758{
1759 struct AuthorityChain *ac;
1760 const char *tld;
1761 char *ns;
1762
1763 ns = NULL;
1764 /* expand authority chain */
1765 ac = GNUNET_new (struct AuthorityChain);
1766 ac->rh = rh;
1768
1769 for (unsigned int i = 0; i < rd_count; i++)
1770 {
1771 char *ip;
1772 char *n;
1773 struct Gns2DnsPending *gp;
1774 struct GNUNET_CRYPTO_PublicKey zone;
1775 struct sockaddr_in v4;
1776 struct sockaddr_in6 v6;
1777
1778 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1779 {
1784 GNUNET_free (ns);
1785 GNUNET_free (ac);
1786 return GNUNET_SYSERR;
1787 }
1788 n = GNUNET_strdup ((const char*) rd[i].data);
1789 if (strlen (n) + 1 >= rd[i].data_size)
1790 {
1791 GNUNET_break_op (0);
1792 continue;
1793 }
1794 ip = GNUNET_strdup (rd[i].data + strlen (n) + 1);
1795 /* resolve 'ip' to determine the IP(s) of the DNS
1796 resolver to use for lookup of 'ns' */
1797 if (NULL != ns)
1798 {
1799 if (0 != strcasecmp (ns,
1800 n))
1801 {
1802 /* NS values must all be the same for all GNS2DNS records,
1803 anything else leads to insanity */
1804 GNUNET_break_op (0);
1805 GNUNET_free (n);
1806 GNUNET_free (ip);
1807 continue;
1808 }
1809 GNUNET_free (n);
1810 }
1811 else
1812 {
1813 ns = n;
1814 }
1815
1816 /* check if 'ip' is already an IPv4/IPv6 address */
1817 if ((1 == inet_pton (AF_INET,
1818 ip,
1819 &v4)) ||
1820 (1 == inet_pton (AF_INET6,
1821 ip,
1822 &v6)))
1823 {
1827 ip));
1829 GNUNET_free (ip);
1830 continue;
1831 }
1832 tld = GNS_get_tld (ip);
1833 if ((0 != strcmp (tld, "+")) &&
1834 (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1835 {
1836 /* 'ip' is a DNS name */
1837 gp = GNUNET_new (struct Gns2DnsPending);
1838 gp->ac = ac;
1841 gp);
1843 AF_UNSPEC,
1846 gp);
1847 GNUNET_free (ip);
1848 continue;
1849 }
1850 /* 'ip' should be a GNS name */
1851 gp = GNUNET_new (struct Gns2DnsPending);
1852 gp->ac = ac;
1855 gp);
1856 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1857 if (0 == strcmp (tld, "+"))
1858 {
1859 ip = translate_dot_plus (rh,
1860 ip);
1861 tld = GNS_get_tld (ip);
1862 if (GNUNET_OK !=
1864 &zone))
1865 {
1866 GNUNET_break_op (0);
1867 GNUNET_free (ip);
1868 continue;
1869 }
1870 }
1871 gp->rh->authority_zone = zone;
1873 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1874 ip,
1875 ns);
1876 gp->rh->name = ip;
1877 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1879 gp->rh->proc_cls = gp;
1882 gp->rh->loop_limiter = rh->loop_limiter + 1;
1883 gp->rh->loop_threshold = rh->loop_threshold;
1884 gp->rh->task_id
1886 gp->rh);
1887 } /* end 'for all records' */
1888
1889 if (NULL == ns)
1890 {
1891 /* not a single GNS2DNS record found */
1892 GNUNET_free (ac);
1893 return GNUNET_SYSERR;
1894 }
1896 strcpy (ac->authority_info.dns_authority.name,
1897 ns);
1898 /* for DNS recursion, the label is the full DNS name,
1899 created from the remainder of the GNS name and the
1900 name in the NS record */
1901 GNUNET_asprintf (&ac->label,
1902 "%.*s%s%s",
1903 (int) rh->name_resolution_pos,
1904 rh->name,
1905 (0 != rh->name_resolution_pos) ? "." : "",
1906 ns);
1907 GNUNET_free (ns);
1908
1909 {
1910 /* the GNS name is UTF-8 and may include multibyte chars.
1911 * We have to convert the combined name to a DNS-compatible IDNA.
1912 */
1913 char *tmp = ac->label;
1914
1915 if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1916 &ac->label,
1917 IDNA_ALLOW_UNASSIGNED))
1918 {
1920 _ ("Name `%s' cannot be converted to IDNA."),
1921 tmp);
1922 GNUNET_free (tmp);
1923 GNUNET_free (ac);
1924 return GNUNET_SYSERR;
1925 }
1926 GNUNET_free (tmp);
1927 }
1928
1930 rh->ac_tail,
1931 ac);
1932 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1933 {
1935 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1936 ac->label);
1937 GNUNET_free (ac->label);
1938 GNUNET_free (ac);
1939 return GNUNET_SYSERR;
1940 }
1942 return GNUNET_OK;
1943}
1944
1945
1946static void
1948 unsigned int rd_count,
1949 const struct GNUNET_GNSRECORD_Data *rd)
1950{
1951 struct GNS_ResolverHandle *rh = cls;
1952 char *cname;
1953 char scratch[UINT16_MAX];
1954 size_t scratch_off;
1955 size_t scratch_start;
1956 size_t off;
1957 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1958 unsigned int rd_off;
1959
1961 "Resolution succeeded for `%s' in zone %s, got %u records\n",
1962 rh->ac_tail->label,
1964 rd_count);
1965 if (0 == rd_count)
1966 {
1968 _ ("GNS lookup failed (zero records found for `%s')\n"),
1969 rh->name);
1970 fail_resolution (rh);
1971 return;
1972 }
1973
1974 if (0 == rh->name_resolution_pos)
1975 {
1976 /* top-level match, are we done yet? */
1977 if ((rd_count > 0) &&
1980 {
1981 off = 0;
1983 rd[0].data_size,
1984 &off);
1985 if ((NULL == cname) ||
1986 (off != rd[0].data_size))
1987 {
1988 GNUNET_break_op (0);
1989 GNUNET_free (cname);
1990 fail_resolution (rh);
1991 return;
1992 }
1994 cname);
1995 GNUNET_free (cname);
1996 return;
1997 }
1998 if ((rd_count > 0) &&
2001 {
2003 rd[0].data);
2004 return;
2005 }
2006
2007
2008 /* If A/AAAA was requested,
2009 * but we got a GNS2DNS record */
2010 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2012 {
2013 for (unsigned int i = 0; i < rd_count; i++)
2014 {
2015 switch (rd[i].record_type)
2016 {
2018 {
2019 /* delegation to DNS */
2021 "Found GNS2DNS record, delegating to DNS!\n");
2022 if (GNUNET_OK ==
2024 rd_count,
2025 rd))
2026 return;
2027 else
2028 goto fail;
2029 }
2030
2031 default:
2032 break;
2033 } /* end: switch */
2034 } /* end: for rd */
2035 } /* end: name_resolution_pos */
2036 /* convert relative names in record values to absolute names,
2037 using 'scratch' array for memory allocations */
2038 scratch_off = 0;
2039 rd_off = 0;
2040 for (unsigned int i = 0; i < rd_count; i++)
2041 {
2042 GNUNET_assert (rd_off <= i);
2043 if ((((0 != rh->protocol) &&
2044 (0 != rh->service)) || (NULL != rh->prefix)) &&
2049 continue;
2050 /* we _only_ care about boxed records */
2051
2052 GNUNET_assert (rd_off < rd_count);
2053 rd_new[rd_off] = rd[i];
2054 /* Check if the embedded name(s) end in "+", and if so,
2055 replace the "+" with the zone at "ac_tail", changing the name
2056 to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2057 so we can free it afterwards. */
2058 switch (rd[i].record_type)
2059 {
2061 {
2062 char *rname;
2063 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2064 rname = translate_dot_plus (rh, rname);
2065 GNUNET_break (NULL != rname);
2066 scratch_start = scratch_off;
2067 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2068 scratch_off += strlen (rname) + 1;
2069 GNUNET_assert (rd_off < rd_count);
2070 rd_new[rd_off].data = &scratch[scratch_start];
2071 rd_new[rd_off].data_size = scratch_off - scratch_start;
2072 rd_off++;
2073 GNUNET_free (rname);
2074 }
2075 break;
2076
2078 {
2079 char *cname_tmp;
2080
2081 off = 0;
2082 cname_tmp = GNUNET_DNSPARSER_parse_name (rd[i].data,
2083 rd[i].data_size,
2084 &off);
2085 if ((NULL == cname_tmp) ||
2086 (off != rd[i].data_size))
2087 {
2088 GNUNET_break_op (0); /* record not well-formed */
2089 }
2090 else
2091 {
2092 cname_tmp = translate_dot_plus (rh, cname_tmp);
2093 GNUNET_break (NULL != cname_tmp);
2094 scratch_start = scratch_off;
2095 if (GNUNET_OK !=
2097 sizeof(scratch),
2098 &scratch_off,
2099 cname_tmp))
2100 {
2101 GNUNET_break (0);
2102 }
2103 else
2104 {
2105 GNUNET_assert (rd_off < rd_count);
2106 rd_new[rd_off].data = &scratch[scratch_start];
2107 rd_new[rd_off].data_size = scratch_off - scratch_start;
2108 rd_off++;
2109 }
2110 }
2111 GNUNET_free (cname_tmp);
2112 }
2113 break;
2114
2116 {
2117 struct GNUNET_DNSPARSER_SoaRecord *soa;
2118
2119 off = 0;
2121 rd[i].data_size,
2122 &off);
2123 if ((NULL == soa) ||
2124 (off != rd[i].data_size))
2125 {
2126 GNUNET_break_op (0); /* record not well-formed */
2127 }
2128 else
2129 {
2130 soa->mname = translate_dot_plus (rh, soa->mname);
2131 soa->rname = translate_dot_plus (rh, soa->rname);
2132 scratch_start = scratch_off;
2133 if (GNUNET_OK !=
2135 sizeof(scratch),
2136 &scratch_off,
2137 soa))
2138 {
2139 GNUNET_break (0);
2140 }
2141 else
2142 {
2143 GNUNET_assert (rd_off < rd_count);
2144 rd_new[rd_off].data = &scratch[scratch_start];
2145 rd_new[rd_off].data_size = scratch_off - scratch_start;
2146 rd_off++;
2147 }
2148 }
2149 if (NULL != soa)
2151 }
2152 break;
2153
2155 {
2156 struct GNUNET_DNSPARSER_MxRecord *mx;
2157
2158 off = 0;
2160 rd[i].data_size,
2161 &off);
2162 if ((NULL == mx) ||
2163 (off != rd[i].data_size))
2164 {
2165 GNUNET_break_op (0); /* record not well-formed */
2166 }
2167 else
2168 {
2169 mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2170 scratch_start = scratch_off;
2171 if (GNUNET_OK !=
2173 sizeof(scratch),
2174 &scratch_off,
2175 mx))
2176 {
2177 GNUNET_break (0);
2178 }
2179 else
2180 {
2181 GNUNET_assert (rd_off < rd_count);
2182 rd_new[rd_off].data = &scratch[scratch_start];
2183 rd_new[rd_off].data_size = scratch_off - scratch_start;
2184 rd_off++;
2185 }
2186 }
2187 if (NULL != mx)
2189 }
2190 break;
2191
2193 {
2194 struct GNUNET_DNSPARSER_SrvRecord *srv;
2195
2196 off = 0;
2198 rd[i].data_size,
2199 &off);
2200 if ((NULL == srv) ||
2201 (off != rd[i].data_size))
2202 {
2203 GNUNET_break_op (0); /* record not well-formed */
2204 }
2205 else
2206 {
2207 srv->target = translate_dot_plus (rh, srv->target);
2208 scratch_start = scratch_off;
2209 if (GNUNET_OK !=
2211 sizeof(scratch),
2212 &scratch_off,
2213 srv))
2214 {
2215 GNUNET_break (0);
2216 }
2217 else
2218 {
2219 GNUNET_assert (rd_off < rd_count);
2220 rd_new[rd_off].data = &scratch[scratch_start];
2221 rd_new[rd_off].data_size = scratch_off - scratch_start;
2222 rd_off++;
2223 }
2224 }
2225 if (NULL != srv)
2227 }
2228 break;
2229
2231 {
2233
2234 off = 0;
2236 rd[i].data_size,
2237 &off);
2238 if ((NULL == uri) ||
2239 (off != rd[i].data_size))
2240 {
2242 _ ("Failed to deserialize URI record with target\n"));
2243 GNUNET_break_op (0); /* record not well-formed */
2244 }
2245 else
2246 {
2247 scratch_start = scratch_off;
2248 if (GNUNET_OK !=
2250 sizeof(scratch),
2251 &scratch_off,
2252 uri))
2253 {
2254 GNUNET_break (0);
2255 }
2256 else
2257 {
2258 GNUNET_assert (rd_off < rd_count);
2259 rd_new[rd_off].data = &scratch[scratch_start];
2260 rd_new[rd_off].data_size = scratch_off - scratch_start;
2261 rd_off++;
2262 }
2263 }
2264 if (NULL != uri)
2266 }
2267 break;
2268
2271 {
2273 if (rd[i].data_size < sizeof(uint32_t))
2274 {
2275 GNUNET_break_op (0);
2276 break;
2277 }
2278 if (GNUNET_OK !=
2280 rd[i].data_size,
2281 rd[i].record_type,
2282 &pubkey))
2283 {
2284 GNUNET_break_op (0);
2285 break;
2286 }
2287 rd_off++;
2288 if (rd[i].record_type != rh->record_type)
2289 {
2290 /* try to resolve "@" */
2291 struct AuthorityChain *ac;
2292
2293 ac = GNUNET_new (struct AuthorityChain);
2294 ac->rh = rh;
2299 rh->ac_tail,
2300 ac);
2302 rh);
2303 return;
2304 }
2305 }
2306 break;
2307
2309 {
2310 /* delegation to DNS */
2312 {
2313 rd_off++;
2314 break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2315 }
2317 "Found GNS2DNS record, delegating to DNS!\n");
2318 if (GNUNET_OK ==
2320 rd_count,
2321 rd))
2322 return;
2323 else
2324 goto fail;
2325 }
2326
2328 {
2329 /* unbox SRV/TLSA records if a specific one was requested */
2330 if ((0 != rh->protocol) &&
2331 (0 != rh->service) &&
2332 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2333 {
2334 const struct GNUNET_GNSRECORD_BoxRecord *box;
2335
2336 box = rd[i].data;
2338 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2339 ntohs (box->protocol), ntohs (box->service),
2340 rh->protocol, rh->service);
2341 if ((ntohs (box->protocol) == rh->protocol) &&
2342 (ntohs (box->service) == rh->service))
2343 {
2344 /* Box matches, unbox! */
2345 GNUNET_assert (rd_off < rd_count);
2346 rd_new[rd_off].record_type = ntohl (box->record_type);
2347 rd_new[rd_off].data_size -= sizeof(struct
2349 rd_new[rd_off].data = &box[1];
2350 rd_off++;
2351 }
2352 }
2353 else
2354 {
2355 /* no specific protocol/service specified, preserve all BOX
2356 records (for modern, GNS-enabled applications) */
2357 rd_off++;
2358 }
2359 break;
2360 }
2362 {
2363 /* unbox SBOX records if a specific one was requested */
2364 if ((rh->prefix != NULL) &&
2365 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2366 {
2367 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2368 const char *prefix;
2369 size_t prefix_len;
2370
2371 box = rd[i].data;
2372 prefix = rd[i].data + sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
2373 prefix_len = strnlen (
2374 prefix,
2375 rd[i].data_size - sizeof(struct GNUNET_GNSRECORD_SBoxRecord)) + 1;
2376 if (prefix_len - 1 >= rd[i].data_size - sizeof(struct
2378 {
2380 "SBOX record with invalid prefix length, maybe not null-terminated\n");
2381 continue;
2382 }
2384 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2385 prefix, rh->prefix);
2386 if (strcmp (rh->prefix, prefix) == 0)
2387 {
2388 /* Box matches, unbox! */
2389 GNUNET_assert (rd_off < rd_count);
2390 rd_new[rd_off].record_type = ntohl (box->record_type);
2391 rd_new[rd_off].data_size -= sizeof(struct
2393 + prefix_len;
2394 rd_new[rd_off].data = rd[i].data
2395 + sizeof(struct GNUNET_GNSRECORD_SBoxRecord)
2396 + prefix_len;
2397 rd_off++;
2398 }
2399 }
2400 else
2401 {
2403 _ (
2404 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2405 rh->name);
2406 /* no specific protocol/service specified, preserve all SBOX
2407 records (for modern, GNS-enabled applications) */
2408 rd_off++;
2409 }
2410 break;
2411 }
2412 default:
2413 rd_off++;
2414 break;
2415 } /* end: switch */
2416 } /* end: for rd_count */
2417
2418 GNUNET_free (rh->prefix);
2419 rh->prefix = NULL;
2420
2421 /* yes, we are done, return result */
2423 "Returning GNS response for `%s' with %u answers\n",
2424 rh->ac_tail->label,
2425 rd_off);
2426 rh->proc (rh->proc_cls,
2427 rd_off,
2428 rd_new);
2430 rh);
2431 return;
2432 }
2433
2434 switch (rd[0].record_type)
2435 {
2437 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2439 &rd[0]);
2440 return;
2441
2443 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2445 &rd[0]);
2446 return;
2447
2450 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2452 &rd[0]);
2453 return;
2454
2456 if (GNUNET_OK ==
2458 rd_count,
2459 rd))
2460 return;
2461 break;
2462 default:
2464 return;
2466 _ ("Unable to process critical delegation record\n"));
2467 break;
2468 }
2469fail:
2471 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2472 fail_resolution (rh);
2473}
2474
2475
2484static void
2486 int32_t success,
2487 const char *emsg)
2488{
2489 struct CacheOps *co = cls;
2490
2491 co->namecache_qe_cache = NULL;
2492 if (GNUNET_OK != success)
2494 _ ("Failed to cache GNS resolution: %s\n"),
2495 emsg);
2497 co_tail,
2498 co);
2499 GNUNET_free (co);
2500}
2501
2502
2521static void
2523 struct GNUNET_TIME_Absolute exp,
2524 const struct GNUNET_HashCode *key,
2525 const struct GNUNET_PeerIdentity *trunc_peer,
2526 const struct GNUNET_DHT_PathElement *get_path,
2527 unsigned int get_path_length,
2528 const struct GNUNET_DHT_PathElement *put_path,
2529 unsigned int put_path_length,
2531 size_t size,
2532 const void *data)
2533{
2534 struct GNS_ResolverHandle *rh = cls;
2535 struct AuthorityChain *ac = rh->ac_tail;
2536 const struct GNUNET_GNSRECORD_Block *block;
2537 struct CacheOps *co;
2538
2539 (void) exp;
2540 (void) key;
2541 (void) get_path;
2542 (void) get_path_length;
2543 (void) put_path;
2544 (void) put_path_length;
2545 (void) type;
2547 rh->get_handle = NULL;
2549 rh->dht_heap_node = NULL;
2551 "Handling response from the DHT\n");
2552 if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2553 {
2554 /* how did this pass DHT block validation!? */
2555 GNUNET_break (0);
2556 fail_resolution (rh);
2557 return;
2558 }
2559 block = data;
2561 {
2562 /* how did this pass DHT block validation!? */
2563 GNUNET_break (0);
2564 fail_resolution (rh);
2565 return;
2566 }
2568 "Decrypting DHT block of size %llu for `%s', expires %s\n",
2569 (unsigned long long) GNUNET_GNSRECORD_block_get_size (block),
2570 rh->name,
2572 if (GNUNET_OK !=
2575 ac->label,
2577 rh))
2578 {
2579 GNUNET_break_op (0); /* block was ill-formed */
2580 fail_resolution (rh);
2581 return;
2582 }
2585 rel_value_us)
2586 {
2588 "Received expired block from the DHT, will not cache it.\n");
2589 return;
2590 }
2592 return;
2593 /* Cache well-formed blocks */
2595 "Caching response from the DHT in namecache\n");
2596 co = GNUNET_new (struct CacheOps);
2598 block,
2599 &
2601 co);
2603 co_tail,
2604 co);
2605}
2606
2607
2614static void
2616 const struct GNUNET_HashCode *query)
2617{
2618 struct GNS_ResolverHandle *rx;
2619
2620 GNUNET_assert (NULL == rh->get_handle);
2623 query,
2626 NULL, 0,
2627 &handle_dht_response, rh);
2629 rh,
2631 abs_value_us);
2634 {
2635 /* fail longest-standing DHT request */
2637 rx->dht_heap_node = NULL;
2638 GNUNET_assert (NULL != rx);
2639 fail_resolution (rx);
2640 }
2641}
2642
2643
2652static void
2654 unsigned int rd_count,
2655 const struct GNUNET_GNSRECORD_Data *rd)
2656{
2657 struct GNS_ResolverHandle *rh = cls;
2658
2659 if (0 == rd_count)
2661 _ ("GNS namecache returned empty result for `%s'\n"),
2662 rh->name);
2664 rd_count,
2665 rd);
2666}
2667
2668
2675static void
2677 const struct GNUNET_GNSRECORD_Block *block)
2678{
2679 struct GNS_ResolverHandle *rh = cls;
2680 struct AuthorityChain *ac = rh->ac_tail;
2681 const char *label = ac->label;
2682 const struct GNUNET_CRYPTO_PublicKey *auth =
2684 struct GNUNET_HashCode query;
2685
2686 GNUNET_assert (NULL != rh->namecache_qe);
2687 rh->namecache_qe = NULL;
2688 if (NULL == block)
2690 "No block found\n");
2691 else
2693 "Got block with expiration %s\n",
2696 if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2698 (ac != rh->ac_head))) &&
2699 ((NULL == block) ||
2702 rel_value_us)))
2703 {
2704 /* namecache knows nothing; try DHT lookup */
2706 label,
2707 &query);
2709 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2710 ac->label,
2712 GNUNET_h2s (&query));
2713 start_dht_request (rh, &query);
2714 return;
2715 }
2716
2717 if ((NULL == block) ||
2720 rel_value_us))
2721 {
2722 /* DHT not permitted and no local result, fail */
2724 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2725 ac->label,
2727 fail_resolution (rh);
2728 return;
2729 }
2731 "Received result from namecache for label `%s'\n",
2732 ac->label);
2733
2734 if (GNUNET_OK !=
2736 auth,
2737 label,
2739 rh))
2740 {
2741 GNUNET_break_op (0); /* block was ill-formed */
2742 /* try DHT instead */
2744 label,
2745 &query);
2747 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2748 ac->label,
2750 GNUNET_h2s (&query));
2751 start_dht_request (rh, &query);
2752 return;
2753 }
2754}
2755
2756
2762static void
2764{
2765 struct AuthorityChain *ac = rh->ac_tail;
2766 struct GNUNET_HashCode query;
2767
2769 "Starting GNS resolution for `%s' in zone %s\n",
2770 ac->label,
2773 ac->label,
2774 &query);
2776 {
2777 rh->namecache_qe
2779 &query,
2781 rh);
2782 GNUNET_assert (NULL != rh->namecache_qe);
2783 }
2784 else
2785 {
2787 &query);
2788 }
2789}
2790
2791
2798static void
2800 int is_valid)
2801{
2802 struct GNS_ResolverHandle *rh = cls;
2803 struct AuthorityChain *ac = rh->ac_tail;
2804
2805 rh->rev_check = NULL;
2806 if (GNUNET_YES != is_valid)
2807 {
2809 _ ("Zone %s was revoked, resolution fails\n"),
2812 return;
2813 }
2815}
2816
2817
2823static void
2825{
2826 struct AuthorityChain *ac = rh->ac_tail;
2827
2829 "Starting revocation check for zone %s\n",
2834 rh);
2835 GNUNET_assert (NULL != rh->rev_check);
2836}
2837
2838
2839static void
2841{
2842 struct GNS_ResolverHandle *rh = cls;
2843
2844 rh->task_id = NULL;
2845 if (rh->loop_threshold < rh->loop_limiter++)
2846 {
2848 "Encountered unbounded recursion resolving `%s'\n",
2849 rh->name);
2850 fail_resolution (rh);
2851 return;
2852 }
2853 if (GNUNET_YES == rh->ac_tail->gns_authority)
2855 else
2857}
2858
2859
2860static void
2862{
2863 struct GNS_ResolverHandle *rh = cls;
2864 struct AuthorityChain *ac;
2865 struct in_addr v4;
2866 struct in6_addr v6;
2867
2868 rh->task_id = NULL;
2869 if (1 == inet_pton (AF_INET,
2870 rh->name,
2871 &v4))
2872 {
2873 /* name is IPv4 address, pretend it's an A record */
2875
2876 rd.data = &v4;
2877 rd.data_size = sizeof(v4);
2878 rd.expiration_time = UINT64_MAX;
2880 rd.flags = 0;
2881 rh->proc (rh->proc_cls,
2882 1,
2883 &rd);
2884 GNUNET_assert (NULL == rh->task_id);
2886 rh);
2887 return;
2888 }
2889 if (1 == inet_pton (AF_INET6,
2890 rh->name,
2891 &v6))
2892 {
2893 /* name is IPv6 address, pretend it's an AAAA record */
2895
2896 rd.data = &v6;
2897 rd.data_size = sizeof(v6);
2898 rd.expiration_time = UINT64_MAX;
2900 rd.flags = 0;
2901 rh->proc (rh->proc_cls,
2902 1,
2903 &rd);
2904 GNUNET_assert (NULL == rh->task_id);
2906 rh);
2907 return;
2908 }
2909
2910 ac = GNUNET_new (struct AuthorityChain);
2911 ac->rh = rh;
2913 if (NULL == ac->label)
2914 /* name was just the "TLD", so we default to label
2915 #GNUNET_GNS_EMPTY_LABEL_AT */
2920 rh->ac_tail,
2921 ac);
2923 rh);
2924}
2925
2926
2941struct GNS_ResolverHandle *
2943 uint32_t record_type,
2944 const char *name,
2946 uint16_t recursion_depth_limit,
2948 void *proc_cls)
2949{
2950 struct GNS_ResolverHandle *rh;
2951
2953 "Starting lookup for `%s'\n",
2954 name);
2955 rh = GNUNET_new (struct GNS_ResolverHandle);
2957 rlh_tail,
2958 rh);
2959 rh->authority_zone = *zone;
2960 rh->proc = proc;
2961 rh->proc_cls = proc_cls;
2962 rh->options = options;
2964 rh->name = GNUNET_strdup (name);
2965 rh->name_resolution_pos = strlen (name);
2966 rh->loop_threshold = recursion_depth_limit;
2968 rh);
2969 return rh;
2970}
2971
2972
2978void
2980{
2981 struct DnsResult *dr;
2982 struct AuthorityChain *ac;
2983
2985 rlh_tail,
2986 rh);
2987 if (NULL != rh->dns_request)
2988 {
2990 rh->dns_request = NULL;
2991 }
2992 while (NULL != (ac = rh->ac_head))
2993 {
2995 rh->ac_tail,
2996 ac);
2997 if (GNUNET_NO == ac->gns_authority)
2998 {
2999 struct Gns2DnsPending *gp;
3000
3001 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
3002 {
3005 gp);
3006 if (NULL != gp->rh)
3007 {
3008 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
3009 using GNS_resolver_lookup_cancel here, we need to
3010 add it first... */
3012 rlh_tail,
3013 gp->rh);
3014 GNUNET_assert (NULL == gp->rh->task_id);
3017 gp->rh);
3018 gp->rh = NULL;
3019 }
3020 if (NULL != gp->dns_rh)
3021 {
3023 gp->dns_rh = NULL;
3024 }
3025 GNUNET_free (gp);
3026 }
3028 }
3029 GNUNET_free (ac->label);
3030 GNUNET_free (ac);
3031 }
3032 if (NULL != rh->task_id)
3033 {
3035 rh->task_id = NULL;
3036 }
3037 if (NULL != rh->get_handle)
3038 {
3040 rh->get_handle = NULL;
3041 }
3042 if (NULL != rh->dht_heap_node)
3043 {
3045 rh->dht_heap_node = NULL;
3046 }
3047 if (NULL != rh->namecache_qe)
3048 {
3050 rh->namecache_qe = NULL;
3051 }
3052 if (NULL != rh->rev_check)
3053 {
3055 rh->rev_check = NULL;
3056 }
3057 if (NULL != rh->std_resolve)
3058 {
3060 "Canceling standard DNS resolution\n");
3062 rh->std_resolve = NULL;
3063 }
3064 while (NULL != (dr = rh->dns_result_head))
3065 {
3068 dr);
3069 GNUNET_free (dr);
3070 }
3071 if (NULL != rh->prefix)
3072 {
3074 rh->prefix = NULL;
3075 }
3076 GNUNET_free (rh->leho);
3077 GNUNET_free (rh->name);
3078 GNUNET_free (rh);
3079}
3080
3081
3082/* ***************** Resolver initialization ********************* */
3083
3084
3093void
3095 struct GNUNET_DHT_Handle *dht,
3096 const struct GNUNET_CONFIGURATION_Handle *c,
3097 unsigned long long max_bg_queries)
3098{
3099 cfg = c;
3101 dht_handle = dht;
3104 max_allowed_background_queries = max_bg_queries;
3106 "namecache",
3107 "DISABLE");
3110 "Namecache disabled\n");
3111}
3112
3113
3117void
3119{
3120 struct GNS_ResolverHandle *rh;
3121 struct CacheOps *co;
3122
3123 /* abort active resolutions */
3124 while (NULL != (rh = rlh_head))
3125 {
3126 rh->proc (rh->proc_cls,
3127 0,
3128 NULL);
3130 }
3131 while (NULL != (co = co_head))
3132 {
3134 co_tail,
3135 co);
3137 GNUNET_free (co);
3138 }
3140 dht_lookup_heap = NULL;
3141 dht_handle = NULL;
3142 namecache_handle = NULL;
3143}
3144
3145
3146/* end of gnunet-service-gns_resolver.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
static size_t strnlen(const char *s, size_t n)
#define memrchr(s, c, n)
Definition compat.h:49
uint16_t GNUNET_GNS_protocol_name_to_number(const char *name)
#define GNUNET_GNSRECORD_TYPE_BOX
Box record.
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Delegation to DNS.
#define GNUNET_GNSRECORD_TYPE_REDIRECT
Redirection record.
#define GNUNET_GNSRECORD_TYPE_LEHO
GNS legacy hostname.
#define GNUNET_GNSRECORD_TYPE_SBOX
SBox record.
#define GNUNET_GNSRECORD_TYPE_PKEY
WARNING: This header is generated! In order to add GNS record types, you must register them in GANA,...
#define GNUNET_GNSRECORD_TYPE_EDKEY
GNS zone delegation (EDKEY)
uint16_t GNUNET_GNS_service_port_name_to_number(const char *name)
static int ret
Final status code.
Definition gnunet-arm.c:93
static int prefix
If printing the value of PREFIX has been requested.
static struct GNUNET_DHT_Handle * dht
Handle to the DHT.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static char * name
Name (label) of the records to list.
static struct GNUNET_NAMECACHE_Handle * ns
Handle to the namecache.
static struct GNUNET_CRYPTO_PublicKey pubkey
Public key of the zone to look in.
static unsigned int rd_count
Number of records for currently parsed set.
static char * res
Currently read line or NULL on EOF.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static uint32_t type
Type string converted to DNS type value.
static size_t data_size
Number of bytes in data.
static uint8_t proto
Protocol to use.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static char * rp
Relying party.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNUNET_NotificationContext * nc
Notification context for broadcasting to monitors.
const char * GNS_get_tld(const char *name)
Obtain the TLD of the given name.
GNU Name System (main service)
#define DNS_LOOKUP_TIMEOUT
Default timeout for DNS lookups.
static int disable_cache
Use namecache.
void GNS_resolver_init(struct GNUNET_NAMECACHE_Handle *nc, struct GNUNET_DHT_Handle *dht, const struct GNUNET_CONFIGURATION_Handle *c, unsigned long long max_bg_queries)
Initialize the resolver.
static unsigned long long max_allowed_background_queries
Maximum amount of parallel queries to the DHT.
static void start_dht_request(struct GNS_ResolverHandle *rh, const struct GNUNET_HashCode *query)
Initiate a DHT query for a set of GNS records.
static void handle_gns2dns_ip(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Function called by the resolver for each address obtained from DNS.
static void handle_revocation_result(void *cls, int is_valid)
Function called with the result from a revocation check.
static int resolver_getprotobyname(const char *name)
Function called to receive the protocol number for a service.
static void recursive_pkey_resolution(struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
We found a PKEY record, perform recursive resolution on it.
static void recursive_resolution(void *cls)
Task scheduled to continue with the resolution process.
static void start_resolver_lookup(void *cls)
Begin the resolution process from 'name', starting with the identification of the zone specified by '...
static struct GNS_ResolverHandle * rlh_tail
Tail of resolver lookup list.
static void transmit_lookup_dns_result(struct GNS_ResolverHandle *rh)
Gives the cumulative result obtained to the callback and clean up the request.
static char * translate_dot_plus(struct GNS_ResolverHandle *rh, char *name)
Expands a name ending in .
static void recursive_gns_resolution_namecache(struct GNS_ResolverHandle *rh)
Lookup tail of our authority chain in the namecache.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Global configuration.
static void fail_resolution(struct GNS_ResolverHandle *rh)
Function called to asynchronously fail a resolution.
static void handle_namecache_block_response(void *cls, const struct GNUNET_GNSRECORD_Block *block)
Process a record that was stored in the namecache.
static void recursive_cname_resolution(struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
We found a CNAME record, perform recursive resolution on it.
static void handle_gns_redirect_result(struct GNS_ResolverHandle *rh, const char *rname)
We encountered a REDIRECT record during our resolution.
static int resolver_getservbyname(const char *name, const char *proto)
Function called to receive the port number for a service.
static void add_dns_result(struct GNS_ResolverHandle *rh, uint64_t expiration_time, uint32_t record_type, size_t data_size, const void *data)
Add a result from DNS to the records to be returned to the application.
static void recursive_gns_resolution_revocation(struct GNS_ResolverHandle *rh)
Perform revocation check on tail of our authority chain.
static struct GNUNET_DHT_Handle * dht_handle
Resolver handle to the dht.
static struct GNS_ResolverHandle * rlh_head
Head of resolver lookup list.
void GNS_resolver_lookup_cancel(struct GNS_ResolverHandle *rh)
Cancel active resolution (i.e.
static void handle_dns_result(void *cls, const struct sockaddr *addr, socklen_t addrlen)
We had to do a DNS lookup.
static struct CacheOps * co_head
Organized in a DLL.
static void handle_dht_response(void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *trunc_peer, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data)
Iterator called on each result obtained for a DHT operation that expects a reply.
static void dns_result_parser(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
Function called with the result of a DNS resolution.
static void recursive_redirect_resolution(struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
We found a REDIRECT record, perform recursive resolution on it.
static void namecache_cache_continuation(void *cls, int32_t success, const char *emsg)
Function called once the namestore has completed the request for caching a block.
static void handle_gns_cname_result(struct GNS_ResolverHandle *rh, const char *cname)
We encountered a CNAME record during our resolution.
#define DHT_GNS_REPLICATION_LEVEL
DHT replication level.
static void GNS_resolver_lookup_cancel_(void *cls)
Wrapper around GNS_resolver_lookup_cancel() as a task.
static void recursive_dns_resolution(struct GNS_ResolverHandle *rh)
Perform recursive DNS resolution.
static char * resolver_lookup_get_next_label(struct GNS_ResolverHandle *rh)
Get the next, rightmost label from the name that we are trying to resolve, and update the resolution ...
static void timeout_resolution(void *cls)
Function called when a resolution times out.
static struct CacheOps * co_tail
Organized in a DLL.
static int recursive_gns2dns_resolution(struct GNS_ResolverHandle *rh, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
We found one or more GNS2DNS records, perform recursive resolution on it.
static void handle_gns_namecache_resolution_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process a records that were decrypted from a block that we got from the namecache.
static void handle_gns_resolution_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process records that were decrypted from a block.
static void handle_gns2dns_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
We've resolved the IP address for the DNS resolver to use after encountering a GNS2DNS record.
static void continue_with_gns2dns(struct AuthorityChain *ac)
We have resolved one or more of the nameservers for a GNS2DNS lookup.
void GNS_resolver_done()
Shutdown resolver.
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_CRYPTO_PublicKey *zone, uint32_t record_type, const char *name, enum GNUNET_GNS_LocalOptions options, uint16_t recursion_depth_limit, GNS_ResultProcessor proc, void *proc_cls)
Lookup of a record in a specific zone calls lookup result processor on result.
static struct GNUNET_CONTAINER_Heap * dht_lookup_heap
Heap for limiting parallel DHT lookups.
static struct GNUNET_NAMECACHE_Handle * namecache_handle
Our handle to the namecache service.
void(* GNS_ResultProcessor)(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Function called with results for a GNS resolution.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition gnunet-uri.c:38
GNUNET_BLOCK_Type
WARNING: This header is generated! In order to add DHT block types, you must register them in GANA,...
@ GNUNET_BLOCK_TYPE_GNS_NAMERECORD
Block for storing GNS record data.
API to the DHT service.
API to the GNS service.
API that can be used to manipulate GNS record data.
API that can be used to store naming information on a GNUnet node.
Functions related to doing DNS lookups.
API to perform and access key revocations.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
void GNUNET_DHT_get_stop(struct GNUNET_DHT_GetHandle *get_handle)
Stop async DHT-get.
Definition dht_api.c:1233
struct GNUNET_DHT_GetHandle * GNUNET_DHT_get_start(struct GNUNET_DHT_Handle *handle, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, const void *xquery, size_t xquery_size, GNUNET_DHT_GetIterator iter, void *iter_cls)
Perform an asynchronous GET operation on the DHT identified.
Definition dht_api.c:1160
@ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
Each peer along the way should process the request (otherwise only peers locally closest to the key w...
#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.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_DNSPARSER_TYPE_URI
struct GNUNET_DNSPARSER_MxRecord * GNUNET_DNSPARSER_parse_mx(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS MX record.
Definition dnsparser.c:455
int GNUNET_DNSPARSER_builder_add_name(char *dst, size_t dst_len, size_t *off, const char *name)
Add a DNS name to the UDP packet at the given location, converting the name to IDNA notation as neces...
Definition dnsparser.c:985
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition dnsparser.c:950
#define GNUNET_DNSPARSER_TYPE_SRV
#define GNUNET_DNSPARSER_TYPE_SOA
#define GNUNET_DNSPARSER_TYPE_A
void GNUNET_DNSPARSER_free_srv(struct GNUNET_DNSPARSER_SrvRecord *srv)
Free SRV information record.
Definition dnsparser.c:139
#define GNUNET_DNSPARSER_TYPE_PTR
struct GNUNET_DNSPARSER_SoaRecord * GNUNET_DNSPARSER_parse_soa(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS SOA record.
Definition dnsparser.c:410
void GNUNET_DNSPARSER_free_uri(struct GNUNET_DNSPARSER_UriRecord *uri)
Free URI information record.
Definition dnsparser.c:154
#define GNUNET_DNSPARSER_TYPE_NS
int GNUNET_DNSPARSER_builder_add_soa(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SoaRecord *soa)
Add an SOA record to the UDP packet at the given location.
Definition dnsparser.c:1177
#define GNUNET_DNSPARSER_TYPE_CNAME
struct GNUNET_DNSPARSER_UriRecord * GNUNET_DNSPARSER_parse_uri(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS URI record.
Definition dnsparser.c:537
struct GNUNET_DNSPARSER_SrvRecord * GNUNET_DNSPARSER_parse_srv(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS SRV record.
Definition dnsparser.c:496
char * GNUNET_DNSPARSER_parse_name(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse name inside of a DNS query or record.
Definition dnsparser.c:353
int GNUNET_DNSPARSER_builder_add_mx(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_MxRecord *mx)
Add an MX record to the UDP packet at the given location.
Definition dnsparser.c:1099
void GNUNET_DNSPARSER_free_soa(struct GNUNET_DNSPARSER_SoaRecord *soa)
Free SOA information record.
Definition dnsparser.c:108
int GNUNET_DNSPARSER_builder_add_srv(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SrvRecord *srv)
Add an SRV record to the UDP packet at the given location.
Definition dnsparser.c:1218
void GNUNET_DNSPARSER_free_mx(struct GNUNET_DNSPARSER_MxRecord *mx)
Free MX information record.
Definition dnsparser.c:169
#define GNUNET_DNSPARSER_TYPE_AAAA
int GNUNET_DNSPARSER_pack(const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length)
Given a DNS packet p, generate the corresponding UDP payload.
Definition dnsparser.c:1400
int GNUNET_DNSPARSER_builder_add_uri(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_UriRecord *uri)
Add an URI record to the UDP packet at the given location.
Definition dnsparser.c:1255
#define GNUNET_DNSPARSER_TYPE_MX
struct GNUNET_DNSPARSER_Packet * GNUNET_DNSPARSER_parse(const char *udp_payload, size_t udp_payload_length)
Parse a UDP payload of a DNS packet in to a nice struct for further processing and manipulation.
Definition dnsparser.c:729
#define GNUNET_DNSPARSER_MAX_NAME_LENGTH
Maximum length of a name in DNS.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition dnsstub.c:586
int GNUNET_DNSSTUB_add_dns_ip(struct GNUNET_DNSSTUB_Context *ctx, const char *dns_ip)
Add nameserver for use by the DNSSTUB.
Definition dnsstub.c:613
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition dnsstub.c:705
struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve(struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls)
Perform DNS resolution using our default IP from init.
Definition dnsstub.c:526
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition dnsstub.c:562
int GNUNET_DNSSTUB_add_dns_sa(struct GNUNET_DNSSTUB_Context *ctx, const struct sockaddr *sa)
Add nameserver for use by the DNSSTUB.
Definition dnsstub.c:665
GNUNET_GNS_LocalOptions
Options for the GNS lookup.
@ GNUNET_GNS_LO_LOCAL_MASTER
For the rightmost label, only look in the cache (it is our local namestore), for the others,...
@ GNUNET_GNS_LO_DEFAULT
Defaults, look in cache, then in DHT.
void GNUNET_GNSRECORD_query_from_public_key(const struct GNUNET_CRYPTO_PublicKey *pub, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_CRYPTO_PublicKey *z)
Convert a zone to a string (for printing debug messages).
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_CRYPTO_PublicKey *pkey)
Convert an absolute domain name to the respective public key.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_CRYPTO_PublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls)
Decrypt block.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_CRYPTO_PublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
size_t GNUNET_GNSRECORD_block_get_size(const struct GNUNET_GNSRECORD_Block *block)
Returns the length of this block in bytes.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_CRYPTO_PublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_is_critical(uint32_t type)
Check if this type is a critical record.
Definition gnsrecord.c:239
#define GNUNET_GNSRECORD_TYPE_ANY
Record type indicating any record/'*'.
struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_block_get_expiration(const struct GNUNET_GNSRECORD_Block *block)
Returns the expiration of a block.
@ GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION
This expiration time of the record is a relative time (not an absolute time).
@ GNUNET_GNSRECORD_RF_SUPPLEMENTAL
This is a supplemental record.
@ GNUNET_GNSRECORD_RF_NONE
Entry for no flags / cleared flags.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
#define GNUNET_log(kind,...)
#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_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#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_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_NAMECACHE_cancel(struct GNUNET_NAMECACHE_QueueEntry *qe)
Cancel a namecache operation.
struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_lookup_block(struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_HashCode *derived_hash, GNUNET_NAMECACHE_BlockProcessor proc, void *proc_cls)
Get a result for a particular key from the namecache.
struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_block_cache(struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_GNSRECORD_Block *block, GNUNET_NAMECACHE_ContinuationWithStatus cont, void *cont_cls)
Store an item in the namecache.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get(const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
Convert a string to one or more IP addresses.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
void GNUNET_REVOCATION_query_cancel(struct GNUNET_REVOCATION_Query *q)
Cancel key revocation check.
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_PublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1304
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1277
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_TIME_UNIT_HOURS
One hour.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:660
#define GNUNET_TUN_DNS_CLASS_INTERNET
A few common DNS classes (ok, only one is common, but I list a couple more to make it clear what we'r...
#define GNUNET_TUN_DNS_OPCODE_QUERY
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
DLL to hold the authority chain we had to pass in the resolution process.
int found
Did we succeed in getting an IP address for any of the DNS servers listed? Once we do,...
char * label
label/name corresponding to the authority
struct AuthorityChain * next
This is a DLL.
union AuthorityChain::@55 authority_info
Information about the resolver authority for this label.
int gns_authority
GNUNET_YES if the authority was a GNS authority, GNUNET_NO if the authority was a DNS authority.
struct GNUNET_DNSSTUB_Context * dns_handle
Handle to perform DNS lookups with this authority (in GNS2DNS handling).
char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH+1]
Domain of the DNS resolver that is the authority.
struct AuthorityChain * prev
This is a DLL.
struct GNS_ResolverHandle * rh
Resolver handle this entry in the chain belongs to.
int launched
Did we start the recursive resolution via DNS?
struct Gns2DnsPending * gp_head
List of resolutions of the 'ip' of the name server that are still pending.
struct Gns2DnsPending * gp_tail
Tail of list of resolutions of the 'ip' of the name server that are still pending.
struct AuthorityChain::@55::@56 dns_authority
Active namestore caching operations.
struct CacheOps * prev
Organized in a DLL.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe_cache
Pending Namestore caching task.
struct CacheOps * next
Organized in a DLL.
A result we got from DNS.
struct DnsResult * next
Kept in DLL.
size_t data_size
Number of bytes in data.
uint32_t record_type
Type of the GNS/DNS record.
struct DnsResult * prev
Kept in DLL.
uint64_t expiration_time
Expiration time for the DNS record, 0 if we didn't get anything useful (i.e.
const void * data
Binary value stored in the DNS record (appended to this struct)
Handle to a currently pending resolution.
size_t name_resolution_pos
Current offset in name where we are resolving.
int service
For SRV and TLSA records, the number of the service specified in the name.
char * leho
Legacy Hostname to use if we encountered GNS2DNS record and thus can deduct the LEHO from that transi...
struct GNUNET_CRYPTO_PublicKey authority_zone
The top-level GNS authoritative zone to query.
struct GNUNET_CONTAINER_HeapNode * dht_heap_node
Heap node associated with this lookup.
void * proc_cls
closure passed to proc
struct GNS_ResolverHandle * next
DLL.
struct GNUNET_DHT_GetHandle * get_handle
Handle for DHT lookups.
struct DnsResult * dns_result_tail
DLL of results we got from DNS.
struct GNUNET_REVOCATION_Query * rev_check
Pending revocation check.
unsigned int loop_limiter
We increment the loop limiter for each step in a recursive resolution.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe
Pending Namecache lookup task.
struct GNUNET_RESOLVER_RequestHandle * std_resolve
Handle for standard DNS resolution, NULL if none is active.
int record_type
Desired type for the resolution.
struct DnsResult * dns_result_head
DLL of results we got from DNS.
struct AuthorityChain * ac_head
DLL to store the authority chain.
struct AuthorityChain * ac_tail
DLL to store the authority chain.
unsigned int loop_threshold
Maximum value of loop_limiter allowed by client.
struct GNUNET_SCHEDULER_Task * task_id
ID of a task associated with the resolution process.
GNS_ResultProcessor proc
called when resolution phase finishes
uint16_t original_dns_id
16 bit random ID we used in the dns_request.
struct GNS_ResolverHandle * prev
DLL.
char * name
The name to resolve.
char * prefix
For SMIMEA,OPENPGPKEY... records.
int protocol
For SRV and TLSA records, the number of the protocol specified in the name.
enum GNUNET_GNS_LocalOptions options
Use only cache.
struct GNUNET_DNSSTUB_RequestSocket * dns_request
Socket for a DNS request, NULL if none is active.
Handle to a node in a heap.
An identity key as per LSD0001.
Handle to a GET request.
Definition dht_api.c:79
Connection to the DHT service.
Definition dht_api.c:235
A (signed) path tracking a block's flow through the DHT is represented by an array of path elements,...
Information from MX records (RFC 1035).
char * mxhost
Name of the mail server.
Easy-to-process, parsed version of a DNS packet.
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
char * name
Name of the record that the query is for (0-terminated).
void * data
Binary record data.
size_t data_len
Number of bytes in data.
A DNS response record.
struct GNUNET_DNSPARSER_SoaRecord * soa
SOA data for SOA records.
struct GNUNET_DNSPARSER_SrvRecord * srv
SRV data for SRV records.
struct GNUNET_DNSPARSER_MxRecord * mx
MX data for MX records.
char * hostname
For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
struct GNUNET_TIME_Absolute expiration_time
When does the record expire?
char * name
Name of the record that the query is for (0-terminated).
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
union GNUNET_DNSPARSER_Record::@20 data
Payload of the record (which one of these is valid depends on the 'type').
struct GNUNET_DNSPARSER_UriRecord * uri
URI data for URI records.
Information from SOA records (RFC 1035).
char * mname
The domainname of the name server that was the original or primary source of data for this zone.
char * rname
A domainname which specifies the mailbox of the person responsible for this zone.
Information from SRV records (RFC 2782).
char * target
Hostname offering the service.
Information from URI records (RFC 7553).
Handle to the stub resolver.
Definition dnsstub.c:125
UDP socket we are using for sending DNS requests to the Internet.
Definition dnsstub.c:46
Record type used to box up SRV and TLSA records.
uint32_t record_type
GNS record type of the boxed record.
uint16_t service
Service of the boxed record (aka port number), in NBO.
uint16_t protocol
Protocol of the boxed record (6 = TCP, 17 = UDP, etc.).
uint32_t record_type
Type of the GNS/DNS record.
const void * data
Binary value stored in the DNS record.
size_t data_size
Number of bytes in data.
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
uint64_t expiration_time
Expiration time for the DNS record.
Record type used to box up SMIMEA records.
uint32_t record_type
GNS record type of the boxed record.
A 512-bit hashcode.
Connection to the NAMECACHE service.
An QueueEntry used to store information for a pending NAMECACHE record operation.
The identity of the host (wraps the signing key of the peer).
Handle to a request given to the resolver.
Handle for the key revocation query.
Entry in list of pending tasks.
Definition scheduler.c:136
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
uint16_t id
Unique identifier for the request/response.
Element of a resolution process for looking up the responsible DNS server hostname in a GNS2DNS recur...
struct GNUNET_RESOLVER_RequestHandle * dns_rh
Handle for DNS resolution of the DNS nameserver.
struct Gns2DnsPending * next
Kept in a DLL.
struct Gns2DnsPending * prev
Kept in a DLL.
struct GNS_ResolverHandle * rh
Handle for the resolution of the IP part of the GNS2DNS record.
struct AuthorityChain * ac
Context this activity belongs with.
unsigned int num_results
How many results did we get?