GNUnet 0.21.1
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"
45#include "gnunet_dns_service.h"
48#include "gnunet_gns_service.h"
49#include "gns.h"
50#include "gnunet-service-gns.h"
52#include "gnu_name_system_protocols.h"
53#include "gnu_name_system_service_ports.h"
54
55
59#define DHT_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
60 GNUNET_TIME_UNIT_SECONDS, 60)
61
65#define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
66 GNUNET_TIME_UNIT_SECONDS, 15)
67
71#define DHT_GNS_REPLICATION_LEVEL 10
72
73
78struct AuthorityChain;
79
80
87{
92
97
102
109
114
118 unsigned int num_results;
119};
120
121
126struct GNS_ResolverHandle;
127
128
134{
139
144
149
153 char *label;
154
160
164 union
165 {
170
171 struct
172 {
179
185
191
196
201 int found;
202
209};
210
211
216{
221
226
230 const void *data;
231
237
241 size_t data_size;
242
246 uint32_t record_type;
247};
248
249
255{
260
265
270
275
279 void *proc_cls;
280
285
286
291
296
301
306
312
317
322
327
331 char *name;
332
337 char *leho;
338
343
348
353
358
364
370
374 char *prefix;
375
376
381
387 unsigned int loop_limiter;
388
392 unsigned int loop_threshold;
393
398};
399
400
405{
409 struct CacheOps *next;
410
414 struct CacheOps *prev;
415
420};
421
422
427
432
437
441static unsigned long long max_allowed_background_queries;
442
447
452
456static struct CacheOps *co_head;
457
461static struct CacheOps *co_tail;
462
466static int disable_cache;
467
471static const struct GNUNET_CONFIGURATION_Handle *cfg;
472
473
489/* dead, but keep for now */ int
490is_canonical (const char *name)
491{
492 const char *pos;
493 const char *dot;
494
495 if (NULL == strchr (name,
496 (unsigned char) '.'))
497 return GNUNET_YES;
498 if ('_' != name[0])
499 return GNUNET_NO;
500 pos = &name[1];
501 while (NULL != (dot = strchr (pos,
502 (unsigned char) '.')))
503 if ('_' != dot[1])
504 return GNUNET_NO;
505 else
506 pos = dot + 1;
507 return GNUNET_YES;
508}
509
510
511/* ************************** Resolution **************************** */
512
520static char *
522 char *name)
523{
524 char *ret;
525 size_t s_len = strlen (name);
526
527 if (0 != strcmp (&name[s_len - 2],
528 ".+"))
529 return name; /* did not end in ".+" */
532 "%.*s.%s",
533 (int) (s_len - 2),
534 name,
538 return ret;
539}
540
541
548static void
550{
551 struct GNS_ResolverHandle *rh = cls;
552
553 rh->task_id = NULL;
555}
556
557
563static void
565{
566 rh->proc (rh->proc_cls,
567 0,
568 NULL);
569 GNUNET_assert (NULL == rh->task_id);
571 rh);
572}
573
574
580static void
582{
583 struct GNS_ResolverHandle *rh = cls;
584
585 rh->task_id = NULL;
586 fail_resolution (rh);
587}
588
589
595static int
597{
598 struct protoent *pe = getprotobyname (name);
599 if (pe == NULL)
600 {
602 }
603 return pe->p_proto;
604}
605
606
613static int
614resolver_getservbyname (const char *name, const char *proto)
615{
616 struct servent *se = getservbyname (name, proto);
617 if (se == NULL)
618 {
620 }
621 return se->s_port;
622}
623
624
643static char *
645{
646 const char *rp;
647 const char *dot;
648 size_t len;
649 char *ret;
650 char *srv_name;
651 char *proto_name;
652 int protocol;
653 int service;
654
655 if (0 == rh->name_resolution_pos)
656 return NULL;
657 dot = memrchr (rh->name,
658 (int) '.',
660 if (NULL == dot)
661 {
662 /* done, this was the last one */
663 len = rh->name_resolution_pos;
664 rp = rh->name;
665 rh->name_resolution_pos = 0;
666 }
667 else if ('_' == dot[1])
668 {
677 len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
678 }
679 else
680 {
681 /* advance by one label */
682 len = rh->name_resolution_pos - (dot - rh->name) - 1;
683 rp = dot + 1;
684 rh->name_resolution_pos = dot - rh->name;
685 }
686 rh->protocol = 0;
687 rh->service = 0;
688 rh->prefix = NULL;
689 ret = GNUNET_strndup (rp, len);
694 if (('_' == rh->name[0]) &&
695 (NULL != (dot = memrchr (rh->name,
696 (int) '.',
697 rh->name_resolution_pos))) &&
698 ('_' == dot[1]) &&
699 (NULL == memrchr (rh->name,
700 (int) '.',
701 dot - rh->name)))
702 {
703 srv_name = GNUNET_strndup (&rh->name[1],
704 (dot - rh->name) - 1);
705 proto_name = GNUNET_strndup (&dot[2],
706 rh->name_resolution_pos - (dot - rh->name)
707 - 2);
708 protocol = resolver_getprotobyname (proto_name);
709 if (0 == protocol)
710 {
712 _ (
713 "Protocol `%s' unknown, skipping labels as BOX retain as SBOX.\n"),
714 proto_name);
715 GNUNET_free (proto_name);
716 GNUNET_free (srv_name);
718 rh->name_resolution_pos = 0;
719 return ret;
720 }
722 proto_name);
723 if (0 == service)
724 {
726 _ (
727 "Service `%s' unknown for protocol `%s', trying as number.\n"),
728 srv_name,
729 proto_name);
730 if (1 != sscanf (srv_name, "%u", &rh->service))
731 {
733 _ (
734 "Service `%s' not a port, skipping service labels as BOX retain as SBOX.\n"),
735 srv_name);
736 GNUNET_free (proto_name);
737 GNUNET_free (srv_name);
739 rh->name_resolution_pos = 0;
740 return ret;
741 }
742 }
743 else
744 {
745 rh->service = ntohs (service);
746 }
747 rh->protocol = protocol;
748 GNUNET_free (proto_name);
749 GNUNET_free (srv_name);
750 }
757 if ((NULL != (dot = memrchr (rh->name,
758 (int) '.',
759 rh->name_resolution_pos)) && '_' == dot[1]) ||
760 ((NULL == memrchr (rh->name,
761 (int) '.',
762 rh->name_resolution_pos)) && '_' == rh->name[0]))
763 {
765 rh->name_resolution_pos = 0;
766 }
767 return ret;
768}
769
770
776static void
778{
779 struct DnsResult *pos;
780 unsigned int n;
781 unsigned int i;
782
783 n = 0;
784 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
785 n++;
786 {
787 struct GNUNET_GNSRECORD_Data rd[n];
788
789 i = 0;
790 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
791 {
792 rd[i].data = pos->data;
793 rd[i].data_size = pos->data_size;
794 rd[i].record_type = pos->record_type;
802 if (0 == pos->expiration_time)
803 {
805 rd[i].expiration_time = 0;
806 }
807 else
808 {
810 }
811 i++;
812 }
813 GNUNET_assert (i == n);
815 "Transmitting standard DNS result with %u records\n",
816 n);
817 rh->proc (rh->proc_cls,
818 n,
819 rd);
820 }
822}
823
824
834static void
836 uint64_t expiration_time,
837 uint32_t record_type,
838 size_t data_size,
839 const void *data)
840{
841 struct DnsResult *res;
842
843 res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
844 res->expiration_time = expiration_time;
845 res->data_size = data_size;
846 res->record_type = record_type;
847 res->data = &res[1];
848 GNUNET_memcpy (&res[1],
849 data,
850 data_size);
852 rh->dns_result_tail,
853 res);
854}
855
856
865static void
867 const struct sockaddr *addr,
868 socklen_t addrlen)
869{
870 struct GNS_ResolverHandle *rh = cls;
871 const struct sockaddr_in *sa4;
872 const struct sockaddr_in6 *sa6;
873
874 if (NULL == addr)
875 {
876 rh->std_resolve = NULL;
878 return;
879 }
881 "Received %u bytes of DNS IP data\n",
882 addrlen);
883 switch (addr->sa_family)
884 {
885 case AF_INET:
886 sa4 = (const struct sockaddr_in *) addr;
887 add_dns_result (rh,
888 0 /* expiration time is unknown */,
890 sizeof(struct in_addr),
891 &sa4->sin_addr);
892 break;
893
894 case AF_INET6:
895 sa6 = (const struct sockaddr_in6 *) addr;
896 add_dns_result (rh,
897 0 /* expiration time is unknown */,
899 sizeof(struct in6_addr),
900 &sa6->sin6_addr);
901 break;
902
903 default:
904 GNUNET_break (0);
905 break;
906 }
907}
908
909
915static void
916recursive_resolution (void *cls);
917
918
925static void
926start_resolver_lookup (void *cls);
927
928
937static void
939 const struct GNUNET_TUN_DnsHeader *dns,
940 size_t dns_len)
941{
942 struct GNS_ResolverHandle *rh = cls;
944 const struct GNUNET_DNSPARSER_Record *rec;
945 unsigned int rd_count;
946
947 if (NULL == dns)
948 {
949 rh->dns_request = NULL;
951 rh->task_id = NULL;
952 fail_resolution (rh);
953 return;
954 }
955 if (rh->original_dns_id != dns->id)
956 {
957 /* DNS answer, but for another query */
958 return;
959 }
960 p = GNUNET_DNSPARSER_parse ((const char *) dns,
961 dns_len);
962 if (NULL == p)
963 {
965 _ ("Failed to parse DNS response\n"));
966 return;
967 }
968
969 /* We got a result from DNS */
971 "Received DNS response for `%s' with %u answers\n",
972 rh->ac_tail->label,
973 (unsigned int) p->num_answers);
974 if ((p->num_answers > 0) &&
975 (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
977 {
978 int af;
979
981 "Got CNAME `%s' from DNS for `%s'\n",
982 p->answers[0].data.hostname,
983 rh->name);
984 if (NULL != rh->std_resolve)
985 {
987 "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
988 rh->name);
990 }
991 GNUNET_free (rh->name);
992 rh->name = GNUNET_strdup (p->answers[0].data.hostname);
993 rh->name_resolution_pos = strlen (rh->name);
994 switch (rh->record_type)
995 {
997 af = AF_INET;
998 break;
999
1001 af = AF_INET6;
1002 break;
1003
1004 default:
1005 af = AF_UNSPEC;
1006 break;
1007 }
1008 if (NULL != rh->leho)
1009 add_dns_result (rh,
1010 GNUNET_TIME_UNIT_HOURS.rel_value_us,
1012 strlen (rh->leho),
1013 rh->leho);
1015 af,
1018 rh);
1021 rh->dns_request = NULL;
1022 return;
1023 }
1024
1025 /* convert from (parsed) DNS to (binary) GNS format! */
1026 rd_count = p->num_answers + p->num_authority_records
1027 + p->num_additional_records;
1028 {
1029 struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
1030 int skip;
1031 char buf[UINT16_MAX];
1032 size_t buf_off;
1033 size_t buf_start;
1034
1035 buf_off = 0;
1036 skip = 0;
1037 memset (rd,
1038 0,
1039 sizeof(rd));
1040 for (unsigned int i = 0; i < rd_count; i++)
1041 {
1042 if (i < p->num_answers)
1043 rec = &p->answers[i];
1044 else if (i < p->num_answers + p->num_authority_records)
1045 rec = &p->authority_records[i - p->num_answers];
1046 else
1047 rec = &p->additional_records[i - p->num_answers
1048 - p->num_authority_records];
1049 /* As we copied the full DNS name to 'rh->ac_tail->label', this
1050 should be the correct check to see if this record is actually
1051 a record for our label... */
1052 if (0 != strcmp (rec->name,
1053 rh->ac_tail->label))
1054 {
1056 "Dropping record `%s', does not match desired name `%s'\n",
1057 rec->name,
1058 rh->ac_tail->label);
1059 skip++;
1060 continue;
1061 }
1062 rd[i - skip].record_type = rec->type;
1064 switch (rec->type)
1065 {
1067 if (rec->data.raw.data_len != sizeof(struct in_addr))
1068 {
1069 GNUNET_break_op (0);
1070 skip++;
1071 continue;
1072 }
1073 rd[i - skip].data_size = rec->data.raw.data_len;
1074 rd[i - skip].data = rec->data.raw.data;
1075 break;
1076
1078 if (rec->data.raw.data_len != sizeof(struct in6_addr))
1079 {
1080 GNUNET_break_op (0);
1081 skip++;
1082 continue;
1083 }
1084 rd[i - skip].data_size = rec->data.raw.data_len;
1085 rd[i - skip].data = rec->data.raw.data;
1086 break;
1087
1091 buf_start = buf_off;
1092 if (GNUNET_OK !=
1094 sizeof(buf),
1095 &buf_off,
1096 rec->data.hostname))
1097 {
1098 GNUNET_break (0);
1099 skip++;
1100 continue;
1101 }
1102 rd[i - skip].data_size = buf_off - buf_start;
1103 rd[i - skip].data = &buf[buf_start];
1104 break;
1105
1107 buf_start = buf_off;
1108 if (GNUNET_OK !=
1110 sizeof(buf),
1111 &buf_off,
1112 rec->data.soa))
1113 {
1114 GNUNET_break (0);
1115 skip++;
1116 continue;
1117 }
1118 rd[i - skip].data_size = buf_off - buf_start;
1119 rd[i - skip].data = &buf[buf_start];
1120 break;
1121
1123 buf_start = buf_off;
1124 if (GNUNET_OK !=
1126 sizeof(buf),
1127 &buf_off,
1128 rec->data.mx))
1129 {
1130 GNUNET_break (0);
1131 skip++;
1132 continue;
1133 }
1134 rd[i - skip].data_size = buf_off - buf_start;
1135 rd[i - skip].data = &buf[buf_start];
1136 break;
1137
1139 buf_start = buf_off;
1140 if (GNUNET_OK !=
1142 sizeof(buf),
1143 &buf_off,
1144 rec->data.srv))
1145 {
1146 GNUNET_break (0);
1147 skip++;
1148 continue;
1149 }
1150 rd[i - skip].data_size = buf_off - buf_start;
1151 rd[i - skip].data = &buf[buf_start];
1152 break;
1153
1155 buf_start = buf_off;
1156 if (GNUNET_OK !=
1158 sizeof(buf),
1159 &buf_off,
1160 rec->data.uri))
1161 {
1162 GNUNET_break (0);
1163 skip++;
1164 continue;
1165 }
1166 rd[i - skip].data_size = buf_off - buf_start;
1167 rd[i - skip].data = &buf[buf_start];
1168 break;
1169
1170 default:
1172 _ ("Skipping record of unsupported type %d\n"),
1173 rec->type);
1174 skip++;
1175 continue;
1176 }
1177 } /* end of for all records in answer */
1178 if (NULL != rh->leho)
1179 {
1183 rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1184 rd[rd_count - skip].data = rh->leho;
1185 rd[rd_count - skip].data_size = strlen (rh->leho);
1186 skip--; /* skip one LESS */
1188 "Adding LEHO %s\n",
1189 rh->leho);
1190 }
1192 "Returning DNS response for `%s' with %u answers\n",
1193 rh->ac_tail->label,
1194 (unsigned int) (rd_count - skip));
1195 rh->proc (rh->proc_cls,
1196 rd_count - skip,
1197 rd);
1199 rh->dns_request = NULL;
1200 }
1202 if (NULL != rh->task_id)
1203 GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1205 rh);
1206}
1207
1208
1217static void
1219{
1220 struct AuthorityChain *ac;
1221 struct GNUNET_DNSPARSER_Query *query;
1222 struct GNUNET_DNSPARSER_Packet *p;
1223 char *dns_request;
1224 size_t dns_request_length;
1225 int ret;
1226
1227 ac = rh->ac_tail;
1228 GNUNET_assert (NULL != ac);
1230 "Starting DNS lookup for `%s'\n",
1231 ac->label);
1233 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1234 query->name = GNUNET_strdup (ac->label);
1235 query->type = rh->record_type;
1238 p->queries = query;
1239 p->num_queries = 1;
1241 UINT16_MAX);
1242 p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1243 p->flags.recursion_desired = 1;
1245 1024,
1246 &dns_request,
1247 &dns_request_length);
1248 if (GNUNET_OK != ret)
1249 {
1250 GNUNET_break (0);
1251 rh->proc (rh->proc_cls,
1252 0,
1253 NULL);
1254 GNUNET_assert (NULL == rh->task_id);
1256 rh);
1257 }
1258 else
1259 {
1260 rh->original_dns_id = p->id;
1262 GNUNET_assert (NULL == rh->dns_request);
1263 rh->leho = GNUNET_strdup (ac->label);
1266 dns_request,
1267 dns_request_length,
1269 rh);
1272 rh);
1273 }
1274 if (GNUNET_SYSERR != ret)
1275 GNUNET_free (dns_request);
1277}
1278
1279
1288static void
1290 const char *rname)
1291{
1292 size_t nlen;
1293 char *res;
1294 const char *tld;
1295 struct AuthorityChain *ac;
1296 int af;
1297 struct GNUNET_CRYPTO_PublicKey zone;
1298
1300 "Handling GNS REDIRECT result `%s'\n",
1301 rname);
1302 nlen = strlen (rname);
1303 tld = GNS_get_tld (rname);
1304 if (0 == strcmp ("+", tld))
1305 {
1306 /* REDIRECT resolution continues relative to current domain */
1307 if (0 == rh->name_resolution_pos)
1308 {
1309 res = GNUNET_strndup (rname, nlen - 2);
1310 rh->name_resolution_pos = nlen - 2;
1311 }
1312 else
1313 {
1315 "%.*s.%.*s",
1316 (int) rh->name_resolution_pos,
1317 rh->name,
1318 (int) (nlen - 2),
1319 rname);
1320 rh->name_resolution_pos = strlen (res);
1321 }
1322 GNUNET_free (rh->name);
1323 rh->name = res;
1324 ac = GNUNET_new (struct AuthorityChain);
1325 ac->rh = rh;
1330 /* add AC to tail */
1332 rh->ac_tail,
1333 ac);
1335 rh);
1336 return;
1337 }
1338 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1339 {
1340 /* REDIRECT resolution continues relative to current domain */
1341 if (0 == rh->name_resolution_pos)
1342 {
1344 "%.*s",
1345 (int) (strlen (rname) - (strlen (tld) + 1)),
1346 rname);
1347 }
1348 else
1349 {
1351 "%.*s.%.*s",
1352 (int) rh->name_resolution_pos,
1353 rh->name,
1354 (int) (strlen (rname) - (strlen (tld) + 1)),
1355 rname);
1356 }
1357 rh->name_resolution_pos = strlen (res);
1358 GNUNET_free (rh->name);
1359 rh->name = res;
1360 ac = GNUNET_new (struct AuthorityChain);
1361 ac->rh = rh;
1363 ac->authority_info.gns_authority = zone;
1365 /* add AC to tail */
1367 rh->ac_tail,
1368 ac);
1370 rh);
1371 return;
1372 }
1373
1375 "Got REDIRECT `%s' from GNS for `%s'\n",
1376 rname,
1377 rh->name);
1378 if (NULL != rh->std_resolve)
1379 {
1381 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1382 rh->name);
1384 }
1385 /* name is absolute, go to DNS */
1386 GNUNET_free (rh->name);
1387 rh->name = GNUNET_strdup (rname);
1388 rh->name_resolution_pos = strlen (rh->name);
1389 switch (rh->record_type)
1390 {
1392 af = AF_INET;
1393 break;
1394
1396 af = AF_INET6;
1397 break;
1398
1399 default:
1400 af = AF_UNSPEC;
1401 break;
1402 }
1404 "Doing standard DNS lookup for `%s'\n",
1405 rh->name);
1406
1408 af,
1411 rh);
1412}
1413
1414
1423static void
1425 const char *cname)
1426{
1427 int af;
1428
1429 GNUNET_free (rh->name);
1430 rh->name = GNUNET_strdup (cname);
1431 rh->name_resolution_pos = strlen (rh->name);
1432 switch (rh->record_type)
1433 {
1435 af = AF_INET;
1436 break;
1437
1439 af = AF_INET6;
1440 break;
1441
1442 default:
1443 af = AF_UNSPEC;
1444 break;
1445 }
1447 "Doing standard DNS lookup for `%s'\n",
1448 rh->name);
1449
1451 af,
1454 rh);
1455}
1456
1457
1465static void
1467 unsigned int rd_count,
1468 const struct GNUNET_GNSRECORD_Data *rd);
1469
1470
1478static void
1480{
1481 struct GNS_ResolverHandle *rh = ac->rh;
1482
1483 if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1485 return; /* more pending and none found yet */
1487 {
1489 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1491 fail_resolution (rh);
1492 return;
1493 }
1495 return; /* already running, do not launch again! */
1496 /* recurse */
1499 "Will continue resolution using DNS to resolve `%s'\n",
1500 ac->label);
1501 GNUNET_assert (NULL == rh->task_id);
1503 rh);
1504}
1505
1506
1515static void
1517 unsigned int rd_count,
1518 const struct GNUNET_GNSRECORD_Data *rd)
1519{
1520 struct Gns2DnsPending *gp = cls;
1521 struct AuthorityChain *ac = gp->ac;
1522
1525 gp);
1526 /* enable cleanup of 'rh' handle that automatically comes after we return,
1527 and which expects 'rh' to be in the #rlh_head DLL. */
1528 if (NULL != gp->rh)
1529 {
1531 rlh_tail,
1532 gp->rh);
1533 gp->rh = NULL;
1534 }
1535 GNUNET_free (gp);
1537 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1538 rd_count);
1539 /* find suitable A/AAAA record */
1540 for (unsigned int j = 0; j < rd_count; j++)
1541 {
1542 switch (rd[j].record_type)
1543 {
1545 {
1546 struct sockaddr_in v4;
1547
1548 if (sizeof(struct in_addr) != rd[j].data_size)
1549 {
1550 GNUNET_break_op (0);
1551 continue;
1552 }
1553 memset (&v4,
1554 0,
1555 sizeof(v4));
1556 v4.sin_family = AF_INET;
1557 v4.sin_port = htons (53);
1558#if HAVE_SOCKADDR_IN_SIN_LEN
1559 v4.sin_len = (u_char) sizeof(v4);
1560#endif
1561 GNUNET_memcpy (&v4.sin_addr,
1562 rd[j].data,
1563 sizeof(struct in_addr));
1564 if (GNUNET_OK ==
1567 (const struct sockaddr *) &v4))
1569 break;
1570 }
1571
1573 {
1574 struct sockaddr_in6 v6;
1575
1576 if (sizeof(struct in6_addr) != rd[j].data_size)
1577 {
1578 GNUNET_break_op (0);
1579 continue;
1580 }
1581 /* FIXME: might want to check if we support IPv6 here,
1582 and otherwise skip this one and hope we find another */
1583 memset (&v6,
1584 0,
1585 sizeof(v6));
1586 v6.sin6_family = AF_INET6;
1587 v6.sin6_port = htons (53);
1588#if HAVE_SOCKADDR_IN_SIN_LEN
1589 v6.sin6_len = (u_char) sizeof(v6);
1590#endif
1591 GNUNET_memcpy (&v6.sin6_addr,
1592 rd[j].data,
1593 sizeof(struct in6_addr));
1594 if (GNUNET_OK ==
1597 (const struct sockaddr *) &v6))
1599 break;
1600 }
1601
1602 default:
1603 break;
1604 }
1605 }
1607}
1608
1609
1617static void
1619 const struct sockaddr *addr,
1620 socklen_t addrlen)
1621{
1622 struct Gns2DnsPending *gp = cls;
1623 struct AuthorityChain *ac = gp->ac;
1624 struct sockaddr_storage ss;
1625 struct sockaddr_in *v4;
1626 struct sockaddr_in6 *v6;
1627
1628 if (NULL == addr)
1629 {
1630 /* DNS resolution finished */
1631 if (0 == gp->num_results)
1633 "Failed to use DNS to resolve name of DNS resolver\n");
1636 gp);
1637 GNUNET_free (gp);
1639 return;
1640 }
1641 GNUNET_memcpy (&ss,
1642 addr,
1643 addrlen);
1644 switch (ss.ss_family)
1645 {
1646 case AF_INET:
1647 v4 = (struct sockaddr_in *) &ss;
1648 v4->sin_port = htons (53);
1649 gp->num_results++;
1650 break;
1651
1652 case AF_INET6:
1653 v6 = (struct sockaddr_in6 *) &ss;
1654 v6->sin6_port = htons (53);
1655 gp->num_results++;
1656 break;
1657
1658 default:
1660 "Unsupported AF %d\n",
1661 ss.ss_family);
1662 return;
1663 }
1664 if (GNUNET_OK ==
1666 (struct sockaddr *) &ss))
1668}
1669
1670
1677static void
1679 const struct GNUNET_GNSRECORD_Data *rd)
1680{
1682 rd->data);
1683}
1684
1685
1692static void
1694 const struct GNUNET_GNSRECORD_Data *rd)
1695{
1696 char *cname;
1697 size_t off;
1698
1699 off = 0;
1701 rd->data_size,
1702 &off);
1703 if ((NULL == cname) ||
1704 (off != rd->data_size))
1705 {
1706 GNUNET_break_op (0); /* record not well-formed */
1707 GNUNET_free (cname);
1708 fail_resolution (rh);
1709 return;
1710 }
1712 cname);
1713 GNUNET_free (cname);
1714}
1715
1716
1723static void
1725 const struct GNUNET_GNSRECORD_Data *rd)
1726{
1727 struct AuthorityChain *ac;
1728 struct GNUNET_CRYPTO_PublicKey auth;
1729
1730 /* delegation to another zone */
1732 rd->data_size,
1733 rd->record_type,
1734 &auth))
1735 {
1736 GNUNET_break_op (0);
1737 fail_resolution (rh);
1738 return;
1739 }
1740 /* expand authority chain */
1741 ac = GNUNET_new (struct AuthorityChain);
1742 ac->rh = rh;
1744 ac->authority_info.gns_authority = auth;
1746 /* add AC to tail */
1748 rh->ac_tail,
1749 ac);
1750 /* recurse */
1752 rh);
1753}
1754
1755
1766static int
1768 unsigned int rd_count,
1769 const struct GNUNET_GNSRECORD_Data *rd)
1770{
1771 struct AuthorityChain *ac;
1772 const char *tld;
1773 char *ns;
1774
1775 ns = NULL;
1776 /* expand authority chain */
1777 ac = GNUNET_new (struct AuthorityChain);
1778 ac->rh = rh;
1780
1781 for (unsigned int i = 0; i < rd_count; i++)
1782 {
1783 char *ip;
1784 char *n;
1785 size_t off;
1786 struct Gns2DnsPending *gp;
1787 struct GNUNET_CRYPTO_PublicKey zone;
1788 struct sockaddr_in v4;
1789 struct sockaddr_in6 v6;
1790
1791 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1792 {
1796 GNUNET_free (ns);
1797 GNUNET_free (ac);
1798 return GNUNET_SYSERR;
1799 }
1800 off = 0;
1802 rd[i].data_size,
1803 &off);
1804 ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1805 if ((NULL == n) ||
1806 (NULL == ip))
1807 {
1808 GNUNET_break_op (0);
1809 GNUNET_free (n);
1810 GNUNET_free (ip);
1811 continue;
1812 }
1813
1814 off += strlen (ip) + 1;
1815
1816 if (off != rd[i].data_size)
1817 {
1818 GNUNET_break_op (0);
1819 GNUNET_free (n);
1820 GNUNET_free (ip);
1821 continue;
1822 }
1823 /* resolve 'ip' to determine the IP(s) of the DNS
1824 resolver to use for lookup of 'ns' */
1825 if (NULL != ns)
1826 {
1827 if (0 != strcasecmp (ns,
1828 n))
1829 {
1830 /* NS values must all be the same for all GNS2DNS records,
1831 anything else leads to insanity */
1832 GNUNET_break_op (0);
1833 GNUNET_free (n);
1834 GNUNET_free (ip);
1835 continue;
1836 }
1837 GNUNET_free (n);
1838 }
1839 else
1840 {
1841 ns = n;
1842 }
1843
1844 /* check if 'ip' is already an IPv4/IPv6 address */
1845 if ((1 == inet_pton (AF_INET,
1846 ip,
1847 &v4)) ||
1848 (1 == inet_pton (AF_INET6,
1849 ip,
1850 &v6)))
1851 {
1855 ip));
1857 GNUNET_free (ip);
1858 continue;
1859 }
1860 tld = GNS_get_tld (ip);
1861 if ((0 != strcmp (tld, "+")) &&
1862 (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1863 {
1864 /* 'ip' is a DNS name */
1865 gp = GNUNET_new (struct Gns2DnsPending);
1866 gp->ac = ac;
1869 gp);
1871 AF_UNSPEC,
1874 gp);
1875 GNUNET_free (ip);
1876 continue;
1877 }
1878 /* 'ip' should be a GNS name */
1879 gp = GNUNET_new (struct Gns2DnsPending);
1880 gp->ac = ac;
1883 gp);
1884 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1885 if (0 == strcmp (tld, "+"))
1886 {
1887 ip = translate_dot_plus (rh,
1888 ip);
1889 tld = GNS_get_tld (ip);
1890 if (GNUNET_OK !=
1892 &zone))
1893 {
1894 GNUNET_break_op (0);
1895 GNUNET_free (ip);
1896 continue;
1897 }
1898 }
1899 gp->rh->authority_zone = zone;
1901 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1902 ip,
1903 ns);
1904 gp->rh->name = ip;
1905 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1907 gp->rh->proc_cls = gp;
1910 gp->rh->loop_limiter = rh->loop_limiter + 1;
1911 gp->rh->loop_threshold = rh->loop_threshold;
1912 gp->rh->task_id
1914 gp->rh);
1915 } /* end 'for all records' */
1916
1917 if (NULL == ns)
1918 {
1919 /* not a single GNS2DNS record found */
1920 GNUNET_free (ac);
1921 return GNUNET_SYSERR;
1922 }
1924 strcpy (ac->authority_info.dns_authority.name,
1925 ns);
1926 /* for DNS recursion, the label is the full DNS name,
1927 created from the remainder of the GNS name and the
1928 name in the NS record */
1929 GNUNET_asprintf (&ac->label,
1930 "%.*s%s%s",
1931 (int) rh->name_resolution_pos,
1932 rh->name,
1933 (0 != rh->name_resolution_pos) ? "." : "",
1934 ns);
1935 GNUNET_free (ns);
1936
1937 {
1938 /* the GNS name is UTF-8 and may include multibyte chars.
1939 * We have to convert the combined name to a DNS-compatible IDNA.
1940 */
1941 char *tmp = ac->label;
1942
1943 if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1944 &ac->label,
1945 IDNA_ALLOW_UNASSIGNED))
1946 {
1948 _ ("Name `%s' cannot be converted to IDNA."),
1949 tmp);
1950 GNUNET_free (tmp);
1951 GNUNET_free (ac);
1952 return GNUNET_SYSERR;
1953 }
1954 GNUNET_free (tmp);
1955 }
1956
1958 rh->ac_tail,
1959 ac);
1960 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1961 {
1963 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1964 ac->label);
1965 GNUNET_free (ac->label);
1966 GNUNET_free (ac);
1967 return GNUNET_SYSERR;
1968 }
1970 return GNUNET_OK;
1971}
1972
1973
1974static void
1976 unsigned int rd_count,
1977 const struct GNUNET_GNSRECORD_Data *rd)
1978{
1979 struct GNS_ResolverHandle *rh = cls;
1980 char *cname;
1981 char scratch[UINT16_MAX];
1982 size_t scratch_off;
1983 size_t scratch_start;
1984 size_t off;
1985 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1986 unsigned int rd_off;
1987
1989 "Resolution succeeded for `%s' in zone %s, got %u records\n",
1990 rh->ac_tail->label,
1992 rd_count);
1993 if (0 == rd_count)
1994 {
1996 _ ("GNS lookup failed (zero records found for `%s')\n"),
1997 rh->name);
1998 fail_resolution (rh);
1999 return;
2000 }
2001
2002 if (0 == rh->name_resolution_pos)
2003 {
2004 /* top-level match, are we done yet? */
2005 if ((rd_count > 0) &&
2008 {
2009 off = 0;
2011 rd[0].data_size,
2012 &off);
2013 if ((NULL == cname) ||
2014 (off != rd[0].data_size))
2015 {
2016 GNUNET_break_op (0);
2017 GNUNET_free (cname);
2018 fail_resolution (rh);
2019 return;
2020 }
2022 cname);
2023 GNUNET_free (cname);
2024 return;
2025 }
2026 if ((rd_count > 0) &&
2029 {
2031 rd[0].data);
2032 return;
2033 }
2034
2035
2036 /* If A/AAAA was requested,
2037 * but we got a GNS2DNS record */
2038 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2040 {
2041 for (unsigned int i = 0; i < rd_count; i++)
2042 {
2043 switch (rd[i].record_type)
2044 {
2046 {
2047 /* delegation to DNS */
2049 "Found GNS2DNS record, delegating to DNS!\n");
2050 if (GNUNET_OK ==
2052 rd_count,
2053 rd))
2054 return;
2055 else
2056 goto fail;
2057 }
2058
2059 default:
2060 break;
2061 } /* end: switch */
2062 } /* end: for rd */
2063 } /* end: name_resolution_pos */
2064 /* convert relative names in record values to absolute names,
2065 using 'scratch' array for memory allocations */
2066 scratch_off = 0;
2067 rd_off = 0;
2068 for (unsigned int i = 0; i < rd_count; i++)
2069 {
2070 GNUNET_assert (rd_off <= i);
2071 if ((((0 != rh->protocol) &&
2072 (0 != rh->service)) || (NULL != rh->prefix)) &&
2077 continue;
2078 /* we _only_ care about boxed records */
2079
2080 GNUNET_assert (rd_off < rd_count);
2081 rd_new[rd_off] = rd[i];
2082 /* Check if the embedded name(s) end in "+", and if so,
2083 replace the "+" with the zone at "ac_tail", changing the name
2084 to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2085 so we can free it afterwards. */
2086 switch (rd[i].record_type)
2087 {
2089 {
2090 char *rname;
2091 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2092 rname = translate_dot_plus (rh, rname);
2093 GNUNET_break (NULL != rname);
2094 scratch_start = scratch_off;
2095 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2096 scratch_off += strlen (rname) + 1;
2097 GNUNET_assert (rd_off < rd_count);
2098 rd_new[rd_off].data = &scratch[scratch_start];
2099 rd_new[rd_off].data_size = scratch_off - scratch_start;
2100 rd_off++;
2101 GNUNET_free (rname);
2102 }
2103 break;
2104
2106 {
2107 char *cname;
2108
2109 off = 0;
2111 rd[i].data_size,
2112 &off);
2113 if ((NULL == cname) ||
2114 (off != rd[i].data_size))
2115 {
2116 GNUNET_break_op (0); /* record not well-formed */
2117 }
2118 else
2119 {
2120 cname = translate_dot_plus (rh, cname);
2121 GNUNET_break (NULL != cname);
2122 scratch_start = scratch_off;
2123 if (GNUNET_OK !=
2125 sizeof(scratch),
2126 &scratch_off,
2127 cname))
2128 {
2129 GNUNET_break (0);
2130 }
2131 else
2132 {
2133 GNUNET_assert (rd_off < rd_count);
2134 rd_new[rd_off].data = &scratch[scratch_start];
2135 rd_new[rd_off].data_size = scratch_off - scratch_start;
2136 rd_off++;
2137 }
2138 }
2139 GNUNET_free (cname);
2140 }
2141 break;
2142
2144 {
2145 struct GNUNET_DNSPARSER_SoaRecord *soa;
2146
2147 off = 0;
2149 rd[i].data_size,
2150 &off);
2151 if ((NULL == soa) ||
2152 (off != rd[i].data_size))
2153 {
2154 GNUNET_break_op (0); /* record not well-formed */
2155 }
2156 else
2157 {
2158 soa->mname = translate_dot_plus (rh, soa->mname);
2159 soa->rname = translate_dot_plus (rh, soa->rname);
2160 scratch_start = scratch_off;
2161 if (GNUNET_OK !=
2163 sizeof(scratch),
2164 &scratch_off,
2165 soa))
2166 {
2167 GNUNET_break (0);
2168 }
2169 else
2170 {
2171 GNUNET_assert (rd_off < rd_count);
2172 rd_new[rd_off].data = &scratch[scratch_start];
2173 rd_new[rd_off].data_size = scratch_off - scratch_start;
2174 rd_off++;
2175 }
2176 }
2177 if (NULL != soa)
2179 }
2180 break;
2181
2183 {
2184 struct GNUNET_DNSPARSER_MxRecord *mx;
2185
2186 off = 0;
2188 rd[i].data_size,
2189 &off);
2190 if ((NULL == mx) ||
2191 (off != rd[i].data_size))
2192 {
2193 GNUNET_break_op (0); /* record not well-formed */
2194 }
2195 else
2196 {
2197 mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2198 scratch_start = scratch_off;
2199 if (GNUNET_OK !=
2201 sizeof(scratch),
2202 &scratch_off,
2203 mx))
2204 {
2205 GNUNET_break (0);
2206 }
2207 else
2208 {
2209 GNUNET_assert (rd_off < rd_count);
2210 rd_new[rd_off].data = &scratch[scratch_start];
2211 rd_new[rd_off].data_size = scratch_off - scratch_start;
2212 rd_off++;
2213 }
2214 }
2215 if (NULL != mx)
2217 }
2218 break;
2219
2221 {
2222 struct GNUNET_DNSPARSER_SrvRecord *srv;
2223
2224 off = 0;
2226 rd[i].data_size,
2227 &off);
2228 if ((NULL == srv) ||
2229 (off != rd[i].data_size))
2230 {
2231 GNUNET_break_op (0); /* record not well-formed */
2232 }
2233 else
2234 {
2235 srv->target = translate_dot_plus (rh, srv->target);
2236 scratch_start = scratch_off;
2237 if (GNUNET_OK !=
2239 sizeof(scratch),
2240 &scratch_off,
2241 srv))
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 != srv)
2255 }
2256 break;
2257
2259 {
2261
2262 off = 0;
2264 rd[i].data_size,
2265 &off);
2266 if ((NULL == uri) ||
2267 (off != rd[i].data_size))
2268 {
2270 _ ("Failed to deserialize URI record with target\n"));
2271 GNUNET_break_op (0); /* record not well-formed */
2272 }
2273 else
2274 {
2275 scratch_start = scratch_off;
2276 if (GNUNET_OK !=
2278 sizeof(scratch),
2279 &scratch_off,
2280 uri))
2281 {
2282 GNUNET_break (0);
2283 }
2284 else
2285 {
2286 GNUNET_assert (rd_off < rd_count);
2287 rd_new[rd_off].data = &scratch[scratch_start];
2288 rd_new[rd_off].data_size = scratch_off - scratch_start;
2289 rd_off++;
2290 }
2291 }
2292 if (NULL != uri)
2294 }
2295 break;
2296
2299 {
2301 if (rd[i].data_size < sizeof(uint32_t))
2302 {
2303 GNUNET_break_op (0);
2304 break;
2305 }
2306 if (GNUNET_OK !=
2308 rd[i].data_size,
2309 rd[i].record_type,
2310 &pubkey))
2311 {
2312 GNUNET_break_op (0);
2313 break;
2314 }
2315 rd_off++;
2316 if (rd[i].record_type != rh->record_type)
2317 {
2318 /* try to resolve "@" */
2319 struct AuthorityChain *ac;
2320
2321 ac = GNUNET_new (struct AuthorityChain);
2322 ac->rh = rh;
2327 rh->ac_tail,
2328 ac);
2330 rh);
2331 return;
2332 }
2333 }
2334 break;
2335
2337 {
2338 /* delegation to DNS */
2340 {
2341 rd_off++;
2342 break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2343 }
2345 "Found GNS2DNS record, delegating to DNS!\n");
2346 if (GNUNET_OK ==
2348 rd_count,
2349 rd))
2350 return;
2351 else
2352 goto fail;
2353 }
2354
2356 {
2357 /* unbox SRV/TLSA records if a specific one was requested */
2358 if ((0 != rh->protocol) &&
2359 (0 != rh->service) &&
2360 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2361 {
2362 const struct GNUNET_GNSRECORD_BoxRecord *box;
2363
2364 box = rd[i].data;
2366 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2367 ntohs (box->protocol), ntohs (box->service),
2368 rh->protocol, rh->service);
2369 if ((ntohs (box->protocol) == rh->protocol) &&
2370 (ntohs (box->service) == rh->service))
2371 {
2372 /* Box matches, unbox! */
2373 GNUNET_assert (rd_off < rd_count);
2374 rd_new[rd_off].record_type = ntohl (box->record_type);
2375 rd_new[rd_off].data_size -= sizeof(struct
2377 rd_new[rd_off].data = &box[1];
2378 rd_off++;
2379 }
2380 }
2381 else
2382 {
2383 /* no specific protocol/service specified, preserve all BOX
2384 records (for modern, GNS-enabled applications) */
2385 rd_off++;
2386 }
2387 break;
2388 }
2390 {
2391 /* unbox SBOX records if a specific one was requested */
2392 if ((rh->prefix != NULL) &&
2393 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2394 {
2395 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2396
2397 box = rd[i].data;
2398 const char *prefix = rd[i].data + sizeof(struct
2400 size_t prefix_len = strnlen (prefix, rd[i].data_size - sizeof(struct
2402 + 1;
2403 if (prefix_len - 1 >= rd[i].data_size - sizeof(struct
2405 {
2407 "SBOX record with invalid prefix length, maybe not null-terminated\n");
2408 continue;
2409 }
2411 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2412 prefix, rh->prefix);
2413 if (strcmp (rh->prefix, prefix) == 0)
2414 {
2415 /* Box matches, unbox! */
2416 GNUNET_assert (rd_off < rd_count);
2417 rd_new[rd_off].record_type = ntohl (box->record_type);
2418 rd_new[rd_off].data_size -= sizeof(struct
2420 + prefix_len;
2421 rd_new[rd_off].data = rd[i].data
2422 + sizeof(struct GNUNET_GNSRECORD_SBoxRecord)
2423 + prefix_len;
2424 rd_off++;
2425 }
2426 }
2427 else
2428 {
2430 _ (
2431 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2432 rh->name);
2433 /* no specific protocol/service specified, preserve all SBOX
2434 records (for modern, GNS-enabled applications) */
2435 rd_off++;
2436 }
2437 break;
2438 }
2439 default:
2440 rd_off++;
2441 break;
2442 } /* end: switch */
2443 } /* end: for rd_count */
2444
2445 GNUNET_free (rh->prefix);
2446 rh->prefix = NULL;
2447
2448 /* yes, we are done, return result */
2450 "Returning GNS response for `%s' with %u answers\n",
2451 rh->ac_tail->label,
2452 rd_off);
2453 rh->proc (rh->proc_cls,
2454 rd_off,
2455 rd_new);
2457 rh);
2458 return;
2459 }
2460
2461 switch (rd[0].record_type)
2462 {
2464 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2466 &rd[0]);
2467 return;
2468
2470 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2472 &rd[0]);
2473 return;
2474
2477 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2479 &rd[0]);
2480 return;
2481
2483 if (GNUNET_OK ==
2485 rd_count,
2486 rd))
2487 return;
2488 break;
2489 default:
2491 return;
2493 _ ("Unable to process critical delegation record\n"));
2494 break;
2495 }
2496fail:
2498 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2499 fail_resolution (rh);
2500}
2501
2502
2511static void
2513 int32_t success,
2514 const char *emsg)
2515{
2516 struct CacheOps *co = cls;
2517
2518 co->namecache_qe_cache = NULL;
2519 if (GNUNET_OK != success)
2521 _ ("Failed to cache GNS resolution: %s\n"),
2522 emsg);
2524 co_tail,
2525 co);
2526 GNUNET_free (co);
2527}
2528
2529
2548static void
2550 struct GNUNET_TIME_Absolute exp,
2551 const struct GNUNET_HashCode *key,
2552 const struct GNUNET_PeerIdentity *trunc_peer,
2553 const struct GNUNET_DHT_PathElement *get_path,
2554 unsigned int get_path_length,
2555 const struct GNUNET_DHT_PathElement *put_path,
2556 unsigned int put_path_length,
2558 size_t size,
2559 const void *data)
2560{
2561 struct GNS_ResolverHandle *rh = cls;
2562 struct AuthorityChain *ac = rh->ac_tail;
2563 const struct GNUNET_GNSRECORD_Block *block;
2564 struct CacheOps *co;
2565
2566 (void) exp;
2567 (void) key;
2568 (void) get_path;
2569 (void) get_path_length;
2570 (void) put_path;
2571 (void) put_path_length;
2572 (void) type;
2574 rh->get_handle = NULL;
2576 rh->dht_heap_node = NULL;
2578 "Handling response from the DHT\n");
2579 if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2580 {
2581 /* how did this pass DHT block validation!? */
2582 GNUNET_break (0);
2583 fail_resolution (rh);
2584 return;
2585 }
2586 block = data;
2588 {
2589 /* how did this pass DHT block validation!? */
2590 GNUNET_break (0);
2591 fail_resolution (rh);
2592 return;
2593 }
2595 "Decrypting DHT block of size %llu for `%s', expires %s\n",
2596 (unsigned long long) GNUNET_GNSRECORD_block_get_size (block),
2597 rh->name,
2599 if (GNUNET_OK !=
2602 ac->label,
2604 rh))
2605 {
2606 GNUNET_break_op (0); /* block was ill-formed */
2607 fail_resolution (rh);
2608 return;
2609 }
2612 rel_value_us)
2613 {
2615 "Received expired block from the DHT, will not cache it.\n");
2616 return;
2617 }
2619 return;
2620 /* Cache well-formed blocks */
2622 "Caching response from the DHT in namecache\n");
2623 co = GNUNET_new (struct CacheOps);
2625 block,
2626 &
2628 co);
2630 co_tail,
2631 co);
2632}
2633
2634
2641static void
2643 const struct GNUNET_HashCode *query)
2644{
2645 struct GNS_ResolverHandle *rx;
2646
2647 GNUNET_assert (NULL == rh->get_handle);
2650 query,
2653 NULL, 0,
2654 &handle_dht_response, rh);
2656 rh,
2658 abs_value_us);
2661 {
2662 /* fail longest-standing DHT request */
2664 rx->dht_heap_node = NULL;
2665 GNUNET_assert (NULL != rx);
2666 fail_resolution (rx);
2667 }
2668}
2669
2670
2679static void
2681 unsigned int rd_count,
2682 const struct GNUNET_GNSRECORD_Data *rd)
2683{
2684 struct GNS_ResolverHandle *rh = cls;
2685
2686 if (0 == rd_count)
2688 _ ("GNS namecache returned empty result for `%s'\n"),
2689 rh->name);
2691 rd_count,
2692 rd);
2693}
2694
2695
2702static void
2704 const struct GNUNET_GNSRECORD_Block *block)
2705{
2706 struct GNS_ResolverHandle *rh = cls;
2707 struct AuthorityChain *ac = rh->ac_tail;
2708 const char *label = ac->label;
2709 const struct GNUNET_CRYPTO_PublicKey *auth =
2711 struct GNUNET_HashCode query;
2712
2713 GNUNET_assert (NULL != rh->namecache_qe);
2714 rh->namecache_qe = NULL;
2715 if (NULL == block)
2717 "No block found\n");
2718 else
2720 "Got block with expiration %s\n",
2723 if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2725 (ac != rh->ac_head))) &&
2726 ((NULL == block) ||
2729 rel_value_us)))
2730 {
2731 /* namecache knows nothing; try DHT lookup */
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 if ((NULL == block) ||
2747 rel_value_us))
2748 {
2749 /* DHT not permitted and no local result, fail */
2751 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2752 ac->label,
2754 fail_resolution (rh);
2755 return;
2756 }
2758 "Received result from namecache for label `%s'\n",
2759 ac->label);
2760
2761 if (GNUNET_OK !=
2763 auth,
2764 label,
2766 rh))
2767 {
2768 GNUNET_break_op (0); /* block was ill-formed */
2769 /* try DHT instead */
2771 label,
2772 &query);
2774 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2775 ac->label,
2777 GNUNET_h2s (&query));
2778 start_dht_request (rh, &query);
2779 return;
2780 }
2781}
2782
2783
2789static void
2791{
2792 struct AuthorityChain *ac = rh->ac_tail;
2793 struct GNUNET_HashCode query;
2794
2796 "Starting GNS resolution for `%s' in zone %s\n",
2797 ac->label,
2800 ac->label,
2801 &query);
2803 {
2804 rh->namecache_qe
2806 &query,
2808 rh);
2809 GNUNET_assert (NULL != rh->namecache_qe);
2810 }
2811 else
2812 {
2814 &query);
2815 }
2816}
2817
2818
2825static void
2827 int is_valid)
2828{
2829 struct GNS_ResolverHandle *rh = cls;
2830 struct AuthorityChain *ac = rh->ac_tail;
2831
2832 rh->rev_check = NULL;
2833 if (GNUNET_YES != is_valid)
2834 {
2836 _ ("Zone %s was revoked, resolution fails\n"),
2839 return;
2840 }
2842}
2843
2844
2850static void
2852{
2853 struct AuthorityChain *ac = rh->ac_tail;
2854
2856 "Starting revocation check for zone %s\n",
2861 rh);
2862 GNUNET_assert (NULL != rh->rev_check);
2863}
2864
2865
2866static void
2868{
2869 struct GNS_ResolverHandle *rh = cls;
2870
2871 rh->task_id = NULL;
2872 if (rh->loop_threshold < rh->loop_limiter++)
2873 {
2875 "Encountered unbounded recursion resolving `%s'\n",
2876 rh->name);
2877 fail_resolution (rh);
2878 return;
2879 }
2880 if (GNUNET_YES == rh->ac_tail->gns_authority)
2882 else
2884}
2885
2886
2887static void
2889{
2890 struct GNS_ResolverHandle *rh = cls;
2891 struct AuthorityChain *ac;
2892 struct in_addr v4;
2893 struct in6_addr v6;
2894
2895 rh->task_id = NULL;
2896 if (1 == inet_pton (AF_INET,
2897 rh->name,
2898 &v4))
2899 {
2900 /* name is IPv4 address, pretend it's an A record */
2902
2903 rd.data = &v4;
2904 rd.data_size = sizeof(v4);
2905 rd.expiration_time = UINT64_MAX;
2907 rd.flags = 0;
2908 rh->proc (rh->proc_cls,
2909 1,
2910 &rd);
2911 GNUNET_assert (NULL == rh->task_id);
2913 rh);
2914 return;
2915 }
2916 if (1 == inet_pton (AF_INET6,
2917 rh->name,
2918 &v6))
2919 {
2920 /* name is IPv6 address, pretend it's an AAAA record */
2922
2923 rd.data = &v6;
2924 rd.data_size = sizeof(v6);
2925 rd.expiration_time = UINT64_MAX;
2927 rd.flags = 0;
2928 rh->proc (rh->proc_cls,
2929 1,
2930 &rd);
2931 GNUNET_assert (NULL == rh->task_id);
2933 rh);
2934 return;
2935 }
2936
2937 ac = GNUNET_new (struct AuthorityChain);
2938 ac->rh = rh;
2940 if (NULL == ac->label)
2941 /* name was just the "TLD", so we default to label
2942 #GNUNET_GNS_EMPTY_LABEL_AT */
2947 rh->ac_tail,
2948 ac);
2950 rh);
2951}
2952
2953
2968struct GNS_ResolverHandle *
2970 uint32_t record_type,
2971 const char *name,
2973 uint16_t recursion_depth_limit,
2975 void *proc_cls)
2976{
2977 struct GNS_ResolverHandle *rh;
2978
2980 "Starting lookup for `%s'\n",
2981 name);
2982 rh = GNUNET_new (struct GNS_ResolverHandle);
2984 rlh_tail,
2985 rh);
2986 rh->authority_zone = *zone;
2987 rh->proc = proc;
2988 rh->proc_cls = proc_cls;
2989 rh->options = options;
2991 rh->name = GNUNET_strdup (name);
2992 rh->name_resolution_pos = strlen (name);
2993 rh->loop_threshold = recursion_depth_limit;
2995 rh);
2996 return rh;
2997}
2998
2999
3005void
3007{
3008 struct DnsResult *dr;
3009 struct AuthorityChain *ac;
3010
3012 rlh_tail,
3013 rh);
3014 if (NULL != rh->dns_request)
3015 {
3017 rh->dns_request = NULL;
3018 }
3019 while (NULL != (ac = rh->ac_head))
3020 {
3022 rh->ac_tail,
3023 ac);
3024 if (GNUNET_NO == ac->gns_authority)
3025 {
3026 struct Gns2DnsPending *gp;
3027
3028 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
3029 {
3032 gp);
3033 if (NULL != gp->rh)
3034 {
3035 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
3036 using GNS_resolver_lookup_cancel here, we need to
3037 add it first... */
3039 rlh_tail,
3040 gp->rh);
3041 GNUNET_assert (NULL == gp->rh->task_id);
3044 gp->rh);
3045 gp->rh = NULL;
3046 }
3047 if (NULL != gp->dns_rh)
3048 {
3050 gp->dns_rh = NULL;
3051 }
3052 GNUNET_free (gp);
3053 }
3055 }
3056 GNUNET_free (ac->label);
3057 GNUNET_free (ac);
3058 }
3059 if (NULL != rh->task_id)
3060 {
3062 rh->task_id = NULL;
3063 }
3064 if (NULL != rh->get_handle)
3065 {
3067 rh->get_handle = NULL;
3068 }
3069 if (NULL != rh->dht_heap_node)
3070 {
3072 rh->dht_heap_node = NULL;
3073 }
3074 if (NULL != rh->namecache_qe)
3075 {
3077 rh->namecache_qe = NULL;
3078 }
3079 if (NULL != rh->rev_check)
3080 {
3082 rh->rev_check = NULL;
3083 }
3084 if (NULL != rh->std_resolve)
3085 {
3087 "Canceling standard DNS resolution\n");
3089 rh->std_resolve = NULL;
3090 }
3091 while (NULL != (dr = rh->dns_result_head))
3092 {
3095 dr);
3096 GNUNET_free (dr);
3097 }
3098 if (NULL != rh->prefix)
3099 {
3101 rh->prefix = NULL;
3102 }
3103 GNUNET_free (rh->leho);
3104 GNUNET_free (rh->name);
3105 GNUNET_free (rh);
3106}
3107
3108
3109/* ***************** Resolver initialization ********************* */
3110
3111
3120void
3122 struct GNUNET_DHT_Handle *dht,
3123 const struct GNUNET_CONFIGURATION_Handle *c,
3124 unsigned long long max_bg_queries)
3125{
3126 cfg = c;
3128 dht_handle = dht;
3131 max_allowed_background_queries = max_bg_queries;
3133 "namecache",
3134 "DISABLE");
3137 "Namecache disabled\n");
3138}
3139
3140
3144void
3146{
3147 struct GNS_ResolverHandle *rh;
3148 struct CacheOps *co;
3149
3150 /* abort active resolutions */
3151 while (NULL != (rh = rlh_head))
3152 {
3153 rh->proc (rh->proc_cls,
3154 0,
3155 NULL);
3157 }
3158 while (NULL != (co = co_head))
3159 {
3161 co_tail,
3162 co);
3164 GNUNET_free (co);
3165 }
3167 dht_lookup_heap = NULL;
3168 dht_handle = NULL;
3169 namecache_handle = NULL;
3170}
3171
3172
3173/* 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
IPC messages between GNS API and GNS service.
static int ret
Final status code.
Definition: gnunet-arm.c:94
static int prefix
If printing the value of PREFIX has been requested.
Definition: gnunet-config.c:59
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.
int is_canonical(const char *name)
Determine if this name is canonical (is a legal name in a zone, without delegation); note that we do ...
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
API to the DHT service.
API to access the DNS 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:1235
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:1162
@ 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:982
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:947
#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:1172
#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:1096
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:1213
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:1392
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:1249
#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:727
#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:247
#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:981
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1305
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1278
#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:405
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:617
#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:178
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)
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.
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?