GNUnet 0.22.2
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
132{
137
142
147
151 char *label;
152
158
162 union
163 {
168
169 struct
170 {
177
183
189
194
199 int found;
200
207};
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
253{
258
263
268
273
277 void *proc_cls;
278
283
284
289
294
299
304
310
315
320
325
329 char *name;
330
335 char *leho;
336
341
346
351
356
362
368
372 char *prefix;
373
374
379
385 unsigned int loop_limiter;
386
390 unsigned int loop_threshold;
391
396};
397
398
403{
407 struct CacheOps *next;
408
412 struct CacheOps *prev;
413
418};
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 size_t buf_off;
994 size_t buf_start;
995
996 buf_off = 0;
997 skip = 0;
998 memset (rd,
999 0,
1000 sizeof(rd));
1001 for (unsigned int i = 0; i < rd_count; i++)
1002 {
1003 if (i < p->num_answers)
1004 rec = &p->answers[i];
1005 else if (i < p->num_answers + p->num_authority_records)
1006 rec = &p->authority_records[i - p->num_answers];
1007 else
1008 rec = &p->additional_records[i - p->num_answers
1009 - p->num_authority_records];
1010 /* As we copied the full DNS name to 'rh->ac_tail->label', this
1011 should be the correct check to see if this record is actually
1012 a record for our label... */
1013 if (0 != strcmp (rec->name,
1014 rh->ac_tail->label))
1015 {
1017 "Dropping record `%s', does not match desired name `%s'\n",
1018 rec->name,
1019 rh->ac_tail->label);
1020 skip++;
1021 continue;
1022 }
1023 rd[i - skip].record_type = rec->type;
1025 switch (rec->type)
1026 {
1028 if (rec->data.raw.data_len != sizeof(struct in_addr))
1029 {
1030 GNUNET_break_op (0);
1031 skip++;
1032 continue;
1033 }
1034 rd[i - skip].data_size = rec->data.raw.data_len;
1035 rd[i - skip].data = rec->data.raw.data;
1036 break;
1037
1039 if (rec->data.raw.data_len != sizeof(struct in6_addr))
1040 {
1041 GNUNET_break_op (0);
1042 skip++;
1043 continue;
1044 }
1045 rd[i - skip].data_size = rec->data.raw.data_len;
1046 rd[i - skip].data = rec->data.raw.data;
1047 break;
1048
1052 buf_start = buf_off;
1053 if (GNUNET_OK !=
1055 sizeof(buf),
1056 &buf_off,
1057 rec->data.hostname))
1058 {
1059 GNUNET_break (0);
1060 skip++;
1061 continue;
1062 }
1063 rd[i - skip].data_size = buf_off - buf_start;
1064 rd[i - skip].data = &buf[buf_start];
1065 break;
1066
1068 buf_start = buf_off;
1069 if (GNUNET_OK !=
1071 sizeof(buf),
1072 &buf_off,
1073 rec->data.soa))
1074 {
1075 GNUNET_break (0);
1076 skip++;
1077 continue;
1078 }
1079 rd[i - skip].data_size = buf_off - buf_start;
1080 rd[i - skip].data = &buf[buf_start];
1081 break;
1082
1084 buf_start = buf_off;
1085 if (GNUNET_OK !=
1087 sizeof(buf),
1088 &buf_off,
1089 rec->data.mx))
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.srv))
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.uri))
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
1131 default:
1133 _ ("Skipping record of unsupported type %d\n"),
1134 rec->type);
1135 skip++;
1136 continue;
1137 }
1138 } /* end of for all records in answer */
1139 if (NULL != rh->leho)
1140 {
1144 rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1145 rd[rd_count - skip].data = rh->leho;
1146 rd[rd_count - skip].data_size = strlen (rh->leho);
1147 skip--; /* skip one LESS */
1149 "Adding LEHO %s\n",
1150 rh->leho);
1151 }
1153 "Returning DNS response for `%s' with %u answers\n",
1154 rh->ac_tail->label,
1155 (unsigned int) (rd_count - skip));
1156 rh->proc (rh->proc_cls,
1157 rd_count - skip,
1158 rd);
1160 rh->dns_request = NULL;
1161 }
1163 if (NULL != rh->task_id)
1164 GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1166 rh);
1167}
1168
1169
1178static void
1180{
1181 struct AuthorityChain *ac;
1182 struct GNUNET_DNSPARSER_Query *query;
1183 struct GNUNET_DNSPARSER_Packet *p;
1184 char *dns_request;
1185 size_t dns_request_length;
1186 int ret;
1187
1188 ac = rh->ac_tail;
1189 GNUNET_assert (NULL != ac);
1191 "Starting DNS lookup for `%s'\n",
1192 ac->label);
1194 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1195 query->name = GNUNET_strdup (ac->label);
1196 query->type = rh->record_type;
1199 p->queries = query;
1200 p->num_queries = 1;
1202 UINT16_MAX);
1203 p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1204 p->flags.recursion_desired = 1;
1206 1024,
1207 &dns_request,
1208 &dns_request_length);
1209 if (GNUNET_OK != ret)
1210 {
1211 GNUNET_break (0);
1212 rh->proc (rh->proc_cls,
1213 0,
1214 NULL);
1215 GNUNET_assert (NULL == rh->task_id);
1217 rh);
1218 }
1219 else
1220 {
1221 rh->original_dns_id = p->id;
1223 GNUNET_assert (NULL == rh->dns_request);
1224 rh->leho = GNUNET_strdup (ac->label);
1227 dns_request,
1228 dns_request_length,
1230 rh);
1233 rh);
1234 }
1235 if (GNUNET_SYSERR != ret)
1236 GNUNET_free (dns_request);
1238}
1239
1240
1249static void
1251 const char *rname)
1252{
1253 size_t nlen;
1254 char *res;
1255 const char *tld;
1256 struct AuthorityChain *ac;
1257 int af;
1258 struct GNUNET_CRYPTO_PublicKey zone;
1259
1261 "Handling GNS REDIRECT result `%s'\n",
1262 rname);
1263 nlen = strlen (rname);
1264 tld = GNS_get_tld (rname);
1265 if (0 == strcmp ("+", tld))
1266 {
1267 /* REDIRECT resolution continues relative to current domain */
1268 if (0 == rh->name_resolution_pos)
1269 {
1270 res = GNUNET_strndup (rname, nlen - 2);
1271 rh->name_resolution_pos = nlen - 2;
1272 }
1273 else
1274 {
1276 "%.*s.%.*s",
1277 (int) rh->name_resolution_pos,
1278 rh->name,
1279 (int) (nlen - 2),
1280 rname);
1281 rh->name_resolution_pos = strlen (res);
1282 }
1283 GNUNET_free (rh->name);
1284 rh->name = res;
1285 ac = GNUNET_new (struct AuthorityChain);
1286 ac->rh = rh;
1291 /* add AC to tail */
1293 rh->ac_tail,
1294 ac);
1296 rh);
1297 return;
1298 }
1299 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1300 {
1301 /* REDIRECT resolution continues relative to current domain */
1302 if (0 == rh->name_resolution_pos)
1303 {
1305 "%.*s",
1306 (int) (strlen (rname) - (strlen (tld) + 1)),
1307 rname);
1308 }
1309 else
1310 {
1312 "%.*s.%.*s",
1313 (int) rh->name_resolution_pos,
1314 rh->name,
1315 (int) (strlen (rname) - (strlen (tld) + 1)),
1316 rname);
1317 }
1318 rh->name_resolution_pos = strlen (res);
1319 GNUNET_free (rh->name);
1320 rh->name = res;
1321 ac = GNUNET_new (struct AuthorityChain);
1322 ac->rh = rh;
1324 ac->authority_info.gns_authority = zone;
1326 /* add AC to tail */
1328 rh->ac_tail,
1329 ac);
1331 rh);
1332 return;
1333 }
1334
1336 "Got REDIRECT `%s' from GNS for `%s'\n",
1337 rname,
1338 rh->name);
1339 if (NULL != rh->std_resolve)
1340 {
1342 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1343 rh->name);
1345 }
1346 /* name is absolute, go to DNS */
1347 GNUNET_free (rh->name);
1348 rh->name = GNUNET_strdup (rname);
1349 rh->name_resolution_pos = strlen (rh->name);
1350 switch (rh->record_type)
1351 {
1353 af = AF_INET;
1354 break;
1355
1357 af = AF_INET6;
1358 break;
1359
1360 default:
1361 af = AF_UNSPEC;
1362 break;
1363 }
1365 "Doing standard DNS lookup for `%s'\n",
1366 rh->name);
1367
1369 af,
1372 rh);
1373}
1374
1375
1384static void
1386 const char *cname)
1387{
1388 int af;
1389
1390 GNUNET_free (rh->name);
1391 rh->name = GNUNET_strdup (cname);
1392 rh->name_resolution_pos = strlen (rh->name);
1393 switch (rh->record_type)
1394 {
1396 af = AF_INET;
1397 break;
1398
1400 af = AF_INET6;
1401 break;
1402
1403 default:
1404 af = AF_UNSPEC;
1405 break;
1406 }
1408 "Doing standard DNS lookup for `%s'\n",
1409 rh->name);
1410
1412 af,
1415 rh);
1416}
1417
1418
1426static void
1428 unsigned int rd_count,
1429 const struct GNUNET_GNSRECORD_Data *rd);
1430
1431
1439static void
1441{
1442 struct GNS_ResolverHandle *rh = ac->rh;
1443
1444 if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1446 return; /* more pending and none found yet */
1448 {
1450 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1452 fail_resolution (rh);
1453 return;
1454 }
1456 return; /* already running, do not launch again! */
1457 /* recurse */
1460 "Will continue resolution using DNS to resolve `%s'\n",
1461 ac->label);
1462 GNUNET_assert (NULL == rh->task_id);
1464 rh);
1465}
1466
1467
1476static void
1478 unsigned int rd_count,
1479 const struct GNUNET_GNSRECORD_Data *rd)
1480{
1481 struct Gns2DnsPending *gp = cls;
1482 struct AuthorityChain *ac = gp->ac;
1483
1486 gp);
1487 /* enable cleanup of 'rh' handle that automatically comes after we return,
1488 and which expects 'rh' to be in the #rlh_head DLL. */
1489 if (NULL != gp->rh)
1490 {
1492 rlh_tail,
1493 gp->rh);
1494 gp->rh = NULL;
1495 }
1496 GNUNET_free (gp);
1498 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1499 rd_count);
1500 /* find suitable A/AAAA record */
1501 for (unsigned int j = 0; j < rd_count; j++)
1502 {
1503 switch (rd[j].record_type)
1504 {
1506 {
1507 struct sockaddr_in v4;
1508
1509 if (sizeof(struct in_addr) != rd[j].data_size)
1510 {
1511 GNUNET_break_op (0);
1512 continue;
1513 }
1514 memset (&v4,
1515 0,
1516 sizeof(v4));
1517 v4.sin_family = AF_INET;
1518 v4.sin_port = htons (53);
1519#if HAVE_SOCKADDR_IN_SIN_LEN
1520 v4.sin_len = (u_char) sizeof(v4);
1521#endif
1522 GNUNET_memcpy (&v4.sin_addr,
1523 rd[j].data,
1524 sizeof(struct in_addr));
1525 if (GNUNET_OK ==
1528 (const struct sockaddr *) &v4))
1530 break;
1531 }
1532
1534 {
1535 struct sockaddr_in6 v6;
1536
1537 if (sizeof(struct in6_addr) != rd[j].data_size)
1538 {
1539 GNUNET_break_op (0);
1540 continue;
1541 }
1542 /* FIXME: might want to check if we support IPv6 here,
1543 and otherwise skip this one and hope we find another */
1544 memset (&v6,
1545 0,
1546 sizeof(v6));
1547 v6.sin6_family = AF_INET6;
1548 v6.sin6_port = htons (53);
1549#if HAVE_SOCKADDR_IN_SIN_LEN
1550 v6.sin6_len = (u_char) sizeof(v6);
1551#endif
1552 GNUNET_memcpy (&v6.sin6_addr,
1553 rd[j].data,
1554 sizeof(struct in6_addr));
1555 if (GNUNET_OK ==
1558 (const struct sockaddr *) &v6))
1560 break;
1561 }
1562
1563 default:
1564 break;
1565 }
1566 }
1568}
1569
1570
1578static void
1580 const struct sockaddr *addr,
1581 socklen_t addrlen)
1582{
1583 struct Gns2DnsPending *gp = cls;
1584 struct AuthorityChain *ac = gp->ac;
1585 struct sockaddr_storage ss;
1586 struct sockaddr_in *v4;
1587 struct sockaddr_in6 *v6;
1588
1589 if (NULL == addr)
1590 {
1591 /* DNS resolution finished */
1592 if (0 == gp->num_results)
1594 "Failed to use DNS to resolve name of DNS resolver\n");
1597 gp);
1598 GNUNET_free (gp);
1600 return;
1601 }
1602 GNUNET_memcpy (&ss,
1603 addr,
1604 addrlen);
1605 switch (ss.ss_family)
1606 {
1607 case AF_INET:
1608 v4 = (struct sockaddr_in *) &ss;
1609 v4->sin_port = htons (53);
1610 gp->num_results++;
1611 break;
1612
1613 case AF_INET6:
1614 v6 = (struct sockaddr_in6 *) &ss;
1615 v6->sin6_port = htons (53);
1616 gp->num_results++;
1617 break;
1618
1619 default:
1621 "Unsupported AF %d\n",
1622 ss.ss_family);
1623 return;
1624 }
1625 if (GNUNET_OK ==
1627 (struct sockaddr *) &ss))
1629}
1630
1631
1638static void
1640 const struct GNUNET_GNSRECORD_Data *rd)
1641{
1643 rd->data);
1644}
1645
1646
1653static void
1655 const struct GNUNET_GNSRECORD_Data *rd)
1656{
1657 char *cname;
1658 size_t off;
1659
1660 off = 0;
1662 rd->data_size,
1663 &off);
1664 if ((NULL == cname) ||
1665 (off != rd->data_size))
1666 {
1667 GNUNET_break_op (0); /* record not well-formed */
1668 GNUNET_free (cname);
1669 fail_resolution (rh);
1670 return;
1671 }
1673 cname);
1674 GNUNET_free (cname);
1675}
1676
1677
1684static void
1686 const struct GNUNET_GNSRECORD_Data *rd)
1687{
1688 struct AuthorityChain *ac;
1689 struct GNUNET_CRYPTO_PublicKey auth;
1690
1691 /* delegation to another zone */
1693 rd->data_size,
1694 rd->record_type,
1695 &auth))
1696 {
1697 GNUNET_break_op (0);
1698 fail_resolution (rh);
1699 return;
1700 }
1701 /* expand authority chain */
1702 ac = GNUNET_new (struct AuthorityChain);
1703 ac->rh = rh;
1705 ac->authority_info.gns_authority = auth;
1707 /* add AC to tail */
1709 rh->ac_tail,
1710 ac);
1711 /* recurse */
1713 rh);
1714}
1715
1716
1727static int
1729 unsigned int rd_count,
1730 const struct GNUNET_GNSRECORD_Data *rd)
1731{
1732 struct AuthorityChain *ac;
1733 const char *tld;
1734 char *ns;
1735
1736 ns = NULL;
1737 /* expand authority chain */
1738 ac = GNUNET_new (struct AuthorityChain);
1739 ac->rh = rh;
1741
1742 for (unsigned int i = 0; i < rd_count; i++)
1743 {
1744 char *ip;
1745 char *n;
1746 size_t off;
1747 struct Gns2DnsPending *gp;
1748 struct GNUNET_CRYPTO_PublicKey zone;
1749 struct sockaddr_in v4;
1750 struct sockaddr_in6 v6;
1751
1752 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1753 {
1757 GNUNET_free (ns);
1758 GNUNET_free (ac);
1759 return GNUNET_SYSERR;
1760 }
1761 off = 0;
1763 rd[i].data_size,
1764 &off);
1765 ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1766 if ((NULL == n) ||
1767 (NULL == ip))
1768 {
1769 GNUNET_break_op (0);
1770 GNUNET_free (n);
1771 GNUNET_free (ip);
1772 continue;
1773 }
1774
1775 off += strlen (ip) + 1;
1776
1777 if (off != rd[i].data_size)
1778 {
1779 GNUNET_break_op (0);
1780 GNUNET_free (n);
1781 GNUNET_free (ip);
1782 continue;
1783 }
1784 /* resolve 'ip' to determine the IP(s) of the DNS
1785 resolver to use for lookup of 'ns' */
1786 if (NULL != ns)
1787 {
1788 if (0 != strcasecmp (ns,
1789 n))
1790 {
1791 /* NS values must all be the same for all GNS2DNS records,
1792 anything else leads to insanity */
1793 GNUNET_break_op (0);
1794 GNUNET_free (n);
1795 GNUNET_free (ip);
1796 continue;
1797 }
1798 GNUNET_free (n);
1799 }
1800 else
1801 {
1802 ns = n;
1803 }
1804
1805 /* check if 'ip' is already an IPv4/IPv6 address */
1806 if ((1 == inet_pton (AF_INET,
1807 ip,
1808 &v4)) ||
1809 (1 == inet_pton (AF_INET6,
1810 ip,
1811 &v6)))
1812 {
1816 ip));
1818 GNUNET_free (ip);
1819 continue;
1820 }
1821 tld = GNS_get_tld (ip);
1822 if ((0 != strcmp (tld, "+")) &&
1823 (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1824 {
1825 /* 'ip' is a DNS name */
1826 gp = GNUNET_new (struct Gns2DnsPending);
1827 gp->ac = ac;
1830 gp);
1832 AF_UNSPEC,
1835 gp);
1836 GNUNET_free (ip);
1837 continue;
1838 }
1839 /* 'ip' should be a GNS name */
1840 gp = GNUNET_new (struct Gns2DnsPending);
1841 gp->ac = ac;
1844 gp);
1845 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1846 if (0 == strcmp (tld, "+"))
1847 {
1848 ip = translate_dot_plus (rh,
1849 ip);
1850 tld = GNS_get_tld (ip);
1851 if (GNUNET_OK !=
1853 &zone))
1854 {
1855 GNUNET_break_op (0);
1856 GNUNET_free (ip);
1857 continue;
1858 }
1859 }
1860 gp->rh->authority_zone = zone;
1862 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1863 ip,
1864 ns);
1865 gp->rh->name = ip;
1866 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1868 gp->rh->proc_cls = gp;
1871 gp->rh->loop_limiter = rh->loop_limiter + 1;
1872 gp->rh->loop_threshold = rh->loop_threshold;
1873 gp->rh->task_id
1875 gp->rh);
1876 } /* end 'for all records' */
1877
1878 if (NULL == ns)
1879 {
1880 /* not a single GNS2DNS record found */
1881 GNUNET_free (ac);
1882 return GNUNET_SYSERR;
1883 }
1885 strcpy (ac->authority_info.dns_authority.name,
1886 ns);
1887 /* for DNS recursion, the label is the full DNS name,
1888 created from the remainder of the GNS name and the
1889 name in the NS record */
1890 GNUNET_asprintf (&ac->label,
1891 "%.*s%s%s",
1892 (int) rh->name_resolution_pos,
1893 rh->name,
1894 (0 != rh->name_resolution_pos) ? "." : "",
1895 ns);
1896 GNUNET_free (ns);
1897
1898 {
1899 /* the GNS name is UTF-8 and may include multibyte chars.
1900 * We have to convert the combined name to a DNS-compatible IDNA.
1901 */
1902 char *tmp = ac->label;
1903
1904 if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1905 &ac->label,
1906 IDNA_ALLOW_UNASSIGNED))
1907 {
1909 _ ("Name `%s' cannot be converted to IDNA."),
1910 tmp);
1911 GNUNET_free (tmp);
1912 GNUNET_free (ac);
1913 return GNUNET_SYSERR;
1914 }
1915 GNUNET_free (tmp);
1916 }
1917
1919 rh->ac_tail,
1920 ac);
1921 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1922 {
1924 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1925 ac->label);
1926 GNUNET_free (ac->label);
1927 GNUNET_free (ac);
1928 return GNUNET_SYSERR;
1929 }
1931 return GNUNET_OK;
1932}
1933
1934
1935static void
1937 unsigned int rd_count,
1938 const struct GNUNET_GNSRECORD_Data *rd)
1939{
1940 struct GNS_ResolverHandle *rh = cls;
1941 char *cname;
1942 char scratch[UINT16_MAX];
1943 size_t scratch_off;
1944 size_t scratch_start;
1945 size_t off;
1946 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1947 unsigned int rd_off;
1948
1950 "Resolution succeeded for `%s' in zone %s, got %u records\n",
1951 rh->ac_tail->label,
1953 rd_count);
1954 if (0 == rd_count)
1955 {
1957 _ ("GNS lookup failed (zero records found for `%s')\n"),
1958 rh->name);
1959 fail_resolution (rh);
1960 return;
1961 }
1962
1963 if (0 == rh->name_resolution_pos)
1964 {
1965 /* top-level match, are we done yet? */
1966 if ((rd_count > 0) &&
1969 {
1970 off = 0;
1972 rd[0].data_size,
1973 &off);
1974 if ((NULL == cname) ||
1975 (off != rd[0].data_size))
1976 {
1977 GNUNET_break_op (0);
1978 GNUNET_free (cname);
1979 fail_resolution (rh);
1980 return;
1981 }
1983 cname);
1984 GNUNET_free (cname);
1985 return;
1986 }
1987 if ((rd_count > 0) &&
1990 {
1992 rd[0].data);
1993 return;
1994 }
1995
1996
1997 /* If A/AAAA was requested,
1998 * but we got a GNS2DNS record */
1999 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2001 {
2002 for (unsigned int i = 0; i < rd_count; i++)
2003 {
2004 switch (rd[i].record_type)
2005 {
2007 {
2008 /* delegation to DNS */
2010 "Found GNS2DNS record, delegating to DNS!\n");
2011 if (GNUNET_OK ==
2013 rd_count,
2014 rd))
2015 return;
2016 else
2017 goto fail;
2018 }
2019
2020 default:
2021 break;
2022 } /* end: switch */
2023 } /* end: for rd */
2024 } /* end: name_resolution_pos */
2025 /* convert relative names in record values to absolute names,
2026 using 'scratch' array for memory allocations */
2027 scratch_off = 0;
2028 rd_off = 0;
2029 for (unsigned int i = 0; i < rd_count; i++)
2030 {
2031 GNUNET_assert (rd_off <= i);
2032 if ((((0 != rh->protocol) &&
2033 (0 != rh->service)) || (NULL != rh->prefix)) &&
2038 continue;
2039 /* we _only_ care about boxed records */
2040
2041 GNUNET_assert (rd_off < rd_count);
2042 rd_new[rd_off] = rd[i];
2043 /* Check if the embedded name(s) end in "+", and if so,
2044 replace the "+" with the zone at "ac_tail", changing the name
2045 to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2046 so we can free it afterwards. */
2047 switch (rd[i].record_type)
2048 {
2050 {
2051 char *rname;
2052 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2053 rname = translate_dot_plus (rh, rname);
2054 GNUNET_break (NULL != rname);
2055 scratch_start = scratch_off;
2056 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2057 scratch_off += strlen (rname) + 1;
2058 GNUNET_assert (rd_off < rd_count);
2059 rd_new[rd_off].data = &scratch[scratch_start];
2060 rd_new[rd_off].data_size = scratch_off - scratch_start;
2061 rd_off++;
2062 GNUNET_free (rname);
2063 }
2064 break;
2065
2067 {
2068 char *cname_tmp;
2069
2070 off = 0;
2071 cname_tmp = GNUNET_DNSPARSER_parse_name (rd[i].data,
2072 rd[i].data_size,
2073 &off);
2074 if ((NULL == cname_tmp) ||
2075 (off != rd[i].data_size))
2076 {
2077 GNUNET_break_op (0); /* record not well-formed */
2078 }
2079 else
2080 {
2081 cname_tmp = translate_dot_plus (rh, cname_tmp);
2082 GNUNET_break (NULL != cname_tmp);
2083 scratch_start = scratch_off;
2084 if (GNUNET_OK !=
2086 sizeof(scratch),
2087 &scratch_off,
2088 cname_tmp))
2089 {
2090 GNUNET_break (0);
2091 }
2092 else
2093 {
2094 GNUNET_assert (rd_off < rd_count);
2095 rd_new[rd_off].data = &scratch[scratch_start];
2096 rd_new[rd_off].data_size = scratch_off - scratch_start;
2097 rd_off++;
2098 }
2099 }
2100 GNUNET_free (cname_tmp);
2101 }
2102 break;
2103
2105 {
2106 struct GNUNET_DNSPARSER_SoaRecord *soa;
2107
2108 off = 0;
2110 rd[i].data_size,
2111 &off);
2112 if ((NULL == soa) ||
2113 (off != rd[i].data_size))
2114 {
2115 GNUNET_break_op (0); /* record not well-formed */
2116 }
2117 else
2118 {
2119 soa->mname = translate_dot_plus (rh, soa->mname);
2120 soa->rname = translate_dot_plus (rh, soa->rname);
2121 scratch_start = scratch_off;
2122 if (GNUNET_OK !=
2124 sizeof(scratch),
2125 &scratch_off,
2126 soa))
2127 {
2128 GNUNET_break (0);
2129 }
2130 else
2131 {
2132 GNUNET_assert (rd_off < rd_count);
2133 rd_new[rd_off].data = &scratch[scratch_start];
2134 rd_new[rd_off].data_size = scratch_off - scratch_start;
2135 rd_off++;
2136 }
2137 }
2138 if (NULL != soa)
2140 }
2141 break;
2142
2144 {
2145 struct GNUNET_DNSPARSER_MxRecord *mx;
2146
2147 off = 0;
2149 rd[i].data_size,
2150 &off);
2151 if ((NULL == mx) ||
2152 (off != rd[i].data_size))
2153 {
2154 GNUNET_break_op (0); /* record not well-formed */
2155 }
2156 else
2157 {
2158 mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2159 scratch_start = scratch_off;
2160 if (GNUNET_OK !=
2162 sizeof(scratch),
2163 &scratch_off,
2164 mx))
2165 {
2166 GNUNET_break (0);
2167 }
2168 else
2169 {
2170 GNUNET_assert (rd_off < rd_count);
2171 rd_new[rd_off].data = &scratch[scratch_start];
2172 rd_new[rd_off].data_size = scratch_off - scratch_start;
2173 rd_off++;
2174 }
2175 }
2176 if (NULL != mx)
2178 }
2179 break;
2180
2182 {
2183 struct GNUNET_DNSPARSER_SrvRecord *srv;
2184
2185 off = 0;
2187 rd[i].data_size,
2188 &off);
2189 if ((NULL == srv) ||
2190 (off != rd[i].data_size))
2191 {
2192 GNUNET_break_op (0); /* record not well-formed */
2193 }
2194 else
2195 {
2196 srv->target = translate_dot_plus (rh, srv->target);
2197 scratch_start = scratch_off;
2198 if (GNUNET_OK !=
2200 sizeof(scratch),
2201 &scratch_off,
2202 srv))
2203 {
2204 GNUNET_break (0);
2205 }
2206 else
2207 {
2208 GNUNET_assert (rd_off < rd_count);
2209 rd_new[rd_off].data = &scratch[scratch_start];
2210 rd_new[rd_off].data_size = scratch_off - scratch_start;
2211 rd_off++;
2212 }
2213 }
2214 if (NULL != srv)
2216 }
2217 break;
2218
2220 {
2222
2223 off = 0;
2225 rd[i].data_size,
2226 &off);
2227 if ((NULL == uri) ||
2228 (off != rd[i].data_size))
2229 {
2231 _ ("Failed to deserialize URI record with target\n"));
2232 GNUNET_break_op (0); /* record not well-formed */
2233 }
2234 else
2235 {
2236 scratch_start = scratch_off;
2237 if (GNUNET_OK !=
2239 sizeof(scratch),
2240 &scratch_off,
2241 uri))
2242 {
2243 GNUNET_break (0);
2244 }
2245 else
2246 {
2247 GNUNET_assert (rd_off < rd_count);
2248 rd_new[rd_off].data = &scratch[scratch_start];
2249 rd_new[rd_off].data_size = scratch_off - scratch_start;
2250 rd_off++;
2251 }
2252 }
2253 if (NULL != uri)
2255 }
2256 break;
2257
2260 {
2262 if (rd[i].data_size < sizeof(uint32_t))
2263 {
2264 GNUNET_break_op (0);
2265 break;
2266 }
2267 if (GNUNET_OK !=
2269 rd[i].data_size,
2270 rd[i].record_type,
2271 &pubkey))
2272 {
2273 GNUNET_break_op (0);
2274 break;
2275 }
2276 rd_off++;
2277 if (rd[i].record_type != rh->record_type)
2278 {
2279 /* try to resolve "@" */
2280 struct AuthorityChain *ac;
2281
2282 ac = GNUNET_new (struct AuthorityChain);
2283 ac->rh = rh;
2288 rh->ac_tail,
2289 ac);
2291 rh);
2292 return;
2293 }
2294 }
2295 break;
2296
2298 {
2299 /* delegation to DNS */
2301 {
2302 rd_off++;
2303 break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2304 }
2306 "Found GNS2DNS record, delegating to DNS!\n");
2307 if (GNUNET_OK ==
2309 rd_count,
2310 rd))
2311 return;
2312 else
2313 goto fail;
2314 }
2315
2317 {
2318 /* unbox SRV/TLSA records if a specific one was requested */
2319 if ((0 != rh->protocol) &&
2320 (0 != rh->service) &&
2321 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2322 {
2323 const struct GNUNET_GNSRECORD_BoxRecord *box;
2324
2325 box = rd[i].data;
2327 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2328 ntohs (box->protocol), ntohs (box->service),
2329 rh->protocol, rh->service);
2330 if ((ntohs (box->protocol) == rh->protocol) &&
2331 (ntohs (box->service) == rh->service))
2332 {
2333 /* Box matches, unbox! */
2334 GNUNET_assert (rd_off < rd_count);
2335 rd_new[rd_off].record_type = ntohl (box->record_type);
2336 rd_new[rd_off].data_size -= sizeof(struct
2338 rd_new[rd_off].data = &box[1];
2339 rd_off++;
2340 }
2341 }
2342 else
2343 {
2344 /* no specific protocol/service specified, preserve all BOX
2345 records (for modern, GNS-enabled applications) */
2346 rd_off++;
2347 }
2348 break;
2349 }
2351 {
2352 /* unbox SBOX records if a specific one was requested */
2353 if ((rh->prefix != NULL) &&
2354 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2355 {
2356 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2357 const char *prefix;
2358 size_t prefix_len;
2359
2360 box = rd[i].data;
2361 prefix = rd[i].data + sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
2362 prefix_len = strnlen (
2363 prefix,
2364 rd[i].data_size - sizeof(struct GNUNET_GNSRECORD_SBoxRecord)) + 1;
2365 if (prefix_len - 1 >= rd[i].data_size - sizeof(struct
2367 {
2369 "SBOX record with invalid prefix length, maybe not null-terminated\n");
2370 continue;
2371 }
2373 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2374 prefix, rh->prefix);
2375 if (strcmp (rh->prefix, prefix) == 0)
2376 {
2377 /* Box matches, unbox! */
2378 GNUNET_assert (rd_off < rd_count);
2379 rd_new[rd_off].record_type = ntohl (box->record_type);
2380 rd_new[rd_off].data_size -= sizeof(struct
2382 + prefix_len;
2383 rd_new[rd_off].data = rd[i].data
2384 + sizeof(struct GNUNET_GNSRECORD_SBoxRecord)
2385 + prefix_len;
2386 rd_off++;
2387 }
2388 }
2389 else
2390 {
2392 _ (
2393 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2394 rh->name);
2395 /* no specific protocol/service specified, preserve all SBOX
2396 records (for modern, GNS-enabled applications) */
2397 rd_off++;
2398 }
2399 break;
2400 }
2401 default:
2402 rd_off++;
2403 break;
2404 } /* end: switch */
2405 } /* end: for rd_count */
2406
2407 GNUNET_free (rh->prefix);
2408 rh->prefix = NULL;
2409
2410 /* yes, we are done, return result */
2412 "Returning GNS response for `%s' with %u answers\n",
2413 rh->ac_tail->label,
2414 rd_off);
2415 rh->proc (rh->proc_cls,
2416 rd_off,
2417 rd_new);
2419 rh);
2420 return;
2421 }
2422
2423 switch (rd[0].record_type)
2424 {
2426 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2428 &rd[0]);
2429 return;
2430
2432 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2434 &rd[0]);
2435 return;
2436
2439 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2441 &rd[0]);
2442 return;
2443
2445 if (GNUNET_OK ==
2447 rd_count,
2448 rd))
2449 return;
2450 break;
2451 default:
2453 return;
2455 _ ("Unable to process critical delegation record\n"));
2456 break;
2457 }
2458fail:
2460 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2461 fail_resolution (rh);
2462}
2463
2464
2473static void
2475 int32_t success,
2476 const char *emsg)
2477{
2478 struct CacheOps *co = cls;
2479
2480 co->namecache_qe_cache = NULL;
2481 if (GNUNET_OK != success)
2483 _ ("Failed to cache GNS resolution: %s\n"),
2484 emsg);
2486 co_tail,
2487 co);
2488 GNUNET_free (co);
2489}
2490
2491
2510static void
2512 struct GNUNET_TIME_Absolute exp,
2513 const struct GNUNET_HashCode *key,
2514 const struct GNUNET_PeerIdentity *trunc_peer,
2515 const struct GNUNET_DHT_PathElement *get_path,
2516 unsigned int get_path_length,
2517 const struct GNUNET_DHT_PathElement *put_path,
2518 unsigned int put_path_length,
2520 size_t size,
2521 const void *data)
2522{
2523 struct GNS_ResolverHandle *rh = cls;
2524 struct AuthorityChain *ac = rh->ac_tail;
2525 const struct GNUNET_GNSRECORD_Block *block;
2526 struct CacheOps *co;
2527
2528 (void) exp;
2529 (void) key;
2530 (void) get_path;
2531 (void) get_path_length;
2532 (void) put_path;
2533 (void) put_path_length;
2534 (void) type;
2536 rh->get_handle = NULL;
2538 rh->dht_heap_node = NULL;
2540 "Handling response from the DHT\n");
2541 if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2542 {
2543 /* how did this pass DHT block validation!? */
2544 GNUNET_break (0);
2545 fail_resolution (rh);
2546 return;
2547 }
2548 block = data;
2550 {
2551 /* how did this pass DHT block validation!? */
2552 GNUNET_break (0);
2553 fail_resolution (rh);
2554 return;
2555 }
2557 "Decrypting DHT block of size %llu for `%s', expires %s\n",
2558 (unsigned long long) GNUNET_GNSRECORD_block_get_size (block),
2559 rh->name,
2561 if (GNUNET_OK !=
2564 ac->label,
2566 rh))
2567 {
2568 GNUNET_break_op (0); /* block was ill-formed */
2569 fail_resolution (rh);
2570 return;
2571 }
2574 rel_value_us)
2575 {
2577 "Received expired block from the DHT, will not cache it.\n");
2578 return;
2579 }
2581 return;
2582 /* Cache well-formed blocks */
2584 "Caching response from the DHT in namecache\n");
2585 co = GNUNET_new (struct CacheOps);
2587 block,
2588 &
2590 co);
2592 co_tail,
2593 co);
2594}
2595
2596
2603static void
2605 const struct GNUNET_HashCode *query)
2606{
2607 struct GNS_ResolverHandle *rx;
2608
2609 GNUNET_assert (NULL == rh->get_handle);
2612 query,
2615 NULL, 0,
2616 &handle_dht_response, rh);
2618 rh,
2620 abs_value_us);
2623 {
2624 /* fail longest-standing DHT request */
2626 rx->dht_heap_node = NULL;
2627 GNUNET_assert (NULL != rx);
2628 fail_resolution (rx);
2629 }
2630}
2631
2632
2641static void
2643 unsigned int rd_count,
2644 const struct GNUNET_GNSRECORD_Data *rd)
2645{
2646 struct GNS_ResolverHandle *rh = cls;
2647
2648 if (0 == rd_count)
2650 _ ("GNS namecache returned empty result for `%s'\n"),
2651 rh->name);
2653 rd_count,
2654 rd);
2655}
2656
2657
2664static void
2666 const struct GNUNET_GNSRECORD_Block *block)
2667{
2668 struct GNS_ResolverHandle *rh = cls;
2669 struct AuthorityChain *ac = rh->ac_tail;
2670 const char *label = ac->label;
2671 const struct GNUNET_CRYPTO_PublicKey *auth =
2673 struct GNUNET_HashCode query;
2674
2675 GNUNET_assert (NULL != rh->namecache_qe);
2676 rh->namecache_qe = NULL;
2677 if (NULL == block)
2679 "No block found\n");
2680 else
2682 "Got block with expiration %s\n",
2685 if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2687 (ac != rh->ac_head))) &&
2688 ((NULL == block) ||
2691 rel_value_us)))
2692 {
2693 /* namecache knows nothing; try DHT lookup */
2695 label,
2696 &query);
2698 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2699 ac->label,
2701 GNUNET_h2s (&query));
2702 start_dht_request (rh, &query);
2703 return;
2704 }
2705
2706 if ((NULL == block) ||
2709 rel_value_us))
2710 {
2711 /* DHT not permitted and no local result, fail */
2713 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2714 ac->label,
2716 fail_resolution (rh);
2717 return;
2718 }
2720 "Received result from namecache for label `%s'\n",
2721 ac->label);
2722
2723 if (GNUNET_OK !=
2725 auth,
2726 label,
2728 rh))
2729 {
2730 GNUNET_break_op (0); /* block was ill-formed */
2731 /* try DHT instead */
2733 label,
2734 &query);
2736 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2737 ac->label,
2739 GNUNET_h2s (&query));
2740 start_dht_request (rh, &query);
2741 return;
2742 }
2743}
2744
2745
2751static void
2753{
2754 struct AuthorityChain *ac = rh->ac_tail;
2755 struct GNUNET_HashCode query;
2756
2758 "Starting GNS resolution for `%s' in zone %s\n",
2759 ac->label,
2762 ac->label,
2763 &query);
2765 {
2766 rh->namecache_qe
2768 &query,
2770 rh);
2771 GNUNET_assert (NULL != rh->namecache_qe);
2772 }
2773 else
2774 {
2776 &query);
2777 }
2778}
2779
2780
2787static void
2789 int is_valid)
2790{
2791 struct GNS_ResolverHandle *rh = cls;
2792 struct AuthorityChain *ac = rh->ac_tail;
2793
2794 rh->rev_check = NULL;
2795 if (GNUNET_YES != is_valid)
2796 {
2798 _ ("Zone %s was revoked, resolution fails\n"),
2801 return;
2802 }
2804}
2805
2806
2812static void
2814{
2815 struct AuthorityChain *ac = rh->ac_tail;
2816
2818 "Starting revocation check for zone %s\n",
2823 rh);
2824 GNUNET_assert (NULL != rh->rev_check);
2825}
2826
2827
2828static void
2830{
2831 struct GNS_ResolverHandle *rh = cls;
2832
2833 rh->task_id = NULL;
2834 if (rh->loop_threshold < rh->loop_limiter++)
2835 {
2837 "Encountered unbounded recursion resolving `%s'\n",
2838 rh->name);
2839 fail_resolution (rh);
2840 return;
2841 }
2842 if (GNUNET_YES == rh->ac_tail->gns_authority)
2844 else
2846}
2847
2848
2849static void
2851{
2852 struct GNS_ResolverHandle *rh = cls;
2853 struct AuthorityChain *ac;
2854 struct in_addr v4;
2855 struct in6_addr v6;
2856
2857 rh->task_id = NULL;
2858 if (1 == inet_pton (AF_INET,
2859 rh->name,
2860 &v4))
2861 {
2862 /* name is IPv4 address, pretend it's an A record */
2864
2865 rd.data = &v4;
2866 rd.data_size = sizeof(v4);
2867 rd.expiration_time = UINT64_MAX;
2869 rd.flags = 0;
2870 rh->proc (rh->proc_cls,
2871 1,
2872 &rd);
2873 GNUNET_assert (NULL == rh->task_id);
2875 rh);
2876 return;
2877 }
2878 if (1 == inet_pton (AF_INET6,
2879 rh->name,
2880 &v6))
2881 {
2882 /* name is IPv6 address, pretend it's an AAAA record */
2884
2885 rd.data = &v6;
2886 rd.data_size = sizeof(v6);
2887 rd.expiration_time = UINT64_MAX;
2889 rd.flags = 0;
2890 rh->proc (rh->proc_cls,
2891 1,
2892 &rd);
2893 GNUNET_assert (NULL == rh->task_id);
2895 rh);
2896 return;
2897 }
2898
2899 ac = GNUNET_new (struct AuthorityChain);
2900 ac->rh = rh;
2902 if (NULL == ac->label)
2903 /* name was just the "TLD", so we default to label
2904 #GNUNET_GNS_EMPTY_LABEL_AT */
2909 rh->ac_tail,
2910 ac);
2912 rh);
2913}
2914
2915
2930struct GNS_ResolverHandle *
2932 uint32_t record_type,
2933 const char *name,
2935 uint16_t recursion_depth_limit,
2937 void *proc_cls)
2938{
2939 struct GNS_ResolverHandle *rh;
2940
2942 "Starting lookup for `%s'\n",
2943 name);
2944 rh = GNUNET_new (struct GNS_ResolverHandle);
2946 rlh_tail,
2947 rh);
2948 rh->authority_zone = *zone;
2949 rh->proc = proc;
2950 rh->proc_cls = proc_cls;
2951 rh->options = options;
2953 rh->name = GNUNET_strdup (name);
2954 rh->name_resolution_pos = strlen (name);
2955 rh->loop_threshold = recursion_depth_limit;
2957 rh);
2958 return rh;
2959}
2960
2961
2967void
2969{
2970 struct DnsResult *dr;
2971 struct AuthorityChain *ac;
2972
2974 rlh_tail,
2975 rh);
2976 if (NULL != rh->dns_request)
2977 {
2979 rh->dns_request = NULL;
2980 }
2981 while (NULL != (ac = rh->ac_head))
2982 {
2984 rh->ac_tail,
2985 ac);
2986 if (GNUNET_NO == ac->gns_authority)
2987 {
2988 struct Gns2DnsPending *gp;
2989
2990 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2991 {
2994 gp);
2995 if (NULL != gp->rh)
2996 {
2997 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2998 using GNS_resolver_lookup_cancel here, we need to
2999 add it first... */
3001 rlh_tail,
3002 gp->rh);
3003 GNUNET_assert (NULL == gp->rh->task_id);
3006 gp->rh);
3007 gp->rh = NULL;
3008 }
3009 if (NULL != gp->dns_rh)
3010 {
3012 gp->dns_rh = NULL;
3013 }
3014 GNUNET_free (gp);
3015 }
3017 }
3018 GNUNET_free (ac->label);
3019 GNUNET_free (ac);
3020 }
3021 if (NULL != rh->task_id)
3022 {
3024 rh->task_id = NULL;
3025 }
3026 if (NULL != rh->get_handle)
3027 {
3029 rh->get_handle = NULL;
3030 }
3031 if (NULL != rh->dht_heap_node)
3032 {
3034 rh->dht_heap_node = NULL;
3035 }
3036 if (NULL != rh->namecache_qe)
3037 {
3039 rh->namecache_qe = NULL;
3040 }
3041 if (NULL != rh->rev_check)
3042 {
3044 rh->rev_check = NULL;
3045 }
3046 if (NULL != rh->std_resolve)
3047 {
3049 "Canceling standard DNS resolution\n");
3051 rh->std_resolve = NULL;
3052 }
3053 while (NULL != (dr = rh->dns_result_head))
3054 {
3057 dr);
3058 GNUNET_free (dr);
3059 }
3060 if (NULL != rh->prefix)
3061 {
3063 rh->prefix = NULL;
3064 }
3065 GNUNET_free (rh->leho);
3066 GNUNET_free (rh->name);
3067 GNUNET_free (rh);
3068}
3069
3070
3071/* ***************** Resolver initialization ********************* */
3072
3073
3082void
3084 struct GNUNET_DHT_Handle *dht,
3085 const struct GNUNET_CONFIGURATION_Handle *c,
3086 unsigned long long max_bg_queries)
3087{
3088 cfg = c;
3090 dht_handle = dht;
3093 max_allowed_background_queries = max_bg_queries;
3095 "namecache",
3096 "DISABLE");
3099 "Namecache disabled\n");
3100}
3101
3102
3106void
3108{
3109 struct GNS_ResolverHandle *rh;
3110 struct CacheOps *co;
3111
3112 /* abort active resolutions */
3113 while (NULL != (rh = rlh_head))
3114 {
3115 rh->proc (rh->proc_cls,
3116 0,
3117 NULL);
3119 }
3120 while (NULL != (co = co_head))
3121 {
3123 co_tail,
3124 co);
3126 GNUNET_free (co);
3127 }
3129 dht_lookup_heap = NULL;
3130 dht_handle = NULL;
3131 namecache_handle = NULL;
3132}
3133
3134
3135/* 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.
Definition: gnunet-config.c:65
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.
Definition: resolver_api.c:940
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:640
#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.
Definition: namecache_api.c:93
An QueueEntry used to store information for a pending NAMECACHE record operation.
Definition: namecache_api.c:46
The identity of the host (wraps the signing key of the peer).
Handle to a request given to the resolver.
Definition: resolver_api.c:104
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?