GNUnet 0.28.1-dev.4-24-g0cf3356dd
 
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
64#define DHT_LOOKUP_RETRIES 2
65
69#define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
70 GNUNET_TIME_UNIT_SECONDS, 15)
71
75#define DHT_GNS_REPLICATION_LEVEL 10
76
77
82struct AuthorityChain;
83
84
91{
96
101
106
113
118
122 unsigned int num_results;
123};
124
125
130struct GNS_ResolverHandle;
131
132
214
215
220{
225
230
234 const void *data;
235
241
245 size_t data_size;
246
250 uint32_t record_type;
251};
252
253
415
416
437
438
443
448
453
457static unsigned long long max_allowed_background_queries;
458
463
468
472static struct CacheOps *co_head;
473
477static struct CacheOps *co_tail;
478
482static int disable_cache;
483
487static const struct GNUNET_CONFIGURATION_Handle *cfg;
488
489
490/* ************************** Resolution **************************** */
491
499static char *
501 char *name)
502{
503 char *ret;
504 size_t s_len = strlen (name);
505
506 if (0 != strcmp (&name[s_len - 2],
507 ".+"))
508 return name; /* did not end in ".+" */
511 "%.*s.%s",
512 (int) (s_len - 2),
513 name,
517 return ret;
518}
519
520
527static void
529{
530 struct GNS_ResolverHandle *rh = cls;
531
532 rh->task_id = NULL;
534}
535
536
542static void
544{
545 rh->proc (rh->proc_cls,
546 0,
547 NULL);
548 GNUNET_assert (NULL == rh->task_id);
550 rh);
551}
552
553
559static void
561{
562 struct GNS_ResolverHandle *rh = cls;
563
564 rh->task_id = NULL;
565 fail_resolution (rh);
566}
567
568
574static int
576{
577 struct protoent *pe = getprotobyname (name);
578 if (pe == NULL)
579 {
581 }
582 return pe->p_proto;
583}
584
585
592static int
593resolver_getservbyname (const char *name, const char *proto)
594{
595 struct servent *se = getservbyname (name, proto);
596 if (se == NULL)
597 {
599 }
600 return se->s_port;
601}
602
603
622static char *
624{
625 const char *rp;
626 const char *dot;
627 size_t len;
628 char *ret;
629 char *srv_name;
630 char *proto_name;
631 int protocol;
632 int service;
633
634 if (0 == rh->name_resolution_pos)
635 return NULL;
636 dot = memrchr (rh->name,
637 (int) '.',
639 if (NULL == dot)
640 {
641 /* done, this was the last one */
642 len = rh->name_resolution_pos;
643 rp = rh->name;
644 rh->name_resolution_pos = 0;
645 }
646 else if ('_' == dot[1])
647 {
656 len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
657 }
658 else
659 {
660 /* advance by one label */
661 len = rh->name_resolution_pos - (dot - rh->name) - 1;
662 rp = dot + 1;
663 rh->name_resolution_pos = dot - rh->name;
664 }
665 rh->protocol = 0;
666 rh->service = 0;
667 rh->prefix = NULL;
668 ret = GNUNET_strndup (rp, len);
673 if (('_' == rh->name[0]) &&
674 (NULL != (dot = memrchr (rh->name,
675 (int) '.',
676 rh->name_resolution_pos))) &&
677 ('_' == dot[1]) &&
678 (NULL == memrchr (rh->name,
679 (int) '.',
680 dot - rh->name)))
681 {
682 srv_name = GNUNET_strndup (&rh->name[1],
683 (dot - rh->name) - 1);
684 proto_name = GNUNET_strndup (&dot[2],
685 rh->name_resolution_pos - (dot - rh->name)
686 - 2);
687 protocol = resolver_getprotobyname (proto_name);
688 if (0 == protocol)
689 {
691 _ (
692 "Protocol `%s' unknown, skipping labels as BOX retain as SBOX.\n"),
693 proto_name);
694 GNUNET_free (proto_name);
695 GNUNET_free (srv_name);
697 rh->name_resolution_pos = 0;
698 return ret;
699 }
701 proto_name);
702 if (0 == service)
703 {
705 _ (
706 "Service `%s' unknown for protocol `%s', trying as number.\n"),
707 srv_name,
708 proto_name);
709 if (1 != sscanf (srv_name, "%u", &rh->service))
710 {
712 _ (
713 "Service `%s' not a port, skipping service labels as BOX retain as SBOX.\n"),
714 srv_name);
715 GNUNET_free (proto_name);
716 GNUNET_free (srv_name);
718 rh->name_resolution_pos = 0;
719 return ret;
720 }
721 }
722 else
723 {
724 rh->service = ntohs (service);
725 }
726 rh->protocol = protocol;
727 GNUNET_free (proto_name);
728 GNUNET_free (srv_name);
729 }
736 if ((NULL != (dot = memrchr (rh->name,
737 (int) '.',
738 rh->name_resolution_pos)) && '_' == dot[1]) ||
739 ((NULL == memrchr (rh->name,
740 (int) '.',
741 rh->name_resolution_pos)) && '_' == rh->name[0]))
742 {
744 rh->name_resolution_pos = 0;
745 }
746 return ret;
747}
748
749
755static void
757{
758 struct DnsResult *pos;
759 unsigned int n;
760 unsigned int i;
761
762 n = 0;
763 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
764 n++;
765 {
766 struct GNUNET_GNSRECORD_Data rd[n];
767
768 i = 0;
769 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
770 {
771 rd[i].data = pos->data;
772 rd[i].data_size = pos->data_size;
773 rd[i].record_type = pos->record_type;
781 if (0 == pos->expiration_time)
782 {
784 rd[i].expiration_time = 0;
785 }
786 else
787 {
789 }
790 i++;
791 }
792 GNUNET_assert (i == n);
794 "Transmitting standard DNS result with %u records\n",
795 n);
796 rh->proc (rh->proc_cls,
797 n,
798 rd);
799 }
801}
802
803
813static void
815 uint64_t expiration_time,
816 uint32_t record_type,
817 size_t data_size,
818 const void *data)
819{
820 struct DnsResult *res;
821
822 res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
823 res->expiration_time = expiration_time;
824 res->data_size = data_size;
825 res->record_type = record_type;
826 res->data = &res[1];
827 GNUNET_memcpy (&res[1],
828 data,
829 data_size);
831 rh->dns_result_tail,
832 res);
833}
834
835
844static void
846 const struct sockaddr *addr,
847 socklen_t addrlen)
848{
849 struct GNS_ResolverHandle *rh = cls;
850 const struct sockaddr_in *sa4;
851 const struct sockaddr_in6 *sa6;
852
853 if (NULL == addr)
854 {
855 rh->std_resolve = NULL;
857 return;
858 }
860 "Received %u bytes of DNS IP data\n",
861 addrlen);
862 switch (addr->sa_family)
863 {
864 case AF_INET:
865 sa4 = (const struct sockaddr_in *) addr;
866 add_dns_result (rh,
867 0 /* expiration time is unknown */,
869 sizeof(struct in_addr),
870 &sa4->sin_addr);
871 break;
872
873 case AF_INET6:
874 sa6 = (const struct sockaddr_in6 *) addr;
875 add_dns_result (rh,
876 0 /* expiration time is unknown */,
878 sizeof(struct in6_addr),
879 &sa6->sin6_addr);
880 break;
881
882 default:
883 GNUNET_break (0);
884 break;
885 }
886}
887
888
894static void
895recursive_resolution (void *cls);
896
897
904static void
905start_resolver_lookup (void *cls);
906
907
916static void
918 const struct GNUNET_TUN_DnsHeader *dns,
919 size_t dns_len)
920{
921 struct GNS_ResolverHandle *rh = cls;
923 const struct GNUNET_DNSPARSER_Record *rec;
924 unsigned int rd_count;
925
926 if (NULL == dns)
927 {
928 rh->dns_request = NULL;
930 rh->task_id = NULL;
931 fail_resolution (rh);
932 return;
933 }
934 if (rh->original_dns_id != dns->id)
935 {
936 /* DNS answer, but for another query */
937 return;
938 }
939 p = GNUNET_DNSPARSER_parse ((const char *) dns,
940 dns_len);
941 if (NULL == p)
942 {
944 _ ("Failed to parse DNS response\n"));
945 return;
946 }
947
948 /* We got a result from DNS */
950 "Received DNS response for `%s' with %u answers\n",
951 rh->ac_tail->label,
952 (unsigned int) p->num_answers);
953 if ((p->num_answers > 0) &&
954 (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
956 {
957 int af;
958
960 "Got CNAME `%s' from DNS for `%s'\n",
961 p->answers[0].data.hostname,
962 rh->name);
963 if (NULL != rh->std_resolve)
964 {
966 "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
967 rh->name);
969 }
970 GNUNET_free (rh->name);
971 rh->name = GNUNET_strdup (p->answers[0].data.hostname);
972 rh->name_resolution_pos = strlen (rh->name);
973 switch (rh->record_type)
974 {
976 af = AF_INET;
977 break;
978
980 af = AF_INET6;
981 break;
982
983 default:
984 af = AF_UNSPEC;
985 break;
986 }
987 if (NULL != rh->leho)
988 add_dns_result (rh,
989 GNUNET_TIME_UNIT_HOURS.rel_value_us,
991 strlen (rh->leho),
992 rh->leho);
994 af,
997 rh);
1000 rh->dns_request = NULL;
1001 return;
1002 }
1003
1004 /* convert from (parsed) DNS to (binary) GNS format! */
1005 rd_count = p->num_answers + p->num_authority_records
1006 + p->num_additional_records;
1007 {
1008 struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
1009 int skip;
1010 char buf[UINT16_MAX];
1011 char *name_ace;
1012 size_t buf_off;
1013 size_t buf_start;
1014
1015 buf_off = 0;
1016 skip = 0;
1017 memset (rd,
1018 0,
1019 sizeof(rd));
1020 for (unsigned int i = 0; i < rd_count; i++)
1021 {
1022 if (i < p->num_answers)
1023 rec = &p->answers[i];
1024 else if (i < p->num_answers + p->num_authority_records)
1025 rec = &p->authority_records[i - p->num_answers];
1026 else
1027 rec = &p->additional_records[i - p->num_answers
1028 - p->num_authority_records];
1029 /* As we copied the full DNS name to 'rh->ac_tail->label', this
1030 should be the correct check to see if this record is actually
1031 a record for our label...
1032 However, DNSPARSER will convert the ACE name to UTF-8 so
1033 we must convert back.
1034 */
1035 if (IDNA_SUCCESS != idna_to_ascii_8z (rec->name,
1036 &name_ace,
1037 IDNA_ALLOW_UNASSIGNED))
1038 {
1040 _ ("Name `%s' cannot be converted to IDNA."),
1041 rec->name);
1042 continue;
1043 }
1044
1045 if (0 != strcmp (name_ace,
1046 rh->ac_tail->label))
1047 {
1049 "Dropping record `%s', does not match desired name `%s'\n",
1050 rec->name,
1051 rh->ac_tail->label);
1052 skip++;
1053 continue;
1054 }
1055 rd[i - skip].record_type = rec->type;
1057 switch (rec->type)
1058 {
1060 if (rec->data.raw.data_len != sizeof(struct in_addr))
1061 {
1062 GNUNET_break_op (0);
1063 skip++;
1064 continue;
1065 }
1066 rd[i - skip].data_size = rec->data.raw.data_len;
1067 rd[i - skip].data = rec->data.raw.data;
1068 break;
1069
1071 if (rec->data.raw.data_len != sizeof(struct in6_addr))
1072 {
1073 GNUNET_break_op (0);
1074 skip++;
1075 continue;
1076 }
1077 rd[i - skip].data_size = rec->data.raw.data_len;
1078 rd[i - skip].data = rec->data.raw.data;
1079 break;
1080
1084 buf_start = buf_off;
1085 if (GNUNET_OK !=
1087 sizeof(buf),
1088 &buf_off,
1089 rec->data.hostname))
1090 {
1091 GNUNET_break (0);
1092 skip++;
1093 continue;
1094 }
1095 rd[i - skip].data_size = buf_off - buf_start;
1096 rd[i - skip].data = &buf[buf_start];
1097 break;
1098
1100 buf_start = buf_off;
1101 if (GNUNET_OK !=
1103 sizeof(buf),
1104 &buf_off,
1105 rec->data.soa))
1106 {
1107 GNUNET_break (0);
1108 skip++;
1109 continue;
1110 }
1111 rd[i - skip].data_size = buf_off - buf_start;
1112 rd[i - skip].data = &buf[buf_start];
1113 break;
1114
1116 buf_start = buf_off;
1117 if (GNUNET_OK !=
1119 sizeof(buf),
1120 &buf_off,
1121 rec->data.mx))
1122 {
1123 GNUNET_break (0);
1124 skip++;
1125 continue;
1126 }
1127 rd[i - skip].data_size = buf_off - buf_start;
1128 rd[i - skip].data = &buf[buf_start];
1129 break;
1130
1132 buf_start = buf_off;
1133 if (GNUNET_OK !=
1135 sizeof(buf),
1136 &buf_off,
1137 rec->data.srv))
1138 {
1139 GNUNET_break (0);
1140 skip++;
1141 continue;
1142 }
1143 rd[i - skip].data_size = buf_off - buf_start;
1144 rd[i - skip].data = &buf[buf_start];
1145 break;
1146
1148 buf_start = buf_off;
1149 if (GNUNET_OK !=
1151 sizeof(buf),
1152 &buf_off,
1153 rec->data.uri))
1154 {
1155 GNUNET_break (0);
1156 skip++;
1157 continue;
1158 }
1159 rd[i - skip].data_size = buf_off - buf_start;
1160 rd[i - skip].data = &buf[buf_start];
1161 break;
1162
1163 default:
1165 _ ("Skipping record of unsupported type %d\n"),
1166 rec->type);
1167 skip++;
1168 continue;
1169 }
1170 } /* end of for all records in answer */
1171 if (NULL != rh->leho)
1172 {
1176 rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1177 rd[rd_count - skip].data = rh->leho;
1178 rd[rd_count - skip].data_size = strlen (rh->leho);
1179 skip--; /* skip one LESS */
1181 "Adding LEHO %s\n",
1182 rh->leho);
1183 }
1185 "Returning DNS response for `%s' with %u answers\n",
1186 rh->ac_tail->label,
1187 (unsigned int) (rd_count - skip));
1188 rh->proc (rh->proc_cls,
1189 rd_count - skip,
1190 rd);
1192 rh->dns_request = NULL;
1193 }
1194
1195
1197 if (NULL != rh->task_id)
1198 GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1200 rh);
1201}
1202
1203
1212static void
1214{
1215 struct AuthorityChain *ac;
1216 struct GNUNET_DNSPARSER_Query *query;
1217 struct GNUNET_DNSPARSER_Packet *p;
1218 char *dns_request;
1219 size_t dns_request_length;
1220 int ret;
1221
1222 ac = rh->ac_tail;
1223 GNUNET_assert (NULL != ac);
1225 "Starting DNS lookup for `%s'\n",
1226 ac->label);
1228 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1229 query->name = GNUNET_strdup (ac->label);
1230 query->type = rh->record_type;
1233 p->queries = query;
1234 p->num_queries = 1;
1235 p->id = (uint16_t) GNUNET_CRYPTO_random_u32 (UINT16_MAX);
1236 p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1237 p->flags.recursion_desired = 1;
1239 1024,
1240 &dns_request,
1241 &dns_request_length);
1242 if (GNUNET_OK != ret)
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 }
1252 else
1253 {
1254 rh->original_dns_id = p->id;
1256 GNUNET_assert (NULL == rh->dns_request);
1257 if (IDNA_SUCCESS != idna_to_unicode_8z8z (ac->label,
1258 &rh->leho,
1259 IDNA_ALLOW_UNASSIGNED))
1260 {
1261 GNUNET_break (0);
1262 rh->proc (rh->proc_cls,
1263 0,
1264 NULL);
1265 GNUNET_assert (NULL == rh->task_id);
1267 rh);
1268 }
1271 dns_request,
1272 dns_request_length,
1274 rh);
1277 rh);
1278 }
1279 if (GNUNET_SYSERR != ret)
1280 GNUNET_free (dns_request);
1282}
1283
1284
1293static void
1295 const char *rname)
1296{
1297 size_t nlen;
1298 char *res;
1299 const char *tld;
1300 struct AuthorityChain *ac;
1301 int af;
1303
1305 "Handling GNS REDIRECT result `%s'\n",
1306 rname);
1307 nlen = strlen (rname);
1308 tld = GNS_get_tld (rname);
1309 if (0 == strcmp ("+", tld))
1310 {
1311 /* REDIRECT resolution continues relative to current domain */
1312 if (0 == rh->name_resolution_pos)
1313 {
1314 res = GNUNET_strndup (rname, nlen - 2);
1315 rh->name_resolution_pos = nlen - 2;
1316 }
1317 else
1318 {
1320 "%.*s.%.*s",
1321 (int) rh->name_resolution_pos,
1322 rh->name,
1323 (int) (nlen - 2),
1324 rname);
1325 rh->name_resolution_pos = strlen (res);
1326 }
1327 GNUNET_free (rh->name);
1328 rh->name = res;
1329 ac = GNUNET_new (struct AuthorityChain);
1330 ac->rh = rh;
1335 /* add AC to tail */
1337 rh->ac_tail,
1338 ac);
1340 rh);
1341 return;
1342 }
1343 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1344 {
1345 /* REDIRECT resolution continues relative to current domain */
1346 if (0 == rh->name_resolution_pos)
1347 {
1349 "%.*s",
1350 (int) (strlen (rname) - (strlen (tld) + 1)),
1351 rname);
1352 }
1353 else
1354 {
1356 "%.*s.%.*s",
1357 (int) rh->name_resolution_pos,
1358 rh->name,
1359 (int) (strlen (rname) - (strlen (tld) + 1)),
1360 rname);
1361 }
1362 rh->name_resolution_pos = strlen (res);
1363 GNUNET_free (rh->name);
1364 rh->name = res;
1365 ac = GNUNET_new (struct AuthorityChain);
1366 ac->rh = rh;
1368 ac->authority_info.gns_authority = zone;
1370 /* add AC to tail */
1372 rh->ac_tail,
1373 ac);
1375 rh);
1376 return;
1377 }
1378
1380 "Got REDIRECT `%s' from GNS for `%s'\n",
1381 rname,
1382 rh->name);
1383 if (NULL != rh->std_resolve)
1384 {
1386 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1387 rh->name);
1389 }
1390 /* name is absolute, go to DNS */
1391 GNUNET_free (rh->name);
1392 rh->name = GNUNET_strdup (rname);
1393 rh->name_resolution_pos = strlen (rh->name);
1394 switch (rh->record_type)
1395 {
1397 af = AF_INET;
1398 break;
1399
1401 af = AF_INET6;
1402 break;
1403
1404 default:
1405 af = AF_UNSPEC;
1406 break;
1407 }
1409 "Doing standard DNS lookup for `%s'\n",
1410 rh->name);
1411
1413 af,
1416 rh);
1417}
1418
1419
1428static void
1430 const char *cname)
1431{
1432 int af;
1433
1434 GNUNET_free (rh->name);
1435 rh->name = GNUNET_strdup (cname);
1436 rh->name_resolution_pos = strlen (rh->name);
1437 switch (rh->record_type)
1438 {
1440 af = AF_INET;
1441 break;
1442
1444 af = AF_INET6;
1445 break;
1446
1447 default:
1448 af = AF_UNSPEC;
1449 break;
1450 }
1452 "Doing standard DNS lookup for `%s'\n",
1453 rh->name);
1454
1456 af,
1459 rh);
1460}
1461
1462
1470static void
1472 unsigned int rd_count,
1473 const struct GNUNET_GNSRECORD_Data *rd);
1474
1475
1483static void
1485{
1486 struct GNS_ResolverHandle *rh = ac->rh;
1487
1488 if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1490 return; /* more pending and none found yet */
1492 {
1494 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1496 fail_resolution (rh);
1497 return;
1498 }
1500 return; /* already running, do not launch again! */
1501 /* recurse */
1504 "Will continue resolution using DNS to resolve `%s'\n",
1505 ac->label);
1506 GNUNET_assert (NULL == rh->task_id);
1508 rh);
1509}
1510
1511
1520static void
1522 unsigned int rd_count,
1523 const struct GNUNET_GNSRECORD_Data *rd)
1524{
1525 struct Gns2DnsPending *gp = cls;
1526 struct AuthorityChain *ac = gp->ac;
1527
1530 gp);
1531 /* enable cleanup of 'rh' handle that automatically comes after we return,
1532 and which expects 'rh' to be in the #rlh_head DLL. */
1533 if (NULL != gp->rh)
1534 {
1536 rlh_tail,
1537 gp->rh);
1538 gp->rh = NULL;
1539 }
1540 GNUNET_free (gp);
1542 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1543 rd_count);
1544 /* find suitable A/AAAA record */
1545 for (unsigned int j = 0; j < rd_count; j++)
1546 {
1547 switch (rd[j].record_type)
1548 {
1550 {
1551 struct sockaddr_in v4;
1552
1553 if (sizeof(struct in_addr) != rd[j].data_size)
1554 {
1555 GNUNET_break_op (0);
1556 continue;
1557 }
1558 memset (&v4,
1559 0,
1560 sizeof(v4));
1561 v4.sin_family = AF_INET;
1562 v4.sin_port = htons (53);
1563#if HAVE_SOCKADDR_IN_SIN_LEN
1564 v4.sin_len = (u_char) sizeof(v4);
1565#endif
1566 GNUNET_memcpy (&v4.sin_addr,
1567 rd[j].data,
1568 sizeof(struct in_addr));
1569 if (GNUNET_OK ==
1572 (const struct sockaddr *) &v4))
1574 break;
1575 }
1576
1578 {
1579 struct sockaddr_in6 v6;
1580
1581 if (sizeof(struct in6_addr) != rd[j].data_size)
1582 {
1583 GNUNET_break_op (0);
1584 continue;
1585 }
1586 /* FIXME: might want to check if we support IPv6 here,
1587 and otherwise skip this one and hope we find another */
1588 memset (&v6,
1589 0,
1590 sizeof(v6));
1591 v6.sin6_family = AF_INET6;
1592 v6.sin6_port = htons (53);
1593#if HAVE_SOCKADDR_IN_SIN_LEN
1594 v6.sin6_len = (u_char) sizeof(v6);
1595#endif
1596 GNUNET_memcpy (&v6.sin6_addr,
1597 rd[j].data,
1598 sizeof(struct in6_addr));
1599 if (GNUNET_OK ==
1602 (const struct sockaddr *) &v6))
1604 break;
1605 }
1606
1607 default:
1608 break;
1609 }
1610 }
1612}
1613
1614
1622static void
1624 const struct sockaddr *addr,
1625 socklen_t addrlen)
1626{
1627 struct Gns2DnsPending *gp = cls;
1628 struct AuthorityChain *ac = gp->ac;
1629 struct sockaddr_storage ss;
1630 struct sockaddr_in *v4;
1631 struct sockaddr_in6 *v6;
1632
1633 if (NULL == addr)
1634 {
1635 /* DNS resolution finished */
1636 if (0 == gp->num_results)
1638 "Failed to use DNS to resolve name of DNS resolver\n");
1641 gp);
1642 GNUNET_free (gp);
1644 return;
1645 }
1646 GNUNET_memcpy (&ss,
1647 addr,
1648 addrlen);
1649 switch (ss.ss_family)
1650 {
1651 case AF_INET:
1652 v4 = (struct sockaddr_in *) &ss;
1653 v4->sin_port = htons (53);
1654 gp->num_results++;
1655 break;
1656
1657 case AF_INET6:
1658 v6 = (struct sockaddr_in6 *) &ss;
1659 v6->sin6_port = htons (53);
1660 gp->num_results++;
1661 break;
1662
1663 default:
1665 "Unsupported AF %d\n",
1666 ss.ss_family);
1667 return;
1668 }
1669 if (GNUNET_OK ==
1671 (struct sockaddr *) &ss))
1673}
1674
1675
1682static void
1689
1690
1697static void
1699 const struct GNUNET_GNSRECORD_Data *rd)
1700{
1701 char *cname;
1702 size_t off;
1703
1704 off = 0;
1706 rd->data_size,
1707 &off);
1708 if ((NULL == cname) ||
1709 (off != rd->data_size))
1710 {
1711 GNUNET_break_op (0); /* record not well-formed */
1712 GNUNET_free (cname);
1713 fail_resolution (rh);
1714 return;
1715 }
1717 cname);
1718 GNUNET_free (cname);
1719}
1720
1721
1728static void
1730 const struct GNUNET_GNSRECORD_Data *rd)
1731{
1732 struct AuthorityChain *ac;
1734
1735 /* delegation to another zone */
1737 rd->data_size,
1738 rd->record_type,
1739 &auth))
1740 {
1741 GNUNET_break_op (0);
1742 fail_resolution (rh);
1743 return;
1744 }
1745 /* expand authority chain */
1746 ac = GNUNET_new (struct AuthorityChain);
1747 ac->rh = rh;
1749 ac->authority_info.gns_authority = auth;
1751 /* add AC to tail */
1753 rh->ac_tail,
1754 ac);
1755 /* recurse */
1757 rh);
1758}
1759
1760
1771static int
1773 unsigned int rd_count,
1774 const struct GNUNET_GNSRECORD_Data *rd)
1775{
1776 struct AuthorityChain *ac;
1777 const char *tld;
1778 char *ns;
1779
1780 ns = NULL;
1781 /* expand authority chain */
1782 ac = GNUNET_new (struct AuthorityChain);
1783 ac->rh = rh;
1785
1786 for (unsigned int i = 0; i < rd_count; i++)
1787 {
1788 char *ip;
1789 char *n;
1790 struct Gns2DnsPending *gp;
1792 struct sockaddr_in v4;
1793 struct sockaddr_in6 v6;
1794
1795 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1796 {
1801 GNUNET_free (ns);
1802 GNUNET_free (ac);
1803 return GNUNET_SYSERR;
1804 }
1805 n = GNUNET_strdup ((const char*) rd[i].data);
1806 if (strlen (n) + 1 >= rd[i].data_size)
1807 {
1808 GNUNET_break_op (0);
1809 continue;
1810 }
1811 ip = GNUNET_strdup (rd[i].data + strlen (n) + 1);
1812 /* resolve 'ip' to determine the IP(s) of the DNS
1813 resolver to use for lookup of 'ns' */
1814 if (NULL != ns)
1815 {
1816 if (0 != strcasecmp (ns,
1817 n))
1818 {
1819 /* NS values must all be the same for all GNS2DNS records,
1820 anything else leads to insanity */
1821 GNUNET_break_op (0);
1822 GNUNET_free (n);
1823 GNUNET_free (ip);
1824 continue;
1825 }
1826 GNUNET_free (n);
1827 }
1828 else
1829 {
1830 ns = n;
1831 }
1832
1833 /* check if 'ip' is already an IPv4/IPv6 address */
1834 if ((1 == inet_pton (AF_INET,
1835 ip,
1836 &v4)) ||
1837 (1 == inet_pton (AF_INET6,
1838 ip,
1839 &v6)))
1840 {
1844 ip));
1846 GNUNET_free (ip);
1847 continue;
1848 }
1849 tld = GNS_get_tld (ip);
1850 if ((0 != strcmp (tld, "+")) &&
1851 (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1852 {
1853 /* 'ip' is a DNS name */
1854 gp = GNUNET_new (struct Gns2DnsPending);
1855 gp->ac = ac;
1858 gp);
1860 AF_UNSPEC,
1863 gp);
1864 GNUNET_free (ip);
1865 continue;
1866 }
1867 /* 'ip' should be a GNS name */
1868 gp = GNUNET_new (struct Gns2DnsPending);
1869 gp->ac = ac;
1872 gp);
1873 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1874 if (0 == strcmp (tld, "+"))
1875 {
1876 ip = translate_dot_plus (rh,
1877 ip);
1878 tld = GNS_get_tld (ip);
1879 if (GNUNET_OK !=
1881 &zone))
1882 {
1883 GNUNET_break_op (0);
1884 GNUNET_free (ip);
1885 continue;
1886 }
1887 }
1888 gp->rh->authority_zone = zone;
1890 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1891 ip,
1892 ns);
1893 gp->rh->name = ip;
1894 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1896 gp->rh->proc_cls = gp;
1899 gp->rh->loop_limiter = rh->loop_limiter + 1;
1900 gp->rh->loop_threshold = rh->loop_threshold;
1901 gp->rh->task_id
1903 gp->rh);
1904 } /* end 'for all records' */
1905
1906 if (NULL == ns)
1907 {
1908 /* not a single GNS2DNS record found */
1909 GNUNET_free (ac);
1910 return GNUNET_SYSERR;
1911 }
1913 strcpy (ac->authority_info.dns_authority.name,
1914 ns);
1915 /* for DNS recursion, the label is the full DNS name,
1916 created from the remainder of the GNS name and the
1917 name in the NS record */
1918 GNUNET_asprintf (&ac->label,
1919 "%.*s%s%s",
1920 (int) rh->name_resolution_pos,
1921 rh->name,
1922 (0 != rh->name_resolution_pos) ? "." : "",
1923 ns);
1924 GNUNET_free (ns);
1925
1926 {
1927 /* the GNS name is UTF-8 and may include multibyte chars.
1928 * We have to convert the combined name to a DNS-compatible IDNA.
1929 */
1930 char *tmp = ac->label;
1931
1932 if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1933 &ac->label,
1934 IDNA_ALLOW_UNASSIGNED))
1935 {
1937 _ ("Name `%s' cannot be converted to IDNA."),
1938 tmp);
1939 GNUNET_free (tmp);
1940 GNUNET_free (ac);
1941 return GNUNET_SYSERR;
1942 }
1943 GNUNET_free (tmp);
1944 }
1945
1947 rh->ac_tail,
1948 ac);
1949 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1950 {
1952 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1953 ac->label);
1954 GNUNET_free (ac->label);
1955 GNUNET_free (ac);
1956 return GNUNET_SYSERR;
1957 }
1959 return GNUNET_OK;
1960}
1961
1962
1963static void
1965 unsigned int rd_count,
1966 const struct GNUNET_GNSRECORD_Data *rd)
1967{
1968 struct GNS_ResolverHandle *rh = cls;
1969 char *cname;
1970 char scratch[UINT16_MAX];
1971 size_t scratch_off;
1972 size_t scratch_start;
1973 size_t off;
1974 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1975 unsigned int rd_off;
1976
1978 "Resolution succeeded for `%s' in zone %s, got %u records\n",
1979 rh->ac_tail->label,
1981 rd_count);
1982 if (0 == rd_count)
1983 {
1985 _ ("GNS lookup failed (zero records found for `%s')\n"),
1986 rh->name);
1987 fail_resolution (rh);
1988 return;
1989 }
1990
1991 if (0 == rh->name_resolution_pos)
1992 {
1993 /* top-level match, are we done yet? */
1994 if ((rd_count > 0) &&
1997 {
1998 off = 0;
2000 rd[0].data_size,
2001 &off);
2002 if ((NULL == cname) ||
2003 (off != rd[0].data_size))
2004 {
2005 GNUNET_break_op (0);
2006 GNUNET_free (cname);
2007 fail_resolution (rh);
2008 return;
2009 }
2011 cname);
2012 GNUNET_free (cname);
2013 return;
2014 }
2015 if ((rd_count > 0) &&
2018 {
2020 rd[0].data);
2021 return;
2022 }
2023
2024
2025 /* If A/AAAA was requested,
2026 * but we got a GNS2DNS record */
2027 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2029 {
2030 for (unsigned int i = 0; i < rd_count; i++)
2031 {
2032 switch (rd[i].record_type)
2033 {
2035 {
2036 /* delegation to DNS */
2038 "Found GNS2DNS record, delegating to DNS!\n");
2039 if (GNUNET_OK ==
2041 rd_count,
2042 rd))
2043 return;
2044 else
2045 goto fail;
2046 }
2047
2048 default:
2049 break;
2050 } /* end: switch */
2051 } /* end: for rd */
2052 } /* end: name_resolution_pos */
2053 /* convert relative names in record values to absolute names,
2054 using 'scratch' array for memory allocations */
2055 scratch_off = 0;
2056 rd_off = 0;
2057 for (unsigned int i = 0; i < rd_count; i++)
2058 {
2059 GNUNET_assert (rd_off <= i);
2060 if ((((0 != rh->protocol) &&
2061 (0 != rh->service)) || (NULL != rh->prefix)) &&
2066 continue;
2067 /* we _only_ care about boxed records */
2068
2069 GNUNET_assert (rd_off < rd_count);
2070 rd_new[rd_off] = rd[i];
2071 /* Check if the embedded name(s) end in "+", and if so,
2072 replace the "+" with the zone at "ac_tail", changing the name
2073 to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2074 so we can free it afterwards. */
2075 switch (rd[i].record_type)
2076 {
2078 {
2079 char *rname;
2080 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2081 rname = translate_dot_plus (rh, rname);
2082 GNUNET_break (NULL != rname);
2083 scratch_start = scratch_off;
2084 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2085 scratch_off += strlen (rname) + 1;
2086 GNUNET_assert (rd_off < rd_count);
2087 rd_new[rd_off].data = &scratch[scratch_start];
2088 rd_new[rd_off].data_size = scratch_off - scratch_start;
2089 rd_off++;
2090 GNUNET_free (rname);
2091 }
2092 break;
2093
2095 {
2096 char *cname_tmp;
2097
2098 off = 0;
2099 cname_tmp = GNUNET_DNSPARSER_parse_name (rd[i].data,
2100 rd[i].data_size,
2101 &off);
2102 if ((NULL == cname_tmp) ||
2103 (off != rd[i].data_size))
2104 {
2105 GNUNET_break_op (0); /* record not well-formed */
2106 }
2107 else
2108 {
2109 cname_tmp = translate_dot_plus (rh, cname_tmp);
2110 GNUNET_break (NULL != cname_tmp);
2111 scratch_start = scratch_off;
2112 if (GNUNET_OK !=
2114 sizeof(scratch),
2115 &scratch_off,
2116 cname_tmp))
2117 {
2118 GNUNET_break (0);
2119 }
2120 else
2121 {
2122 GNUNET_assert (rd_off < rd_count);
2123 rd_new[rd_off].data = &scratch[scratch_start];
2124 rd_new[rd_off].data_size = scratch_off - scratch_start;
2125 rd_off++;
2126 }
2127 }
2128 GNUNET_free (cname_tmp);
2129 }
2130 break;
2131
2133 {
2134 struct GNUNET_DNSPARSER_SoaRecord *soa;
2135
2136 off = 0;
2138 rd[i].data_size,
2139 &off);
2140 if ((NULL == soa) ||
2141 (off != rd[i].data_size))
2142 {
2143 GNUNET_break_op (0); /* record not well-formed */
2144 }
2145 else
2146 {
2147 soa->mname = translate_dot_plus (rh, soa->mname);
2148 soa->rname = translate_dot_plus (rh, soa->rname);
2149 scratch_start = scratch_off;
2150 if (GNUNET_OK !=
2152 sizeof(scratch),
2153 &scratch_off,
2154 soa))
2155 {
2156 GNUNET_break (0);
2157 }
2158 else
2159 {
2160 GNUNET_assert (rd_off < rd_count);
2161 rd_new[rd_off].data = &scratch[scratch_start];
2162 rd_new[rd_off].data_size = scratch_off - scratch_start;
2163 rd_off++;
2164 }
2165 }
2166 if (NULL != soa)
2168 }
2169 break;
2170
2172 {
2173 struct GNUNET_DNSPARSER_MxRecord *mx;
2174
2175 off = 0;
2177 rd[i].data_size,
2178 &off);
2179 if ((NULL == mx) ||
2180 (off != rd[i].data_size))
2181 {
2182 GNUNET_break_op (0); /* record not well-formed */
2183 }
2184 else
2185 {
2186 mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2187 scratch_start = scratch_off;
2188 if (GNUNET_OK !=
2190 sizeof(scratch),
2191 &scratch_off,
2192 mx))
2193 {
2194 GNUNET_break (0);
2195 }
2196 else
2197 {
2198 GNUNET_assert (rd_off < rd_count);
2199 rd_new[rd_off].data = &scratch[scratch_start];
2200 rd_new[rd_off].data_size = scratch_off - scratch_start;
2201 rd_off++;
2202 }
2203 }
2204 if (NULL != mx)
2206 }
2207 break;
2208
2210 {
2211 struct GNUNET_DNSPARSER_SrvRecord *srv;
2212
2213 off = 0;
2215 rd[i].data_size,
2216 &off);
2217 if ((NULL == srv) ||
2218 (off != rd[i].data_size))
2219 {
2220 GNUNET_break_op (0); /* record not well-formed */
2221 }
2222 else
2223 {
2224 srv->target = translate_dot_plus (rh, srv->target);
2225 scratch_start = scratch_off;
2226 if (GNUNET_OK !=
2228 sizeof(scratch),
2229 &scratch_off,
2230 srv))
2231 {
2232 GNUNET_break (0);
2233 }
2234 else
2235 {
2236 GNUNET_assert (rd_off < rd_count);
2237 rd_new[rd_off].data = &scratch[scratch_start];
2238 rd_new[rd_off].data_size = scratch_off - scratch_start;
2239 rd_off++;
2240 }
2241 }
2242 if (NULL != srv)
2244 }
2245 break;
2246
2248 {
2250
2251 off = 0;
2253 rd[i].data_size,
2254 &off);
2255 if ((NULL == uri) ||
2256 (off != rd[i].data_size))
2257 {
2259 _ ("Failed to deserialize URI record with target\n"));
2260 GNUNET_break_op (0); /* record not well-formed */
2261 }
2262 else
2263 {
2264 scratch_start = scratch_off;
2265 if (GNUNET_OK !=
2267 sizeof(scratch),
2268 &scratch_off,
2269 uri))
2270 {
2271 GNUNET_break (0);
2272 }
2273 else
2274 {
2275 GNUNET_assert (rd_off < rd_count);
2276 rd_new[rd_off].data = &scratch[scratch_start];
2277 rd_new[rd_off].data_size = scratch_off - scratch_start;
2278 rd_off++;
2279 }
2280 }
2281 if (NULL != uri)
2283 }
2284 break;
2285
2288 {
2290 if (rd[i].data_size < sizeof(uint32_t))
2291 {
2292 GNUNET_break_op (0);
2293 break;
2294 }
2295 if (GNUNET_OK !=
2297 rd[i].data_size,
2298 rd[i].record_type,
2299 &pubkey))
2300 {
2301 GNUNET_break_op (0);
2302 break;
2303 }
2304 rd_off++;
2305 if (rd[i].record_type != rh->record_type)
2306 {
2307 /* try to resolve "@" */
2308 struct AuthorityChain *ac;
2309
2310 ac = GNUNET_new (struct AuthorityChain);
2311 ac->rh = rh;
2316 rh->ac_tail,
2317 ac);
2319 rh);
2320 return;
2321 }
2322 }
2323 break;
2324
2326 {
2327 /* delegation to DNS */
2329 {
2330 rd_off++;
2331 break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2332 }
2334 "Found GNS2DNS record, delegating to DNS!\n");
2335 if (GNUNET_OK ==
2337 rd_count,
2338 rd))
2339 return;
2340 else
2341 goto fail;
2342 }
2343
2345 {
2346 /* unbox SRV/TLSA records if a specific one was requested */
2347 if ((0 != rh->protocol) &&
2348 (0 != rh->service) &&
2349 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2350 {
2351 const struct GNUNET_GNSRECORD_BoxRecord *box;
2352
2353 box = rd[i].data;
2355 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2356 ntohs (box->protocol), ntohs (box->service),
2357 rh->protocol, rh->service);
2358 if ((ntohs (box->protocol) == rh->protocol) &&
2359 (ntohs (box->service) == rh->service))
2360 {
2361 /* Box matches, unbox! */
2362 GNUNET_assert (rd_off < rd_count);
2363 rd_new[rd_off].record_type = ntohl (box->record_type);
2364 rd_new[rd_off].data_size -= sizeof(struct
2366 rd_new[rd_off].data = &box[1];
2367 rd_off++;
2368 }
2369 }
2370 else
2371 {
2372 /* no specific protocol/service specified, preserve all BOX
2373 records (for modern, GNS-enabled applications) */
2374 rd_off++;
2375 }
2376 break;
2377 }
2379 {
2380 /* unbox SBOX records if a specific one was requested */
2381 if ((rh->prefix != NULL) &&
2382 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2383 {
2384 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2385 const char *prefix;
2386 size_t prefix_len;
2387
2388 box = rd[i].data;
2389 prefix = rd[i].data + sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
2390 prefix_len = strnlen (
2391 prefix,
2392 rd[i].data_size - sizeof(struct GNUNET_GNSRECORD_SBoxRecord)) + 1;
2393 if (prefix_len - 1 >= rd[i].data_size - sizeof(struct
2395 {
2397 "SBOX record with invalid prefix length, maybe not null-terminated\n");
2398 continue;
2399 }
2401 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2402 prefix, rh->prefix);
2403 if (strcmp (rh->prefix, prefix) == 0)
2404 {
2405 /* Box matches, unbox! */
2406 GNUNET_assert (rd_off < rd_count);
2407 rd_new[rd_off].record_type = ntohl (box->record_type);
2408 rd_new[rd_off].data_size -= sizeof(struct
2410 + prefix_len;
2411 rd_new[rd_off].data = rd[i].data
2412 + sizeof(struct GNUNET_GNSRECORD_SBoxRecord)
2413 + prefix_len;
2414 rd_off++;
2415 }
2416 }
2417 else
2418 {
2420 _ (
2421 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2422 rh->name);
2423 /* no specific protocol/service specified, preserve all SBOX
2424 records (for modern, GNS-enabled applications) */
2425 rd_off++;
2426 }
2427 break;
2428 }
2429 default:
2430 rd_off++;
2431 break;
2432 } /* end: switch */
2433 } /* end: for rd_count */
2434
2435 GNUNET_free (rh->prefix);
2436 rh->prefix = NULL;
2437
2438 /* yes, we are done, return result */
2440 "Returning GNS response for `%s' with %u answers\n",
2441 rh->ac_tail->label,
2442 rd_off);
2443 rh->proc (rh->proc_cls,
2444 rd_off,
2445 rd_new);
2447 rh);
2448 return;
2449 }
2450
2451 switch (rd[0].record_type)
2452 {
2454 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2456 &rd[0]);
2457 return;
2458
2460 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2462 &rd[0]);
2463 return;
2464
2467 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2469 &rd[0]);
2470 return;
2471
2473 if (GNUNET_OK ==
2475 rd_count,
2476 rd))
2477 return;
2478 break;
2479 default:
2481 return;
2483 _ ("Unable to process critical delegation record\n"));
2484 break;
2485 }
2486fail:
2488 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2489 fail_resolution (rh);
2490}
2491
2492
2501static void
2503 int32_t success,
2504 const char *emsg)
2505{
2506 struct CacheOps *co = cls;
2507
2508 co->namecache_qe_cache = NULL;
2509 if (GNUNET_OK != success)
2511 _ ("Failed to cache GNS resolution: %s\n"),
2512 emsg);
2514 co_tail,
2515 co);
2516 GNUNET_free (co);
2517}
2518
2519
2538static void
2540 struct GNUNET_TIME_Absolute exp,
2541 const struct GNUNET_HashCode *key,
2542 const struct GNUNET_PeerIdentity *trunc_peer,
2543 const struct GNUNET_DHT_PathElement *get_path,
2544 unsigned int get_path_length,
2545 const struct GNUNET_DHT_PathElement *put_path,
2546 unsigned int put_path_length,
2548 size_t size,
2549 const void *data)
2550{
2551 struct GNS_ResolverHandle *rh = cls;
2552 struct AuthorityChain *ac = rh->ac_tail;
2553 const struct GNUNET_GNSRECORD_Block *block;
2554 struct CacheOps *co;
2555
2556 (void) exp;
2557 (void) key;
2558 (void) get_path;
2559 (void) get_path_length;
2560 (void) put_path;
2561 (void) put_path_length;
2562 (void) type;
2564 rh->get_handle = NULL;
2566 rh->dht_heap_node = NULL;
2567 /* must be cleared before handle_gns_resolution_result() below gets
2568 to schedule the next step */
2569 if (NULL != rh->task_id)
2570 {
2572 rh->task_id = NULL;
2573 }
2575 "Handling response from the DHT\n");
2576 if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2577 {
2578 /* how did this pass DHT block validation!? */
2579 GNUNET_break (0);
2580 fail_resolution (rh);
2581 return;
2582 }
2583 block = data;
2585 {
2586 /* how did this pass DHT block validation!? */
2587 GNUNET_break (0);
2588 fail_resolution (rh);
2589 return;
2590 }
2592 "Decrypting DHT block of size %llu for `%s', expires %s\n",
2593 (unsigned long long) GNUNET_GNSRECORD_block_get_size (block),
2594 rh->name,
2596 if (GNUNET_OK !=
2599 ac->label,
2601 rh))
2602 {
2603 GNUNET_break_op (0); /* block was ill-formed */
2604 fail_resolution (rh);
2605 return;
2606 }
2609 rel_value_us)
2610 {
2612 "Received expired block from the DHT, will not cache it.\n");
2613 return;
2614 }
2616 return;
2617 /* Cache well-formed blocks */
2619 "Caching response from the DHT in namecache\n");
2620 co = GNUNET_new (struct CacheOps);
2622 block,
2623 &
2625 co);
2627 co_tail,
2628 co);
2629}
2630
2631
2638static void
2640 const struct GNUNET_HashCode *query);
2641
2642
2650static void
2652{
2653 struct GNS_ResolverHandle *rh = cls;
2654 struct GNUNET_HashCode query = rh->dht_query;
2655
2656 rh->task_id = NULL;
2658 rh->get_handle = NULL;
2660 rh->dht_heap_node = NULL;
2662 {
2664 _ ("DHT lookup for `%s' timed out\n"),
2665 rh->name);
2666 fail_resolution (rh);
2667 return;
2668 }
2669 rh->dht_retries++;
2671 "DHT lookup for `%s' under key %s timed out, retrying (%u/%u)\n",
2672 rh->name,
2673 GNUNET_h2s (&query),
2674 rh->dht_retries,
2675 (unsigned int) DHT_LOOKUP_RETRIES);
2677 &query);
2678}
2679
2680
2681static void
2683 const struct GNUNET_HashCode *query)
2684{
2685 struct GNS_ResolverHandle *rx;
2686
2687 GNUNET_assert (NULL == rh->get_handle);
2688 rh->dht_query = *query;
2691 query,
2694 NULL, 0,
2695 &handle_dht_response, rh);
2697 rh,
2699 abs_value_us);
2700 GNUNET_assert (NULL == rh->task_id);
2703 rh);
2706 {
2707 /* fail longest-standing DHT request */
2709 GNUNET_assert (NULL != rx);
2710 rx->dht_heap_node = NULL;
2711 if (NULL != rx->task_id)
2712 {
2714 rx->task_id = NULL;
2715 }
2716 fail_resolution (rx);
2717 }
2718}
2719
2720
2729static void
2731 unsigned int rd_count,
2732 const struct GNUNET_GNSRECORD_Data *rd)
2733{
2734 struct GNS_ResolverHandle *rh = cls;
2735
2736 if (0 == rd_count)
2738 _ ("GNS namecache returned empty result for `%s'\n"),
2739 rh->name);
2741 rd_count,
2742 rd);
2743}
2744
2745
2752static void
2754 const struct GNUNET_GNSRECORD_Block *block)
2755{
2756 struct GNS_ResolverHandle *rh = cls;
2757 struct AuthorityChain *ac = rh->ac_tail;
2758 const char *label = ac->label;
2759 const struct GNUNET_CRYPTO_BlindablePublicKey *auth =
2761 struct GNUNET_HashCode query;
2762
2763 GNUNET_assert (NULL != rh->namecache_qe);
2764 rh->namecache_qe = NULL;
2765 if (NULL == block)
2767 "No block found\n");
2768 else
2770 "Got block with expiration %s\n",
2773 if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2775 (ac != rh->ac_head))) &&
2776 ((NULL == block) ||
2779 rel_value_us)))
2780 {
2781 /* namecache knows nothing; try DHT lookup */
2783 label,
2784 &query);
2786 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2787 ac->label,
2789 GNUNET_h2s (&query));
2790 start_dht_request (rh, &query);
2791 return;
2792 }
2793
2794 if ((NULL == block) ||
2797 rel_value_us))
2798 {
2799 /* DHT not permitted and no local result, fail */
2801 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2802 ac->label,
2804 fail_resolution (rh);
2805 return;
2806 }
2808 "Received result from namecache for label `%s'\n",
2809 ac->label);
2810
2811 if (GNUNET_OK !=
2813 auth,
2814 label,
2816 rh))
2817 {
2818 GNUNET_break_op (0); /* block was ill-formed */
2819 /* try DHT instead */
2821 label,
2822 &query);
2824 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2825 ac->label,
2827 GNUNET_h2s (&query));
2828 start_dht_request (rh, &query);
2829 return;
2830 }
2831}
2832
2833
2839static void
2841{
2842 struct AuthorityChain *ac = rh->ac_tail;
2843 struct GNUNET_HashCode query;
2844
2846 "Starting GNS resolution for `%s' in zone %s\n",
2847 ac->label,
2850 ac->label,
2851 &query);
2853 {
2854 rh->namecache_qe
2856 &query,
2858 rh);
2859 GNUNET_assert (NULL != rh->namecache_qe);
2860 }
2861 else
2862 {
2864 &query);
2865 }
2866}
2867
2868
2875static void
2877 int is_valid)
2878{
2879 struct GNS_ResolverHandle *rh = cls;
2880 struct AuthorityChain *ac = rh->ac_tail;
2881
2882 rh->rev_check = NULL;
2883 if (GNUNET_YES != is_valid)
2884 {
2886 _ ("Zone %s was revoked, resolution fails\n"),
2889 return;
2890 }
2892}
2893
2894
2900static void
2902{
2903 struct AuthorityChain *ac = rh->ac_tail;
2904
2906 "Starting revocation check for zone %s\n",
2911 rh);
2912 GNUNET_assert (NULL != rh->rev_check);
2913}
2914
2915
2916static void
2918{
2919 struct GNS_ResolverHandle *rh = cls;
2920
2921 rh->task_id = NULL;
2922 if (rh->loop_threshold < rh->loop_limiter++)
2923 {
2925 "Encountered unbounded recursion resolving `%s'\n",
2926 rh->name);
2927 fail_resolution (rh);
2928 return;
2929 }
2930 if (GNUNET_YES == rh->ac_tail->gns_authority)
2932 else
2934}
2935
2936
2937static void
2939{
2940 struct GNS_ResolverHandle *rh = cls;
2941 struct AuthorityChain *ac;
2942 struct in_addr v4;
2943 struct in6_addr v6;
2944
2945 rh->task_id = NULL;
2946 if (1 == inet_pton (AF_INET,
2947 rh->name,
2948 &v4))
2949 {
2950 /* name is IPv4 address, pretend it's an A record */
2952
2953 rd.data = &v4;
2954 rd.data_size = sizeof(v4);
2955 rd.expiration_time = UINT64_MAX;
2957 rd.flags = 0;
2958 rh->proc (rh->proc_cls,
2959 1,
2960 &rd);
2961 GNUNET_assert (NULL == rh->task_id);
2963 rh);
2964 return;
2965 }
2966 if (1 == inet_pton (AF_INET6,
2967 rh->name,
2968 &v6))
2969 {
2970 /* name is IPv6 address, pretend it's an AAAA record */
2972
2973 rd.data = &v6;
2974 rd.data_size = sizeof(v6);
2975 rd.expiration_time = UINT64_MAX;
2977 rd.flags = 0;
2978 rh->proc (rh->proc_cls,
2979 1,
2980 &rd);
2981 GNUNET_assert (NULL == rh->task_id);
2983 rh);
2984 return;
2985 }
2986
2987 ac = GNUNET_new (struct AuthorityChain);
2988 ac->rh = rh;
2990 if (NULL == ac->label)
2991 /* name was just the "TLD", so we default to label
2992 #GNUNET_GNS_EMPTY_LABEL_AT */
2997 rh->ac_tail,
2998 ac);
3000 rh);
3001}
3002
3003
3018struct GNS_ResolverHandle *
3020 uint32_t record_type,
3021 const char *name,
3023 uint16_t recursion_depth_limit,
3025 void *proc_cls)
3026{
3027 struct GNS_ResolverHandle *rh;
3028
3030 "Starting lookup for `%s'\n",
3031 name);
3032 rh = GNUNET_new (struct GNS_ResolverHandle);
3034 rlh_tail,
3035 rh);
3036 rh->authority_zone = *zone;
3037 rh->proc = proc;
3038 rh->proc_cls = proc_cls;
3039 rh->options = options;
3041 rh->name = GNUNET_strdup (name);
3042 rh->name_resolution_pos = strlen (name);
3043 rh->loop_threshold = recursion_depth_limit;
3045 rh);
3046 return rh;
3047}
3048
3049
3055void
3057{
3058 struct DnsResult *dr;
3059 struct AuthorityChain *ac;
3060
3062 rlh_tail,
3063 rh);
3064 if (NULL != rh->dns_request)
3065 {
3067 rh->dns_request = NULL;
3068 }
3069 while (NULL != (ac = rh->ac_head))
3070 {
3072 rh->ac_tail,
3073 ac);
3074 if (GNUNET_NO == ac->gns_authority)
3075 {
3076 struct Gns2DnsPending *gp;
3077
3078 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
3079 {
3082 gp);
3083 if (NULL != gp->rh)
3084 {
3085 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
3086 using GNS_resolver_lookup_cancel here, we need to
3087 add it first... */
3089 rlh_tail,
3090 gp->rh);
3091 GNUNET_assert (NULL == gp->rh->task_id);
3094 gp->rh);
3095 gp->rh = NULL;
3096 }
3097 if (NULL != gp->dns_rh)
3098 {
3100 gp->dns_rh = NULL;
3101 }
3102 GNUNET_free (gp);
3103 }
3105 }
3106 GNUNET_free (ac->label);
3107 GNUNET_free (ac);
3108 }
3109 if (NULL != rh->task_id)
3110 {
3112 rh->task_id = NULL;
3113 }
3114 if (NULL != rh->get_handle)
3115 {
3117 rh->get_handle = NULL;
3118 }
3119 if (NULL != rh->dht_heap_node)
3120 {
3122 rh->dht_heap_node = NULL;
3123 }
3124 if (NULL != rh->namecache_qe)
3125 {
3127 rh->namecache_qe = NULL;
3128 }
3129 if (NULL != rh->rev_check)
3130 {
3132 rh->rev_check = NULL;
3133 }
3134 if (NULL != rh->std_resolve)
3135 {
3137 "Canceling standard DNS resolution\n");
3139 rh->std_resolve = NULL;
3140 }
3141 while (NULL != (dr = rh->dns_result_head))
3142 {
3145 dr);
3146 GNUNET_free (dr);
3147 }
3148 if (NULL != rh->prefix)
3149 {
3151 rh->prefix = NULL;
3152 }
3153 GNUNET_free (rh->leho);
3154 GNUNET_free (rh->name);
3155 GNUNET_free (rh);
3156}
3157
3158
3159/* ***************** Resolver initialization ********************* */
3160
3161
3170void
3172 struct GNUNET_DHT_Handle *dht,
3173 const struct GNUNET_CONFIGURATION_Handle *c,
3174 unsigned long long max_bg_queries)
3175{
3176 cfg = c;
3178 dht_handle = dht;
3181 max_allowed_background_queries = max_bg_queries;
3183 "namecache",
3184 "DISABLE");
3187 "Namecache disabled\n");
3188}
3189
3190
3194void
3196{
3197 struct GNS_ResolverHandle *rh;
3198 struct CacheOps *co;
3199
3200 /* abort active resolutions */
3201 while (NULL != (rh = rlh_head))
3202 {
3203 rh->proc (rh->proc_cls,
3204 0,
3205 NULL);
3207 }
3208 while (NULL != (co = co_head))
3209 {
3211 co_tail,
3212 co);
3214 GNUNET_free (co);
3215 }
3217 dht_lookup_heap = NULL;
3218 dht_handle = NULL;
3219 namecache_handle = NULL;
3220}
3221
3222
3223/* 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 struct GNUNET_CRYPTO_BlindablePublicKey pubkey
Public key of the zone to look in.
static char * name
Name (label) of the records to list.
static struct GNUNET_NAMECACHE_Handle * ns
Handle to the namecache.
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 DHT_LOOKUP_TIMEOUT
Default DHT timeout for lookups.
#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 dht_lookup_timeout(void *cls)
The DHT did not answer within DHT_LOOKUP_TIMEOUT.
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.
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_CRYPTO_BlindablePublicKey *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 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.
#define DHT_LOOKUP_RETRIES
How often do we restart a DHT lookup that stayed unanswered for DHT_LOOKUP_TIMEOUT before we give up ...
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_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(uint32_t i)
Produce a random value.
void GNUNET_DHT_get_stop(struct GNUNET_DHT_GetHandle *get_handle)
Stop async DHT-get.
Definition dht_api.c:1238
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:1165
@ 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:473
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:1013
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition dnsparser.c:978
#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:156
#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:428
void GNUNET_DNSPARSER_free_uri(struct GNUNET_DNSPARSER_UriRecord *uri)
Free URI information record.
Definition dnsparser.c:171
#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:1205
#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:555
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:514
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:371
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:1127
void GNUNET_DNSPARSER_free_soa(struct GNUNET_DNSPARSER_SoaRecord *soa)
Free SOA information record.
Definition dnsparser.c:125
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:1246
void GNUNET_DNSPARSER_free_mx(struct GNUNET_DNSPARSER_MxRecord *mx)
Free MX information record.
Definition dnsparser.c:186
#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:1428
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:1283
#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:756
#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:585
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:612
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition dnsstub.c:704
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:525
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition dnsstub.c:561
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:664
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.
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_CRYPTO_BlindablePublicKey *pkey)
Convert an absolute domain name to the respective public key.
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_CRYPTO_BlindablePublicKey *z)
Convert a zone to a string (for printing debug messages).
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_CRYPTO_BlindablePublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls)
Decrypt block.
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_BlindablePublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_CRYPTO_BlindablePublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
#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
void GNUNET_GNSRECORD_query_from_public_key(const struct GNUNET_CRYPTO_BlindablePublicKey *pub, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
#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.
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_BlindablePublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.
void GNUNET_REVOCATION_query_cancel(struct GNUNET_REVOCATION_Query *q)
Cancel key revocation check.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
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:1310
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:1283
#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:671
#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::@63::@64 dns_authority
struct AuthorityChain * next
This is a DLL.
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?
union AuthorityChain::@63 authority_info
Information about the resolver authority for this label.
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.
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_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 GNUNET_CRYPTO_BlindablePublicKey authority_zone
The top-level GNS authoritative zone to query.
struct DnsResult * dns_result_head
DLL of results we got from DNS.
struct AuthorityChain * ac_head
DLL to store the authority chain.
unsigned int dht_retries
How many times did we already restart the DHT GET in get_handle because it did not answer within DHT_...
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.
struct GNUNET_HashCode dht_query
Key of the DHT GET in get_handle, so that we can re-issue it when it times out.
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?
union GNUNET_DNSPARSER_Record::@24 data
Payload of the record (which one of these is valid depends on the 'type').
char * name
Name of the record that the query is for (0-terminated).
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
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:141
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?