GNUnet  0.11.x
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 #include "gnunet_util_lib.h"
29 #include "gnunet_dnsstub_lib.h"
30 #include "gnunet_dht_service.h"
31 #include "gnunet_gnsrecord_lib.h"
33 #include "gnunet_dns_service.h"
36 #include "gnunet_dnsparser_lib.h"
37 #include "gnunet_tun_lib.h"
38 #include "gnunet_gns_service.h"
39 #include "gns.h"
40 #include "gnunet-service-gns.h"
42 #include "gnunet_vpn_service.h"
43 
44 
48 #define DHT_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
49  GNUNET_TIME_UNIT_SECONDS, 60)
50 
54 #define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
55  GNUNET_TIME_UNIT_SECONDS, 15)
56 
60 #define VPN_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
61 
65 #define DHT_GNS_REPLICATION_LEVEL 10
66 
70 #define MAX_RECURSION 256
71 
72 
77 struct AuthorityChain;
78 
79 
86 {
91 
96 
101 
108 
113 
117  unsigned int num_results;
118 };
119 
120 
125 struct GNS_ResolverHandle;
126 
127 
133 {
138 
143 
148 
152  char *label;
153 
159 
163  union
164  {
168  struct GNUNET_CRYPTO_EcdsaPublicKey gns_authority;
169 
170  struct
171  {
178 
184 
190 
195 
200  int found;
201 
205  int launched;
206  } dns_authority;
207  } authority_info;
208 };
209 
210 
214 struct DnsResult
215 {
219  struct DnsResult *next;
220 
224  struct DnsResult *prev;
225 
229  const void *data;
230 
235  uint64_t expiration_time;
236 
240  size_t data_size;
241 
245  uint32_t record_type;
246 };
247 
248 
253 {
258 
263 
267  unsigned int rd_count;
268 
272  char *rd_data;
273 
277  ssize_t rd_data_size;
278 };
279 
280 
286 {
291 
296 
300  struct GNUNET_CRYPTO_EcdsaPublicKey authority_zone;
301 
306 
310  void*proc_cls;
311 
316 
321 
326 
331 
336 
341 
347 
352 
357 
362 
366  char *name;
367 
372  char *leho;
373 
378 
383 
388 
393 
398  int protocol;
399 
404  int service;
405 
410 
416  unsigned int loop_limiter;
417 
421  uint16_t original_dns_id;
422 };
423 
424 
428 struct CacheOps
429 {
433  struct CacheOps *next;
434 
438  struct CacheOps *prev;
439 
444 };
445 
446 
451 
456 
461 
466 
470 static unsigned long long max_allowed_background_queries;
471 
476 
481 
485 static struct CacheOps *co_head;
486 
490 static struct CacheOps *co_tail;
491 
495 static int disable_cache;
496 
500 static const struct GNUNET_CONFIGURATION_Handle *cfg;
501 
502 
518 /* dead, but keep for now */ int
519 is_canonical (const char *name)
520 {
521  const char *pos;
522  const char *dot;
523 
524  if (NULL == strchr (name,
525  (unsigned char) '.'))
526  return GNUNET_YES;
527  if ('_' != name[0])
528  return GNUNET_NO;
529  pos = &name[1];
530  while (NULL != (dot = strchr (pos,
531  (unsigned char) '.')))
532  if ('_' != dot[1])
533  return GNUNET_NO;
534  else
535  pos = dot + 1;
536  return GNUNET_YES;
537 }
538 
539 
540 /* ************************** Resolution **************************** */
541 
549 static char *
551  char *name)
552 {
553  char *ret;
554  size_t s_len = strlen (name);
555 
556  if (0 != strcmp (&name[s_len - 2],
557  ".+"))
558  return name; /* did not end in ".+" */
560  GNUNET_asprintf (&ret,
561  "%.*s.%s",
562  (int) (s_len - 2),
563  name,
566  GNUNET_free (name);
567  return ret;
568 }
569 
570 
577 static void
579 {
580  struct GNS_ResolverHandle *rh = cls;
581 
582  rh->task_id = NULL;
584 }
585 
586 
592 static void
594 {
595  rh->proc (rh->proc_cls,
596  0,
597  NULL);
598  GNUNET_assert (NULL == rh->task_id);
600  rh);
601 }
602 
603 
609 static void
611 {
612  struct GNS_ResolverHandle *rh = cls;
613 
614  rh->task_id = NULL;
615  fail_resolution (rh);
616 }
617 
618 
636 static char *
638 {
639  const char *rp;
640  const char *dot;
641  size_t len;
642  char *ret;
643  char *srv_name;
644  char *proto_name;
645  struct protoent *pe;
646  struct servent *se;
647 
648  if (0 == rh->name_resolution_pos)
649  return NULL;
650  dot = memrchr (rh->name,
651  (int) '.',
652  rh->name_resolution_pos);
653  if (NULL == dot)
654  {
655  /* done, this was the last one */
656  len = rh->name_resolution_pos;
657  rp = rh->name;
658  rh->name_resolution_pos = 0;
659  }
660  else
661  {
662  /* advance by one label */
663  len = rh->name_resolution_pos - (dot - rh->name) - 1;
664  rp = dot + 1;
665  rh->name_resolution_pos = dot - rh->name;
666  }
667  rh->protocol = 0;
668  rh->service = 0;
669  ret = GNUNET_strndup (rp, len);
670  /* If we have labels starting with underscore with label on
671  * the right (SRV/DANE/BOX case), determine port/protocol;
672  * The format of `rh->name` must be "_PORT._PROTOCOL".
673  */
674  if (('_' == rh->name[0]) &&
675  (NULL != (dot = memrchr (rh->name,
676  (int) '.',
677  rh->name_resolution_pos))) &&
678  ('_' == dot[1]) &&
679  (NULL == memrchr (rh->name,
680  (int) '.',
681  dot - rh->name)))
682  {
683  srv_name = GNUNET_strndup (&rh->name[1],
684  (dot - rh->name) - 1);
685  proto_name = GNUNET_strndup (&dot[2],
686  rh->name_resolution_pos - (dot - rh->name)
687  - 1);
688  rh->name_resolution_pos = 0;
689  pe = getprotobyname (proto_name);
690  if (NULL == pe)
691  {
693  _ ("Protocol `%s' unknown, skipping labels.\n"),
694  proto_name);
695  GNUNET_free (proto_name);
696  GNUNET_free (srv_name);
697  return ret;
698  }
699  se = getservbyname (srv_name,
700  proto_name);
701  if (NULL == se)
702  {
704  _ (
705  "Service `%s' unknown for protocol `%s', skipping labels.\n"),
706  srv_name,
707  proto_name);
708  GNUNET_free (proto_name);
709  GNUNET_free (srv_name);
710  return ret;
711  }
712  rh->protocol = pe->p_proto;
713  rh->service = se->s_port;
714  GNUNET_free (proto_name);
715  GNUNET_free (srv_name);
716  }
717  return ret;
718 }
719 
720 
726 static void
728 {
729  struct DnsResult *pos;
730  unsigned int n;
731  unsigned int i;
732 
733  n = 0;
734  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
735  n++;
736  {
737  struct GNUNET_GNSRECORD_Data rd[n];
738 
739  i = 0;
740  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
741  {
742  rd[i].data = pos->data;
743  rd[i].data_size = pos->data_size;
744  rd[i].record_type = pos->record_type;
745  if (0 == pos->expiration_time)
746  {
748  rd[i].expiration_time = 0;
749  }
750  else
751  {
753  rd[i].expiration_time = pos->expiration_time;
754  }
755  i++;
756  }
757  GNUNET_assert (i == n);
759  "Transmitting standard DNS result with %u records\n",
760  n);
761  rh->proc (rh->proc_cls,
762  n,
763  rd);
764  }
766 }
767 
768 
778 static void
780  uint64_t expiration_time,
781  uint32_t record_type,
782  size_t data_size,
783  const void *data)
784 {
785  struct DnsResult *res;
786 
787  res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
789  res->data_size = data_size;
790  res->record_type = record_type;
791  res->data = &res[1];
792  GNUNET_memcpy (&res[1],
793  data,
794  data_size);
796  rh->dns_result_tail,
797  res);
798 }
799 
800 
809 static void
810 handle_dns_result (void *cls,
811  const struct sockaddr *addr,
812  socklen_t addrlen)
813 {
814  struct GNS_ResolverHandle *rh = cls;
815  const struct sockaddr_in *sa4;
816  const struct sockaddr_in6 *sa6;
817 
818  if (NULL == addr)
819  {
820  rh->std_resolve = NULL;
822  return;
823  }
825  "Received %u bytes of DNS IP data\n",
826  addrlen);
827  switch (addr->sa_family)
828  {
829  case AF_INET:
830  sa4 = (const struct sockaddr_in *) addr;
831  add_dns_result (rh,
832  0 /* expiration time is unknown */,
834  sizeof(struct in_addr),
835  &sa4->sin_addr);
836  break;
837 
838  case AF_INET6:
839  sa6 = (const struct sockaddr_in6 *) addr;
840  add_dns_result (rh,
841  0 /* expiration time is unknown */,
843  sizeof(struct in6_addr),
844  &sa6->sin6_addr);
845  break;
846 
847  default:
848  GNUNET_break (0);
849  break;
850  }
851 }
852 
853 
860 static void
861 recursive_resolution (void *cls);
862 
863 
870 static void
871 start_resolver_lookup (void *cls);
872 
873 
882 static void
883 dns_result_parser (void *cls,
884  const struct GNUNET_TUN_DnsHeader *dns,
885  size_t dns_len)
886 {
887  struct GNS_ResolverHandle *rh = cls;
888  struct GNUNET_DNSPARSER_Packet *p;
889  const struct GNUNET_DNSPARSER_Record *rec;
890  unsigned int rd_count;
891 
892  if (NULL == dns)
893  {
894  rh->dns_request = NULL;
896  rh->task_id = NULL;
897  fail_resolution (rh);
898  return;
899  }
900  if (rh->original_dns_id != dns->id)
901  {
902  /* DNS answer, but for another query */
903  return;
904  }
905  p = GNUNET_DNSPARSER_parse ((const char *) dns,
906  dns_len);
907  if (NULL == p)
908  {
910  _ ("Failed to parse DNS response\n"));
911  return;
912  }
913 
914  /* We got a result from DNS */
916  "Received DNS response for `%s' with %u answers\n",
917  rh->ac_tail->label,
918  (unsigned int) p->num_answers);
919  if ((p->num_answers > 0) &&
922  {
923  int af;
924 
926  "Got CNAME `%s' from DNS for `%s'\n",
927  p->answers[0].data.hostname,
928  rh->name);
929  if (NULL != rh->std_resolve)
930  {
932  "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
933  rh->name);
935  }
936  GNUNET_free (rh->name);
937  rh->name = GNUNET_strdup (p->answers[0].data.hostname);
938  rh->name_resolution_pos = strlen (rh->name);
939  switch (rh->record_type)
940  {
942  af = AF_INET;
943  break;
944 
946  af = AF_INET6;
947  break;
948 
949  default:
950  af = AF_UNSPEC;
951  break;
952  }
953  if (NULL != rh->leho)
954  add_dns_result (rh,
955  GNUNET_TIME_UNIT_HOURS.rel_value_us,
957  strlen (rh->leho),
958  rh->leho);
960  af,
963  rh);
966  rh->dns_request = NULL;
967  return;
968  }
969 
970  /* convert from (parsed) DNS to (binary) GNS format! */
971  rd_count = p->num_answers + p->num_authority_records
973  {
974  struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
975  int skip;
976  char buf[UINT16_MAX];
977  size_t buf_off;
978  size_t buf_start;
979 
980  buf_off = 0;
981  skip = 0;
982  memset (rd,
983  0,
984  sizeof(rd));
985  for (unsigned int i = 0; i < rd_count; i++)
986  {
987  if (i < p->num_answers)
988  rec = &p->answers[i];
989  else if (i < p->num_answers + p->num_authority_records)
990  rec = &p->authority_records[i - p->num_answers];
991  else
992  rec = &p->additional_records[i - p->num_answers
993  - p->num_authority_records];
994  /* As we copied the full DNS name to 'rh->ac_tail->label', this
995  should be the correct check to see if this record is actually
996  a record for our label... */
997  if (0 != strcmp (rec->name,
998  rh->ac_tail->label))
999  {
1001  "Dropping record `%s', does not match desired name `%s'\n",
1002  rec->name,
1003  rh->ac_tail->label);
1004  skip++;
1005  continue;
1006  }
1007  rd[i - skip].record_type = rec->type;
1008  rd[i - skip].expiration_time = rec->expiration_time.abs_value_us;
1009  switch (rec->type)
1010  {
1012  if (rec->data.raw.data_len != sizeof(struct in_addr))
1013  {
1014  GNUNET_break_op (0);
1015  skip++;
1016  continue;
1017  }
1018  rd[i - skip].data_size = rec->data.raw.data_len;
1019  rd[i - skip].data = rec->data.raw.data;
1020  break;
1021 
1023  if (rec->data.raw.data_len != sizeof(struct in6_addr))
1024  {
1025  GNUNET_break_op (0);
1026  skip++;
1027  continue;
1028  }
1029  rd[i - skip].data_size = rec->data.raw.data_len;
1030  rd[i - skip].data = rec->data.raw.data;
1031  break;
1032 
1036  buf_start = buf_off;
1037  if (GNUNET_OK !=
1039  sizeof(buf),
1040  &buf_off,
1041  rec->data.hostname))
1042  {
1043  GNUNET_break (0);
1044  skip++;
1045  continue;
1046  }
1047  rd[i - skip].data_size = buf_off - buf_start;
1048  rd[i - skip].data = &buf[buf_start];
1049  break;
1050 
1052  buf_start = buf_off;
1053  if (GNUNET_OK !=
1055  sizeof(buf),
1056  &buf_off,
1057  rec->data.soa))
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.mx))
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.srv))
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 
1099  default:
1101  _ ("Skipping record of unsupported type %d\n"),
1102  rec->type);
1103  skip++;
1104  continue;
1105  }
1106  } /* end of for all records in answer */
1107  if (NULL != rh->leho)
1108  {
1109  rd[rd_count - skip].record_type = GNUNET_GNSRECORD_TYPE_LEHO;
1110  rd[rd_count - skip].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1111  rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1112  rd[rd_count - skip].data = rh->leho;
1113  rd[rd_count - skip].data_size = strlen (rh->leho);
1114  skip--; /* skip one LESS */
1116  "Adding LEHO %s\n",
1117  rh->leho);
1118  }
1120  "Returning DNS response for `%s' with %u answers\n",
1121  rh->ac_tail->label,
1122  (unsigned int) (rd_count - skip));
1123  rh->proc (rh->proc_cls,
1124  rd_count - skip,
1125  rd);
1127  rh->dns_request = NULL;
1128  }
1130  if (NULL != rh->task_id)
1131  GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1133  rh);
1134 }
1135 
1136 
1145 static void
1147 {
1148  struct AuthorityChain *ac;
1149  struct GNUNET_DNSPARSER_Query *query;
1150  struct GNUNET_DNSPARSER_Packet *p;
1151  char *dns_request;
1152  size_t dns_request_length;
1153  int ret;
1154 
1155  ac = rh->ac_tail;
1156  GNUNET_assert (NULL != ac);
1158  "Starting DNS lookup for `%s'\n",
1159  ac->label);
1161  query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1162  query->name = GNUNET_strdup (ac->label);
1163  query->type = rh->record_type;
1165  p = GNUNET_new (struct GNUNET_DNSPARSER_Packet);
1166  p->queries = query;
1167  p->num_queries = 1;
1169  UINT16_MAX);
1171  p->flags.recursion_desired = 1;
1172  ret = GNUNET_DNSPARSER_pack (p,
1173  1024,
1174  &dns_request,
1175  &dns_request_length);
1176  if (GNUNET_OK != ret)
1177  {
1178  GNUNET_break (0);
1179  rh->proc (rh->proc_cls,
1180  0,
1181  NULL);
1182  GNUNET_assert (NULL == rh->task_id);
1184  rh);
1185  }
1186  else
1187  {
1188  rh->original_dns_id = p->id;
1189  GNUNET_assert (NULL != ac->authority_info.dns_authority.dns_handle);
1190  GNUNET_assert (NULL == rh->dns_request);
1191  rh->leho = GNUNET_strdup (ac->label);
1193  ac->authority_info.dns_authority.dns_handle,
1194  dns_request,
1195  dns_request_length,
1197  rh);
1200  rh);
1201  }
1202  if (GNUNET_SYSERR != ret)
1203  GNUNET_free (dns_request);
1205 }
1206 
1207 
1216 static void
1218  const char *cname)
1219 {
1220  size_t nlen;
1221  char *res;
1222  struct AuthorityChain *ac;
1223  int af;
1224 
1225  nlen = strlen (cname);
1226  if ((nlen > 2) &&
1227  (0 == strcmp (".+",
1228  &cname[nlen - 2])))
1229  {
1230  /* CNAME resolution continues relative to current domain */
1231  if (0 == rh->name_resolution_pos)
1232  {
1233  res = GNUNET_strndup (cname, nlen - 2);
1234  rh->name_resolution_pos = nlen - 2;
1235  }
1236  else
1237  {
1238  GNUNET_asprintf (&res,
1239  "%.*s.%.*s",
1240  (int) rh->name_resolution_pos,
1241  rh->name,
1242  (int) (nlen - 2),
1243  cname);
1244  rh->name_resolution_pos = strlen (res);
1245  }
1246  GNUNET_free (rh->name);
1247  rh->name = res;
1248  ac = GNUNET_new (struct AuthorityChain);
1249  ac->rh = rh;
1250  ac->gns_authority = GNUNET_YES;
1254  /* add AC to tail */
1256  rh->ac_tail,
1257  ac);
1259  rh);
1260  return;
1261  }
1263  "Got CNAME `%s' from GNS for `%s'\n",
1264  cname,
1265  rh->name);
1266  if (NULL != rh->std_resolve)
1267  {
1269  "Multiple CNAME results from GNS resolving `%s'! Not really allowed...\n",
1270  rh->name);
1272  }
1273  /* name is absolute, go to DNS */
1274  GNUNET_free (rh->name);
1275  rh->name = GNUNET_strdup (cname);
1276  rh->name_resolution_pos = strlen (rh->name);
1277  switch (rh->record_type)
1278  {
1280  af = AF_INET;
1281  break;
1282 
1284  af = AF_INET6;
1285  break;
1286 
1287  default:
1288  af = AF_UNSPEC;
1289  break;
1290  }
1292  "Doing standard DNS lookup for `%s'\n",
1293  rh->name);
1295  af,
1298  rh);
1299 }
1300 
1301 
1309 static void
1310 handle_gns_resolution_result (void *cls,
1311  unsigned int rd_count,
1312  const struct GNUNET_GNSRECORD_Data *rd);
1313 
1314 
1329 static void
1331  int af,
1332  const void *address)
1333 {
1334  struct VpnContext *vpn_ctx = cls;
1335  struct GNS_ResolverHandle *rh = vpn_ctx->rh;
1336  struct GNUNET_GNSRECORD_Data rd[vpn_ctx->rd_count];
1337  unsigned int i;
1338 
1339  vpn_ctx->vpn_request = NULL;
1340  rh->vpn_ctx = NULL;
1343  (size_t) vpn_ctx->rd_data_size,
1344  vpn_ctx->rd_data,
1345  vpn_ctx->rd_count,
1346  rd));
1347  for (i = 0; i < vpn_ctx->rd_count; i++)
1348  {
1350  {
1351  switch (af)
1352  {
1353  case AF_INET:
1355  rd[i].data_size = sizeof(struct in_addr);
1358  rd[i].flags = 0;
1359  rd[i].data = address;
1360  break;
1361 
1362  case AF_INET6:
1366  rd[i].flags = 0;
1367  rd[i].data = address;
1368  rd[i].data_size = sizeof(struct in6_addr);
1369  break;
1370 
1371  default:
1372  GNUNET_assert (0);
1373  }
1374  break;
1375  }
1376  }
1377  GNUNET_assert (i < vpn_ctx->rd_count);
1378  if (0 == vpn_ctx->rd_count)
1380  _ ("VPN returned empty result for `%s'\n"),
1381  rh->name);
1383  vpn_ctx->rd_count,
1384  rd);
1385  GNUNET_free (vpn_ctx->rd_data);
1386  GNUNET_free (vpn_ctx);
1387 }
1388 
1389 
1397 static void
1399 {
1400  struct GNS_ResolverHandle *rh = ac->rh;
1401 
1402  if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1403  (GNUNET_NO == ac->authority_info.dns_authority.found))
1404  return; /* more pending and none found yet */
1405  if (GNUNET_NO == ac->authority_info.dns_authority.found)
1406  {
1408  "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1409  ac->authority_info.dns_authority.name);
1410  fail_resolution (rh);
1411  return;
1412  }
1413  if (GNUNET_NO != ac->authority_info.dns_authority.launched)
1414  return; /* already running, do not launch again! */
1415  /* recurse */
1416  ac->authority_info.dns_authority.launched = GNUNET_YES;
1418  "Will continue resolution using DNS to resolve `%s'\n",
1419  ac->label);
1420  GNUNET_assert (NULL == rh->task_id);
1422  rh);
1423 }
1424 
1425 
1434 static void
1436  unsigned int rd_count,
1437  const struct GNUNET_GNSRECORD_Data *rd)
1438 {
1439  struct Gns2DnsPending *gp = cls;
1440  struct AuthorityChain *ac = gp->ac;
1441 
1443  ac->authority_info.dns_authority.gp_tail,
1444  gp);
1445  /* enable cleanup of 'rh' handle that automatically comes after we return,
1446  and which expects 'rh' to be in the #rlh_head DLL. */
1447  if (NULL != gp->rh)
1448  {
1449  GNUNET_CONTAINER_DLL_insert (rlh_head,
1450  rlh_tail,
1451  gp->rh);
1452  gp->rh = NULL;
1453  }
1454  GNUNET_free (gp);
1456  "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1457  rd_count);
1458  /* find suitable A/AAAA record */
1459  for (unsigned int j = 0; j < rd_count; j++)
1460  {
1461  switch (rd[j].record_type)
1462  {
1464  {
1465  struct sockaddr_in v4;
1466 
1467  if (sizeof(struct in_addr) != rd[j].data_size)
1468  {
1469  GNUNET_break_op (0);
1470  continue;
1471  }
1472  memset (&v4,
1473  0,
1474  sizeof(v4));
1475  v4.sin_family = AF_INET;
1476  v4.sin_port = htons (53);
1477 #if HAVE_SOCKADDR_IN_SIN_LEN
1478  v4.sin_len = (u_char) sizeof(v4);
1479 #endif
1480  GNUNET_memcpy (&v4.sin_addr,
1481  rd[j].data,
1482  sizeof(struct in_addr));
1483  if (GNUNET_OK ==
1485  ac->authority_info.dns_authority.dns_handle,
1486  (const struct sockaddr *) &v4))
1488  break;
1489  }
1490 
1492  {
1493  struct sockaddr_in6 v6;
1494 
1495  if (sizeof(struct in6_addr) != rd[j].data_size)
1496  {
1497  GNUNET_break_op (0);
1498  continue;
1499  }
1500  /* FIXME: might want to check if we support IPv6 here,
1501  and otherwise skip this one and hope we find another */
1502  memset (&v6,
1503  0,
1504  sizeof(v6));
1505  v6.sin6_family = AF_INET6;
1506  v6.sin6_port = htons (53);
1507 #if HAVE_SOCKADDR_IN_SIN_LEN
1508  v6.sin6_len = (u_char) sizeof(v6);
1509 #endif
1510  GNUNET_memcpy (&v6.sin6_addr,
1511  rd[j].data,
1512  sizeof(struct in6_addr));
1513  if (GNUNET_OK ==
1515  ac->authority_info.dns_authority.dns_handle,
1516  (const struct sockaddr *) &v6))
1518  break;
1519  }
1520 
1521  default:
1522  break;
1523  }
1524  }
1525  continue_with_gns2dns (ac);
1526 }
1527 
1528 
1536 static void
1538  const struct sockaddr *addr,
1539  socklen_t addrlen)
1540 {
1541  struct Gns2DnsPending *gp = cls;
1542  struct AuthorityChain *ac = gp->ac;
1543  struct sockaddr_storage ss;
1544  struct sockaddr_in *v4;
1545  struct sockaddr_in6 *v6;
1546 
1547  if (NULL == addr)
1548  {
1549  /* DNS resolution finished */
1550  if (0 == gp->num_results)
1552  "Failed to use DNS to resolve name of DNS resolver\n");
1554  ac->authority_info.dns_authority.gp_tail,
1555  gp);
1556  GNUNET_free (gp);
1557  continue_with_gns2dns (ac);
1558  return;
1559  }
1560  GNUNET_memcpy (&ss,
1561  addr,
1562  addrlen);
1563  switch (ss.ss_family)
1564  {
1565  case AF_INET:
1566  v4 = (struct sockaddr_in *) &ss;
1567  v4->sin_port = htons (53);
1568  gp->num_results++;
1569  break;
1570 
1571  case AF_INET6:
1572  v6 = (struct sockaddr_in6 *) &ss;
1573  v6->sin6_port = htons (53);
1574  gp->num_results++;
1575  break;
1576 
1577  default:
1579  "Unsupported AF %d\n",
1580  ss.ss_family);
1581  return;
1582  }
1583  if (GNUNET_OK ==
1585  (struct sockaddr *) &ss))
1587 }
1588 
1589 
1596 static void
1598  const struct GNUNET_GNSRECORD_Data *rd)
1599 {
1600  char *cname;
1601  size_t off;
1602 
1603  off = 0;
1604  cname = GNUNET_DNSPARSER_parse_name (rd->data,
1605  rd->data_size,
1606  &off);
1607  if ((NULL == cname) ||
1608  (off != rd->data_size))
1609  {
1610  GNUNET_break_op (0); /* record not well-formed */
1611  GNUNET_free_non_null (cname);
1612  fail_resolution (rh);
1613  return;
1614  }
1616  cname);
1617  GNUNET_free (cname);
1618 }
1619 
1620 
1627 static void
1629  const struct GNUNET_GNSRECORD_Data *rd)
1630 {
1631  struct AuthorityChain *ac;
1632 
1633  /* delegation to another zone */
1634  if (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) !=
1635  rd->data_size)
1636  {
1637  GNUNET_break_op (0);
1638  fail_resolution (rh);
1639  return;
1640  }
1641  /* expand authority chain */
1642  ac = GNUNET_new (struct AuthorityChain);
1643  ac->rh = rh;
1644  ac->gns_authority = GNUNET_YES;
1646  rd->data,
1647  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
1649  /* add AC to tail */
1651  rh->ac_tail,
1652  ac);
1653  /* recurse */
1655  rh);
1656 }
1657 
1658 
1669 static int
1671  unsigned int rd_count,
1672  const struct GNUNET_GNSRECORD_Data *rd)
1673 {
1674  struct AuthorityChain *ac;
1675  const char *tld;
1676  char *ns;
1677 
1678  ns = NULL;
1679  /* expand authority chain */
1680  ac = GNUNET_new (struct AuthorityChain);
1681  ac->rh = rh;
1682  ac->authority_info.dns_authority.dns_handle = GNUNET_DNSSTUB_start (4);
1683 
1684  for (unsigned int i = 0; i < rd_count; i++)
1685  {
1686  char *ip;
1687  char *n;
1688  size_t off;
1689  struct Gns2DnsPending *gp;
1690  struct GNUNET_CRYPTO_EcdsaPublicKey zone;
1691  struct sockaddr_in v4;
1692  struct sockaddr_in6 v6;
1693 
1694  if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1695  continue;
1696  off = 0;
1697  n = GNUNET_DNSPARSER_parse_name (rd[i].data,
1698  rd[i].data_size,
1699  &off);
1700  ip = GNUNET_DNSPARSER_parse_name (rd[i].data,
1701  rd[i].data_size,
1702  &off);
1703  if ((NULL == n) ||
1704  (NULL == ip) ||
1705  (off != rd[i].data_size))
1706  {
1707  GNUNET_break_op (0);
1709  GNUNET_free_non_null (ip);
1710  continue;
1711  }
1712  /* resolve 'ip' to determine the IP(s) of the DNS
1713  resolver to use for lookup of 'ns' */
1714  if (NULL != ns)
1715  {
1716  if (0 != strcasecmp (ns,
1717  n))
1718  {
1719  /* NS values must all be the same for all GNS2DNS records,
1720  anything else leads to insanity */
1721  GNUNET_break_op (0);
1722  GNUNET_free (n);
1723  GNUNET_free (ip);
1724  continue;
1725  }
1726  GNUNET_free (n);
1727  }
1728  else
1729  {
1730  ns = n;
1731  }
1732 
1733  /* check if 'ip' is already an IPv4/IPv6 address */
1734  if ((1 == inet_pton (AF_INET,
1735  ip,
1736  &v4)) ||
1737  (1 == inet_pton (AF_INET6,
1738  ip,
1739  &v6)))
1740  {
1743  ac->authority_info.dns_authority.dns_handle,
1744  ip));
1746  GNUNET_free (ip);
1747  continue;
1748  }
1749  tld = GNS_get_tld (ip);
1750  if (0 != strcmp (tld,
1751  "+"))
1752  {
1753  /* 'ip' is a DNS name */
1754  gp = GNUNET_new (struct Gns2DnsPending);
1755  gp->ac = ac;
1757  ac->authority_info.dns_authority.gp_tail,
1758  gp);
1759  gp->dns_rh = GNUNET_RESOLVER_ip_get (ip,
1760  AF_UNSPEC,
1763  gp);
1764  GNUNET_free (ip);
1765  continue;
1766  }
1767  /* 'ip' should be a GNS name */
1768  gp = GNUNET_new (struct Gns2DnsPending);
1769  gp->ac = ac;
1771  ac->authority_info.dns_authority.gp_tail,
1772  gp);
1773  gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1774  ip = translate_dot_plus (rh,
1775  ip);
1776  tld = GNS_get_tld (ip);
1777  if (GNUNET_OK !=
1779  &zone))
1780  {
1781  GNUNET_break_op (0);
1782  GNUNET_free (ip);
1783  continue;
1784  }
1785  gp->rh->authority_zone = zone;
1787  "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1788  ip,
1789  ns);
1790  gp->rh->name = ip;
1791  gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1792  gp->rh->proc = &handle_gns2dns_result;
1793  gp->rh->proc_cls = gp;
1796  gp->rh->loop_limiter = rh->loop_limiter + 1;
1797  gp->rh->task_id
1799  gp->rh);
1800  } /* end 'for all records' */
1801 
1802  if (NULL == ns)
1803  {
1804  /* not a single GNS2DNS record found */
1805  GNUNET_free (ac);
1806  return GNUNET_SYSERR;
1807  }
1809  strcpy (ac->authority_info.dns_authority.name,
1810  ns);
1811  /* for DNS recursion, the label is the full DNS name,
1812  created from the remainder of the GNS name and the
1813  name in the NS record */
1814  GNUNET_asprintf (&ac->label,
1815  "%.*s%s%s",
1816  (int) rh->name_resolution_pos,
1817  rh->name,
1818  (0 != rh->name_resolution_pos) ? "." : "",
1819  ns);
1820  GNUNET_free (ns);
1822  rh->ac_tail,
1823  ac);
1824  if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1825  {
1827  _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1828  ac->label);
1829  return GNUNET_SYSERR;
1830  }
1831  continue_with_gns2dns (ac);
1832  return GNUNET_OK;
1833 }
1834 
1835 
1843 static void
1845  unsigned int rd_count,
1846  const struct GNUNET_GNSRECORD_Data *rd)
1847 {
1848  struct GNS_ResolverHandle *rh = cls;
1849  char *cname;
1850  struct VpnContext *vpn_ctx;
1851  const struct GNUNET_TUN_GnsVpnRecord *vpn;
1852  const char *vname;
1853  struct GNUNET_HashCode vhash;
1854  int af;
1855  char scratch[UINT16_MAX];
1856  size_t scratch_off;
1857  size_t scratch_start;
1858  size_t off;
1859  struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1860  unsigned int rd_off;
1861 
1863  "Resolution succeeded for `%s' in zone %s, got %u records\n",
1864  rh->ac_tail->label,
1866  rd_count);
1867  if (0 == rd_count)
1868  {
1870  _ ("GNS lookup failed (zero records found for `%s')\n"),
1871  rh->name);
1872  fail_resolution (rh);
1873  return;
1874  }
1875 
1876  if (0 == rh->name_resolution_pos)
1877  {
1878  /* top-level match, are we done yet? */
1879  if ((rd_count > 0) &&
1882  {
1883  off = 0;
1884  cname = GNUNET_DNSPARSER_parse_name (rd[0].data,
1885  rd[0].data_size,
1886  &off);
1887  if ((NULL == cname) ||
1888  (off != rd[0].data_size))
1889  {
1890  GNUNET_break_op (0);
1891  GNUNET_free_non_null (cname);
1892  fail_resolution (rh);
1893  return;
1894  }
1896  cname);
1897  GNUNET_free (cname);
1898  return;
1899  }
1900  /* If A/AAAA was requested, but we got a VPN
1901  record, we convert it to A/AAAA using GNUnet VPN */
1902  if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
1904  {
1905  for (unsigned int i = 0; i < rd_count; i++)
1906  {
1907  switch (rd[i].record_type)
1908  {
1910  {
1911  af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET :
1912  AF_INET6;
1913  if (sizeof(struct GNUNET_TUN_GnsVpnRecord) >
1914  rd[i].data_size)
1915  {
1916  GNUNET_break_op (0);
1917  fail_resolution (rh);
1918  return;
1919  }
1920  vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
1921  vname = (const char *) &vpn[1];
1922  if ('\0' != vname[rd[i].data_size - 1 - sizeof(struct
1924  ])
1925  {
1926  GNUNET_break_op (0);
1927  fail_resolution (rh);
1928  return;
1929  }
1931  &vhash);
1933  "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n",
1934  GNUNET_i2s (&vpn->peer),
1935  vname,
1936  (int) af,
1937  (int) ntohs (vpn->proto));
1938  vpn_ctx = GNUNET_new (struct VpnContext);
1939  rh->vpn_ctx = vpn_ctx;
1940  vpn_ctx->rh = rh;
1941  vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
1942  rd);
1943  if (vpn_ctx->rd_data_size < 0)
1944  {
1945  GNUNET_break_op (0);
1946  GNUNET_free (vpn_ctx);
1947  fail_resolution (rh);
1948  return;
1949  }
1950  vpn_ctx->rd_data = GNUNET_malloc ((size_t) vpn_ctx->rd_data_size);
1951  vpn_ctx->rd_count = rd_count;
1952  GNUNET_assert (vpn_ctx->rd_data_size ==
1954  rd,
1955  (size_t) vpn_ctx
1956  ->rd_data_size,
1957  vpn_ctx->rd_data));
1958  vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
1959  af,
1960  ntohs (
1961  vpn->proto),
1962  &vpn->peer,
1963  &vhash,
1965  VPN_TIMEOUT),
1966  &
1968  vpn_ctx);
1969  return;
1970  }
1971 
1973  {
1974  /* delegation to DNS */
1976  "Found GNS2DNS record, delegating to DNS!\n");
1977  if (GNUNET_OK ==
1979  rd_count,
1980  rd))
1981  return;
1982  else
1983  goto fail;
1984  }
1985 
1986  default:
1987  break;
1988  } /* end: switch */
1989  } /* end: for rd */
1990  } /* end: name_resolution_pos */
1991  /* convert relative names in record values to absolute names,
1992  using 'scratch' array for memory allocations */
1993  scratch_off = 0;
1994  rd_off = 0;
1995  for (unsigned int i = 0; i < rd_count; i++)
1996  {
1997  GNUNET_assert (rd_off <= i);
1998  if ((0 != rh->protocol) &&
1999  (0 != rh->service) &&
2001  continue; /* we _only_ care about boxed records */
2002 
2003  GNUNET_assert (rd_off < rd_count);
2004  rd_new[rd_off] = rd[i];
2005  /* Check if the embedded name(s) end in "+", and if so,
2006  replace the "+" with the zone at "ac_tail", changing the name
2007  to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2008  so we can free it afterwards. */
2009  switch (rd[i].record_type)
2010  {
2012  {
2013  char *cname;
2014 
2015  off = 0;
2016  cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
2017  rd[i].data_size,
2018  &off);
2019  if ((NULL == cname) ||
2020  (off != rd[i].data_size))
2021  {
2022  GNUNET_break_op (0); /* record not well-formed */
2023  }
2024  else
2025  {
2026  cname = translate_dot_plus (rh, cname);
2027  GNUNET_break (NULL != cname);
2028  scratch_start = scratch_off;
2029  if (GNUNET_OK !=
2031  sizeof(scratch),
2032  &scratch_off,
2033  cname))
2034  {
2035  GNUNET_break (0);
2036  }
2037  else
2038  {
2039  GNUNET_assert (rd_off < rd_count);
2040  rd_new[rd_off].data = &scratch[scratch_start];
2041  rd_new[rd_off].data_size = scratch_off - scratch_start;
2042  rd_off++;
2043  }
2044  }
2045  GNUNET_free_non_null (cname);
2046  }
2047  break;
2048 
2050  {
2051  struct GNUNET_DNSPARSER_SoaRecord *soa;
2052 
2053  off = 0;
2054  soa = GNUNET_DNSPARSER_parse_soa (rd[i].data,
2055  rd[i].data_size,
2056  &off);
2057  if ((NULL == soa) ||
2058  (off != rd[i].data_size))
2059  {
2060  GNUNET_break_op (0); /* record not well-formed */
2061  }
2062  else
2063  {
2064  soa->mname = translate_dot_plus (rh, soa->mname);
2065  soa->rname = translate_dot_plus (rh, soa->rname);
2066  scratch_start = scratch_off;
2067  if (GNUNET_OK !=
2069  sizeof(scratch),
2070  &scratch_off,
2071  soa))
2072  {
2073  GNUNET_break (0);
2074  }
2075  else
2076  {
2077  GNUNET_assert (rd_off < rd_count);
2078  rd_new[rd_off].data = &scratch[scratch_start];
2079  rd_new[rd_off].data_size = scratch_off - scratch_start;
2080  rd_off++;
2081  }
2082  }
2083  if (NULL != soa)
2085  }
2086  break;
2087 
2089  {
2090  struct GNUNET_DNSPARSER_MxRecord *mx;
2091 
2092  off = 0;
2093  mx = GNUNET_DNSPARSER_parse_mx (rd[i].data,
2094  rd[i].data_size,
2095  &off);
2096  if ((NULL == mx) ||
2097  (off != rd[i].data_size))
2098  {
2099  GNUNET_break_op (0); /* record not well-formed */
2100  }
2101  else
2102  {
2103  mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2104  scratch_start = scratch_off;
2105  if (GNUNET_OK !=
2107  sizeof(scratch),
2108  &scratch_off,
2109  mx))
2110  {
2111  GNUNET_break (0);
2112  }
2113  else
2114  {
2115  GNUNET_assert (rd_off < rd_count);
2116  rd_new[rd_off].data = &scratch[scratch_start];
2117  rd_new[rd_off].data_size = scratch_off - scratch_start;
2118  rd_off++;
2119  }
2120  }
2121  if (NULL != mx)
2123  }
2124  break;
2125 
2127  {
2128  struct GNUNET_DNSPARSER_SrvRecord *srv;
2129 
2130  off = 0;
2131  srv = GNUNET_DNSPARSER_parse_srv (rd[i].data,
2132  rd[i].data_size,
2133  &off);
2134  if ((NULL == srv) ||
2135  (off != rd[i].data_size))
2136  {
2137  GNUNET_break_op (0); /* record not well-formed */
2138  }
2139  else
2140  {
2141  srv->target = translate_dot_plus (rh, srv->target);
2142  scratch_start = scratch_off;
2143  if (GNUNET_OK !=
2145  sizeof(scratch),
2146  &scratch_off,
2147  srv))
2148  {
2149  GNUNET_break (0);
2150  }
2151  else
2152  {
2153  GNUNET_assert (rd_off < rd_count);
2154  rd_new[rd_off].data = &scratch[scratch_start];
2155  rd_new[rd_off].data_size = scratch_off - scratch_start;
2156  rd_off++;
2157  }
2158  }
2159  if (NULL != srv)
2161  }
2162  break;
2163 
2165  /* ignore */
2166  break;
2167 
2169  {
2170  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
2171 
2172  if (rd[i].data_size != sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))
2173  {
2174  GNUNET_break_op (0);
2175  break;
2176  }
2177  GNUNET_memcpy (&pub,
2178  rd[i].data,
2179  rd[i].data_size);
2180  rd_off++;
2182  {
2183  /* try to resolve "@" */
2184  struct AuthorityChain *ac;
2185 
2186  ac = GNUNET_new (struct AuthorityChain);
2187  ac->rh = rh;
2188  ac->gns_authority = GNUNET_YES;
2192  rh->ac_tail,
2193  ac);
2195  rh);
2196  return;
2197  }
2198  }
2199  break;
2200 
2202  {
2203  /* delegation to DNS */
2205  {
2206  rd_off++;
2207  break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2208  }
2210  "Found GNS2DNS record, delegating to DNS!\n");
2211  if (GNUNET_OK ==
2213  rd_count,
2214  rd))
2215  return;
2216  else
2217  goto fail;
2218  }
2219 
2221  {
2222  /* unbox SRV/TLSA records if a specific one was requested */
2223  if ((0 != rh->protocol) &&
2224  (0 != rh->service) &&
2225  (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2226  {
2227  const struct GNUNET_GNSRECORD_BoxRecord *box;
2228 
2229  box = rd[i].data;
2230  if ((ntohs (box->protocol) == rh->protocol) &&
2231  (ntohs (box->service) == rh->service))
2232  {
2233  /* Box matches, unbox! */
2234  GNUNET_assert (rd_off < rd_count);
2235  rd_new[rd_off].record_type = ntohl (box->record_type);
2236  rd_new[rd_off].data_size -= sizeof(struct
2238  rd_new[rd_off].data = &box[1];
2239  rd_off++;
2240  }
2241  }
2242  else
2243  {
2244  /* no specific protocol/service specified, preserve all BOX
2245  records (for modern, GNS-enabled applications) */
2246  rd_off++;
2247  }
2248  break;
2249  }
2250 
2251  default:
2252  rd_off++;
2253  break;
2254  } /* end: switch */
2255  } /* end: for rd_count */
2256 
2257  /* yes, we are done, return result */
2259  "Returning GNS response for `%s' with %u answers\n",
2260  rh->ac_tail->label,
2261  rd_off);
2262  rh->proc (rh->proc_cls,
2263  rd_off,
2264  rd_new);
2266  rh);
2267  return;
2268  }
2269 
2270  switch (rd[0].record_type)
2271  {
2273  GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2275  &rd[0]);
2276  return;
2277 
2279  GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2281  &rd[0]);
2282  return;
2283 
2284  default:
2285  if (GNUNET_OK ==
2287  rd_count,
2288  rd))
2289  return;
2290  break;
2291  }
2292 fail:
2294  _ ("GNS lookup recursion failed (no delegation record found)\n"));
2295  fail_resolution (rh);
2296 }
2297 
2298 
2307 static void
2309  int32_t success,
2310  const char *emsg)
2311 {
2312  struct CacheOps *co = cls;
2313 
2314  co->namecache_qe_cache = NULL;
2315  if (GNUNET_OK != success)
2317  _ ("Failed to cache GNS resolution: %s\n"),
2318  emsg);
2319  GNUNET_CONTAINER_DLL_remove (co_head,
2320  co_tail,
2321  co);
2322  GNUNET_free (co);
2323 }
2324 
2325 
2343 static void
2345  struct GNUNET_TIME_Absolute exp,
2346  const struct GNUNET_HashCode *key,
2347  const struct GNUNET_PeerIdentity *get_path,
2348  unsigned int get_path_length,
2349  const struct GNUNET_PeerIdentity *put_path,
2350  unsigned int put_path_length,
2351  enum GNUNET_BLOCK_Type type,
2352  size_t size,
2353  const void *data)
2354 {
2355  struct GNS_ResolverHandle *rh = cls;
2356  struct AuthorityChain *ac = rh->ac_tail;
2357  const struct GNUNET_GNSRECORD_Block *block;
2358  struct CacheOps *co;
2359 
2360  (void) exp;
2361  (void) key;
2362  (void) get_path;
2363  (void) get_path_length;
2364  (void) put_path;
2365  (void) put_path_length;
2366  (void) type;
2368  rh->get_handle = NULL;
2370  rh->dht_heap_node = NULL;
2372  "Handling response from the DHT\n");
2373  if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2374  {
2375  /* how did this pass DHT block validation!? */
2376  GNUNET_break (0);
2377  fail_resolution (rh);
2378  return;
2379  }
2380  block = data;
2381  if (size !=
2382  ntohl (block->purpose.size)
2383  + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)
2384  + sizeof(struct GNUNET_CRYPTO_EcdsaSignature))
2385  {
2386  /* how did this pass DHT block validation!? */
2387  GNUNET_break (0);
2388  fail_resolution (rh);
2389  return;
2390  }
2392  "Decrypting DHT block of size %u for `%s', expires %s\n",
2393  ntohl (block->purpose.size),
2394  rh->name,
2396  if (GNUNET_OK !=
2399  ac->label,
2401  rh))
2402  {
2403  GNUNET_break_op (0); /* block was ill-formed */
2404  fail_resolution (rh);
2405  return;
2406  }
2408  block->expiration_time)).
2409  rel_value_us)
2410  {
2412  "Received expired block from the DHT, will not cache it.\n");
2413  return;
2414  }
2415  if (GNUNET_YES == disable_cache)
2416  return;
2417  /* Cache well-formed blocks */
2419  "Caching response from the DHT in namecache\n");
2420  co = GNUNET_new (struct CacheOps);
2421  co->namecache_qe_cache = GNUNET_NAMECACHE_block_cache (namecache_handle,
2422  block,
2423  &
2425  co);
2426  GNUNET_CONTAINER_DLL_insert (co_head,
2427  co_tail,
2428  co);
2429 }
2430 
2431 
2438 static void
2440  const struct GNUNET_HashCode *query)
2441 {
2442  struct GNS_ResolverHandle *rx;
2443 
2444  GNUNET_assert (NULL == rh->get_handle);
2445  rh->get_handle = GNUNET_DHT_get_start (dht_handle,
2447  query,
2450  NULL, 0,
2451  &handle_dht_response, rh);
2452  rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
2453  rh,
2455  abs_value_us);
2456  if (GNUNET_CONTAINER_heap_get_size (dht_lookup_heap) >
2458  {
2459  /* fail longest-standing DHT request */
2460  rx = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
2461  rx->dht_heap_node = NULL;
2462  GNUNET_assert (NULL != rx);
2463  fail_resolution (rx);
2464  }
2465 }
2466 
2467 
2476 static void
2478  unsigned int rd_count,
2479  const struct GNUNET_GNSRECORD_Data *rd)
2480 {
2481  struct GNS_ResolverHandle *rh = cls;
2482 
2483  if (0 == rd_count)
2485  _ ("GNS namecache returned empty result for `%s'\n"),
2486  rh->name);
2488  rd_count,
2489  rd);
2490 }
2491 
2492 
2499 static void
2501  const struct GNUNET_GNSRECORD_Block *block)
2502 {
2503  struct GNS_ResolverHandle *rh = cls;
2504  struct AuthorityChain *ac = rh->ac_tail;
2505  const char *label = ac->label;
2506  const struct GNUNET_CRYPTO_EcdsaPublicKey *auth =
2508  struct GNUNET_HashCode query;
2509 
2510  GNUNET_assert (NULL != rh->namecache_qe);
2511  rh->namecache_qe = NULL;
2512  if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2513  ((GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2514  (ac != rh->ac_head))) &&
2515  ((NULL == block) ||
2517  block->expiration_time)).
2518  rel_value_us)))
2519  {
2520  /* namecache knows nothing; try DHT lookup */
2522  label,
2523  &query);
2525  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2526  ac->label,
2528  GNUNET_h2s (&query));
2529  start_dht_request (rh, &query);
2530  return;
2531  }
2532 
2533  if ((NULL == block) ||
2535  block->expiration_time)).
2536  rel_value_us))
2537  {
2538  /* DHT not permitted and no local result, fail */
2540  "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2541  ac->label,
2543  fail_resolution (rh);
2544  return;
2545  }
2547  "Received result from namecache for label `%s'\n",
2548  ac->label);
2549 
2550  if (GNUNET_OK !=
2552  auth,
2553  label,
2555  rh))
2556  {
2557  GNUNET_break_op (0); /* block was ill-formed */
2558  /* try DHT instead */
2560  label,
2561  &query);
2563  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2564  ac->label,
2566  GNUNET_h2s (&query));
2567  start_dht_request (rh, &query);
2568  return;
2569  }
2570 }
2571 
2572 
2578 static void
2580 {
2581  struct AuthorityChain *ac = rh->ac_tail;
2582  struct GNUNET_HashCode query;
2583 
2585  "Starting GNS resolution for `%s' in zone %s\n",
2586  ac->label,
2589  ac->label,
2590  &query);
2591  if (GNUNET_YES != disable_cache)
2592  {
2593  rh->namecache_qe
2594  = GNUNET_NAMECACHE_lookup_block (namecache_handle,
2595  &query,
2597  rh);
2598  GNUNET_assert (NULL != rh->namecache_qe);
2599  }
2600  else
2601  {
2602  start_dht_request (rh,
2603  &query);
2604  }
2605 }
2606 
2607 
2614 static void
2616  int is_valid)
2617 {
2618  struct GNS_ResolverHandle *rh = cls;
2619  struct AuthorityChain *ac = rh->ac_tail;
2620 
2621  rh->rev_check = NULL;
2622  if (GNUNET_YES != is_valid)
2623  {
2625  _ ("Zone %s was revoked, resolution fails\n"),
2627  fail_resolution (rh);
2628  return;
2629  }
2631 }
2632 
2633 
2639 static void
2641 {
2642  struct AuthorityChain *ac = rh->ac_tail;
2643 
2645  "Starting revocation check for zone %s\n",
2650  rh);
2651  GNUNET_assert (NULL != rh->rev_check);
2652 }
2653 
2654 
2660 static void
2662 {
2663  struct GNS_ResolverHandle *rh = cls;
2664 
2665  rh->task_id = NULL;
2666  if (MAX_RECURSION < rh->loop_limiter++)
2667  {
2669  "Encountered unbounded recursion resolving `%s'\n",
2670  rh->name);
2671  fail_resolution (rh);
2672  return;
2673  }
2674  if (GNUNET_YES == rh->ac_tail->gns_authority)
2676  else
2678 }
2679 
2680 
2687 static void
2689 {
2690  struct GNS_ResolverHandle *rh = cls;
2691  struct AuthorityChain *ac;
2692  struct in_addr v4;
2693  struct in6_addr v6;
2694 
2695  rh->task_id = NULL;
2696  if (1 == inet_pton (AF_INET,
2697  rh->name,
2698  &v4))
2699  {
2700  /* name is IPv4 address, pretend it's an A record */
2701  struct GNUNET_GNSRECORD_Data rd;
2702 
2703  rd.data = &v4;
2704  rd.data_size = sizeof(v4);
2705  rd.expiration_time = UINT64_MAX;
2707  rd.flags = 0;
2708  rh->proc (rh->proc_cls,
2709  1,
2710  &rd);
2711  GNUNET_assert (NULL == rh->task_id);
2713  rh);
2714  return;
2715  }
2716  if (1 == inet_pton (AF_INET6,
2717  rh->name,
2718  &v6))
2719  {
2720  /* name is IPv6 address, pretend it's an AAAA record */
2721  struct GNUNET_GNSRECORD_Data rd;
2722 
2723  rd.data = &v6;
2724  rd.data_size = sizeof(v6);
2725  rd.expiration_time = UINT64_MAX;
2727  rd.flags = 0;
2728  rh->proc (rh->proc_cls,
2729  1,
2730  &rd);
2731  GNUNET_assert (NULL == rh->task_id);
2733  rh);
2734  return;
2735  }
2736 
2737  ac = GNUNET_new (struct AuthorityChain);
2738  ac->rh = rh;
2740  if (NULL == ac->label)
2741  /* name was just the "TLD", so we default to label
2742  #GNUNET_GNS_EMPTY_LABEL_AT */
2744  ac->gns_authority = GNUNET_YES;
2747  rh->ac_tail,
2748  ac);
2750  rh);
2751 }
2752 
2753 
2766 struct GNS_ResolverHandle *
2768  uint32_t record_type,
2769  const char *name,
2772  void *proc_cls)
2773 {
2774  struct GNS_ResolverHandle *rh;
2775 
2777  "Starting lookup for `%s'\n",
2778  name);
2779  rh = GNUNET_new (struct GNS_ResolverHandle);
2780  GNUNET_CONTAINER_DLL_insert (rlh_head,
2781  rlh_tail,
2782  rh);
2783  rh->authority_zone = *zone;
2784  rh->proc = proc;
2785  rh->proc_cls = proc_cls;
2786  rh->options = options;
2787  rh->record_type = record_type;
2788  rh->name = GNUNET_strdup (name);
2789  rh->name_resolution_pos = strlen (name);
2791  rh);
2792  return rh;
2793 }
2794 
2795 
2801 void
2803 {
2804  struct DnsResult *dr;
2805  struct AuthorityChain *ac;
2806  struct VpnContext *vpn_ctx;
2807 
2808  GNUNET_CONTAINER_DLL_remove (rlh_head,
2809  rlh_tail,
2810  rh);
2811  if (NULL != rh->dns_request)
2812  {
2814  rh->dns_request = NULL;
2815  }
2816  while (NULL != (ac = rh->ac_head))
2817  {
2819  rh->ac_tail,
2820  ac);
2821  if (GNUNET_NO == ac->gns_authority)
2822  {
2823  struct Gns2DnsPending *gp;
2824 
2825  while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2826  {
2828  ac->authority_info.dns_authority.gp_tail,
2829  gp);
2830  if (NULL != gp->rh)
2831  {
2832  /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2833  using GNS_resolver_lookup_cancel here, we need to
2834  add it first... */
2835  GNUNET_CONTAINER_DLL_insert (rlh_head,
2836  rlh_tail,
2837  gp->rh);
2838  GNUNET_assert (NULL == gp->rh->task_id);
2841  gp->rh);
2842  gp->rh = NULL;
2843  }
2844  if (NULL != gp->dns_rh)
2845  {
2847  gp->dns_rh = NULL;
2848  }
2849  GNUNET_free (gp);
2850  }
2852  }
2853  GNUNET_free (ac->label);
2854  GNUNET_free (ac);
2855  }
2856  if (NULL != rh->task_id)
2857  {
2859  rh->task_id = NULL;
2860  }
2861  if (NULL != rh->get_handle)
2862  {
2864  rh->get_handle = NULL;
2865  }
2866  if (NULL != rh->dht_heap_node)
2867  {
2869  rh->dht_heap_node = NULL;
2870  }
2871  if (NULL != (vpn_ctx = rh->vpn_ctx))
2872  {
2874  GNUNET_free (vpn_ctx->rd_data);
2875  GNUNET_free (vpn_ctx);
2876  }
2877  if (NULL != rh->namecache_qe)
2878  {
2880  rh->namecache_qe = NULL;
2881  }
2882  if (NULL != rh->rev_check)
2883  {
2885  rh->rev_check = NULL;
2886  }
2887  if (NULL != rh->std_resolve)
2888  {
2890  "Canceling standard DNS resolution\n");
2892  rh->std_resolve = NULL;
2893  }
2894  while (NULL != (dr = rh->dns_result_head))
2895  {
2897  rh->dns_result_tail,
2898  dr);
2899  GNUNET_free (dr);
2900  }
2901  GNUNET_free_non_null (rh->leho);
2902  GNUNET_free (rh->name);
2903  GNUNET_free (rh);
2904 }
2905 
2906 
2907 /* ***************** Resolver initialization ********************* */
2908 
2909 
2918 void
2920  struct GNUNET_DHT_Handle *dht,
2921  const struct GNUNET_CONFIGURATION_Handle *c,
2922  unsigned long long max_bg_queries)
2923 {
2924  cfg = c;
2925  namecache_handle = nc;
2926  dht_handle = dht;
2927  dht_lookup_heap =
2929  max_allowed_background_queries = max_bg_queries;
2931  "namecache",
2932  "DISABLE");
2933  if (GNUNET_YES == disable_cache)
2935  "Namecache disabled\n");
2936  vpn_handle = GNUNET_VPN_connect (cfg);
2937 }
2938 
2939 
2943 void
2945 {
2946  struct GNS_ResolverHandle *rh;
2947  struct CacheOps *co;
2948 
2949  /* abort active resolutions */
2950  while (NULL != (rh = rlh_head))
2951  {
2952  rh->proc (rh->proc_cls,
2953  0,
2954  NULL);
2956  }
2957  while (NULL != (co = co_head))
2958  {
2959  GNUNET_CONTAINER_DLL_remove (co_head,
2960  co_tail,
2961  co);
2963  GNUNET_free (co);
2964  }
2965  GNUNET_CONTAINER_heap_destroy (dht_lookup_heap);
2966  dht_lookup_heap = NULL;
2967  GNUNET_VPN_disconnect (vpn_handle);
2968  vpn_handle = NULL;
2969  dht_handle = NULL;
2970  namecache_handle = NULL;
2971 }
2972 
2973 
2974 /* end of gnunet-service-gns_resolver.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void GNUNET_DNSPARSER_free_soa(struct GNUNET_DNSPARSER_SoaRecord *soa)
Free SOA information record.
Definition: dnsparser.c:108
struct GNUNET_DNSPARSER_Record * answers
Array of all answers in the packet, must contain "num_answers" entries.
static struct GNUNET_VPN_Handle * vpn_handle
Our handle to the vpn service.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
Information from SOA records (RFC 1035).
For the rightmost label, only look in the cache (it is our local namestore), for the others...
static struct GNUNET_NAMECACHE_Handle * namecache_handle
Our handle to the namecache service.
struct GNUNET_TIME_AbsoluteNBO expiration_time
Expiration time of the block.
Payload of GNS VPN record.
unsigned int num_results
How many results did we get?
GNUNET_NETWORK_STRUCT_END ssize_t GNUNET_GNSRECORD_records_get_size(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Calculate how many bytes we will need to serialize the given records.
#define memrchr(s, c, n)
Definition: compat.h:49
struct GNS_ResolverHandle * rh
Handle for the resolution of the IP part of the GNS2DNS record.
void GNUNET_REVOCATION_query_cancel(struct GNUNET_REVOCATION_Query *q)
Cancel key revocation check.
static struct GNUNET_CONTAINER_Heap * dht_lookup_heap
Heap for limiting parallel DHT lookups.
void GNS_resolver_lookup_cancel(struct GNS_ResolverHandle *rh)
Cancel active resolution (i.e.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
uint16_t service
Service of the boxed record (aka port number), in NBO.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
#define GNUNET_TIME_UNIT_HOURS
One hour.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:673
static void vpn_allocation_cb(void *cls, int af, const void *address)
Callback invoked from the VPN service once a redirection is available.
Record type used to box up SRV and TLSA records.
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:334
struct Gns2DnsPending * gp_tail
Tail of list of resolutions of the &#39;ip&#39; of the name server that are still pending.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
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.
char * mname
The domainname of the name server that was the original or primary source of data for this zone...
static void recursive_resolution(void *cls)
Task scheduled to continue with the resolution process.
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.
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
size_t data_size
Number of bytes in data.
void GNUNET_DNSPARSER_free_srv(struct GNUNET_DNSPARSER_SrvRecord *srv)
Free SRV information record.
Definition: dnsparser.c:139
GNUNET_BLOCK_Type
Blocks in the datastore and the datacache must have a unique type.
static void recursive_gns_resolution_revocation(struct GNS_ResolverHandle *rh)
Perform revocation check on tail of our authority chain.
#define GNUNET_DNSPARSER_TYPE_CNAME
#define DHT_GNS_REPLICATION_LEVEL
DHT replication level.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe_cache
Pending Namestore caching task.
struct GNUNET_DHT_GetHandle * get_handle
Handle for DHT lookups.
static void handle_namecache_block_response(void *cls, const struct GNUNET_GNSRECORD_Block *block)
Process a record that was stored in the namecache.
char * mxhost
Name of the mail server.
struct GNUNET_DNSPARSER_SrvRecord * srv
SRV data for SRV records.
ssize_t GNUNET_GNSRECORD_records_serialize(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, size_t dest_size, char *dest)
Serialize the given records to the given destination buffer.
static void handle_dns_result(void *cls, const struct sockaddr *addr, socklen_t addrlen)
We had to do a DNS lookup.
static void GNS_resolver_lookup_cancel_(void *cls)
Wrapper around GNS_resolver_lookup_cancel() as a task.
const char * GNS_get_tld(const char *name)
Obtain the TLD of the given name.
struct GNS_ResolverHandle * next
DLL.
static void timeout_resolution(void *cls)
Function called when a resolution times out.
uint64_t expiration_time
Expiration time for the DNS record, 0 if we didn&#39;t get anything useful (i.e.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition: dnsstub.c:690
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:1257
char * label
label/name corresponding to the authority
#define GNUNET_GNSRECORD_TYPE_ANY
Record type indicating any record/&#39;*&#39;.
static unsigned long long max_allowed_background_queries
Maximum amount of parallel queries to the DHT.
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
Convert an absolute domain name to the respective public key.
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:591
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:1118
uint16_t id
DNS ID (to match replies to requests).
struct AuthorityChain * prev
This is a DLL.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GNS_LocalOptions
Options for the GNS lookup.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
GNS_ResultProcessor proc
called when resolution phase finishes
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:854
struct GNUNET_VPN_RedirectionRequest * vpn_request
Handle to the VPN request that we were performing.
#define VPN_TIMEOUT
Default timeout for VPN redirections.
#define GNUNET_NO
Definition: gnunet_common.h:78
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:391
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:939
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
size_t data_size
Number of bytes in data.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
char * name
The name to resolve.
int gns_authority
GNUNET_YES if the authority was a GNS authority, GNUNET_NO if the authority was a DNS authority...
int GNUNET_GNSRECORD_records_deserialize(size_t len, const char *src, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest)
Deserialize the given records to the given destination.
Information we have in an encrypted block with record data (i.e.
struct GNUNET_DNSPARSER_Record * additional_records
Array of all additional answers in the packet, must contain "num_additional_records" entries...
#define GNUNET_GNSRECORD_TYPE_BOX
Record type for a boxed record (see TLSA/SRV handling in GNS).
static const struct GNUNET_CONFIGURATION_Handle * cfg
Global configuration.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_DNSPARSER_TYPE_MX
Information from MX records (RFC 1035).
#define GNUNET_GNSRECORD_TYPE_NICK
Record type for GNS nick names ("NICK").
static int disable_cache
Use namecache.
unsigned int num_answers
Number of answers in the packet, should be 0 for queries.
uint64_t abs_value_us
The actual value.
uint16_t id
Unique identifier for the request/response.
IPC messages between GNS API and GNS service.
struct AuthorityChain * ac_head
DLL to store the authority chain.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
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. ...
Handle to a currenty pending resolution.
void * proc_cls
closure passed to proc
Connection to the DHT service.
Definition: dht_api.c:201
uint32_t record_type
Type of the GNS/DNS record.
#define GNUNET_GNSRECORD_TYPE_VPN
Record type for VPN resolution.
static void start_resolver_lookup(void *cls)
Begin the resolution process from &#39;name&#39;, starting with the identification of the zone specified by &#39;...
Opaque VPN handle.
Definition: vpn_api.c:34
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
Active namestore caching operations.
#define GNUNET_DNSPARSER_TYPE_PTR
const void * data
Binary value stored in the DNS record (appended to this struct)
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
static char * zone
Name of the zone we manage.
int found
Did we succeed in getting an IP address for any of the DNS servers listed? Once we do...
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
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:1253
#define GNUNET_DNSPARSER_MAX_NAME_LENGTH
Maximum length of a name in DNS.
#define GNUNET_DNSPARSER_TYPE_SOA
int service
For SRV and TLSA records, the number of the service specified in the name.
char * name
Name of the record that the query is for (0-terminated).
char * hostname
For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
const void * data
Binary value stored in the DNS record.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
struct GNUNET_DNSPARSER_SoaRecord * soa
SOA data for SOA records.
unsigned int num_additional_records
Number of additional records in the packet, should be 0 for queries.
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 ...
struct GNUNET_RESOLVER_RequestHandle * std_resolve
Handle for standard DNS resolution, NULL if none is active.
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:656
#define GNUNET_GNSRECORD_TYPE_PKEY
Record type for GNS zone transfer ("PKEY").
struct AuthorityChain * ac_tail
DLL to store the authority chain.
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.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition: dnsstub.c:564
static void recursive_gns_resolution_namecache(struct GNS_ResolverHandle *rh)
Lookup tail of our authority chain in the namecache.
char * target
Hostname offering the service.
uint64_t expiration_time
Expiration time for the DNS record.
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:1280
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Record type for delegation to DNS.
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 ...
char * rname
A domainname which specifies the mailbox of the person responsible for this zone. ...
static struct GNUNET_NAMESTORE_Handle * ns
Handle to the namestore.
Definition: gnunet-abd.c:41
int record_type
Desired type for the resolution.
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:477
void GNUNET_VPN_disconnect(struct GNUNET_VPN_Handle *vh)
Disconnect from the VPN service.
Definition: vpn_api.c:534
Randomness for IVs etc.
int protocol
For SRV and TLSA records, the number of the protocol specified in the name.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe
Pending Namecache lookup task.
an ECC signature using ECDSA
static char buf[2048]
static struct GNUNET_DHT_Handle * dht_handle
Resolver handle to the dht.
union GNUNET_DNSPARSER_Record::@24 data
Payload of the record (which one of these is valid depends on the &#39;type&#39;).
unsigned int recursion_desired
Set to 1 if recursion is desired (client -> server)
void GNS_resolver_done()
Shutdown resolver.
struct GNS_ResolverHandle * rh
Resolver handle this entry in the chain belongs to.
void GNUNET_NAMECACHE_cancel(struct GNUNET_NAMECACHE_QueueEntry *qe)
Cancel a namecache operation.
void GNUNET_TUN_service_name_to_hash(const char *service_name, struct GNUNET_HashCode *hc)
Hash the service name of a hosted service to the hash code that is used to identify the service on th...
Definition: regex.c:814
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
DLL to hold the authority chain we had to pass in the resolution process.
GNU Name System (main service)
Handle to a node in a heap.
unsigned int opcode
See GNUNET_TUN_DNS_OPCODE_ defines.
struct AuthorityChain * ac
Context this activity belongs with.
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:1077
uint16_t protocol
Protocol of the boxed record (6 = TCP, 17 = UDP, etc.).
struct GNUNET_SCHEDULER_Task * task_id
ID of a task associated with the resolution process.
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
A DNS response record.
Heap with the minimum cost at the root.
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.
Block for storing record data.
struct GNUNET_DNSPARSER_Record * authority_records
Array of all authority records in the packet, must contain "num_authority_records" entries...
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
A 512-bit hashcode.
Handle to the stub resolver.
Definition: dnsstub.c:123
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_CRYPTO_EcdsaPublicKey *z)
Convert a zone key to a string (for printing debug messages).
struct GNUNET_DNSPARSER_Query * queries
Array of all queries in the packet, must contain "num_queries" entries.
void GNUNET_DHT_get_stop(struct GNUNET_DHT_GetHandle *get_handle)
Stop async DHT-get.
Definition: dht_api.c:1155
static int res
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:436
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
void GNUNET_VPN_cancel_request(struct GNUNET_VPN_RedirectionRequest *rr)
Cancel redirection request with the service.
Definition: vpn_api.c:375
size_t name_resolution_pos
Current offset in &#39;name&#39; where we are resolving.
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 transmit_lookup_dns_result(struct GNS_ResolverHandle *rh)
Gives the cummulative result obtained to the callback and clean up the request.
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:504
A result we got from DNS.
Node in the heap.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
struct GNUNET_VPN_RedirectionRequest * GNUNET_VPN_redirect_to_peer(struct GNUNET_VPN_Handle *vh, int result_af, uint8_t protocol, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HashCode *serv, struct GNUNET_TIME_Absolute expiration_time, GNUNET_VPN_AllocationCallback cb, void *cb_cls)
Tell the VPN that a forwarding to a particular peer offering a particular service is requested...
Definition: vpn_api.c:410
#define DNS_LOOKUP_TIMEOUT
Default timeout for DNS lookups.
struct GNUNET_PeerIdentity peer
The peer to contact.
struct GNUNET_CONTAINER_HeapNode * dht_heap_node
Heap node associated with this lookup.
GNUnet GNS service.
static void handle_gns2dns_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
We&#39;ve resolved the IP address for the DNS resolver to use after encountering a GNS2DNS record...
uint16_t proto
The protocol to use.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static struct GNUNET_PEERINFO_NotifyContext * nc
Iterator context.
struct GNS_ResolverHandle * rh
Which resolution process are we processing.
static unsigned int size
Size of the "table".
Definition: peer.c:67
size_t data_len
Number of bytes in data.
int launched
Did we start the recursive resolution via DNS?
Element of a resolution process for looking up the responsible DNS server hostname in a GNS2DNS recur...
struct CacheOps * prev
Organized in a DLL.
void * data
Binary record data.
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:1001
struct VpnContext * vpn_ctx
Handle to a VPN request, NULL if none is active.
Handle to a request given to the resolver.
Definition: resolver_api.c:102
Opaque redirection request handle.
Definition: vpn_api.c:76
void(* GNS_ResultProcessor)(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Function called with results for a GNS resolution.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static void continue_with_gns2dns(struct AuthorityChain *ac)
We have resolved one or more of the nameservers for a GNS2DNS lookup.
unsigned int num_authority_records
Number of authoritative answers in the packet, should be 0 for queries.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
struct DnsResult * prev
Kept in DLL.
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, uint32_t record_type, const char *name, enum GNUNET_GNS_LocalOptions options, GNS_ResultProcessor proc, void *proc_cls)
Lookup of a record in a specific zone calls lookup result processor on result.
Handle for the key revocation query.
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.
struct GNUNET_CRYPTO_EcdsaPublicKey authority_zone
The top-level GNS authoritative zone to query.
uint32_t record_type
GNS record type of the boxed record.
#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&#39;r...
char * rd_data
Serialized records.
Handle to a GET request.
Definition: dht_api.c:79
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
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.
static char * translate_dot_plus(struct GNS_ResolverHandle *rh, char *name)
Expands a name ending in .
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.
struct GNUNET_DNSSTUB_RequestSocket * dns_request
Socket for a DNS request, NULL if none is active.
struct Gns2DnsPending * prev
Kept in a DLL.
struct GNUNET_TIME_Absolute expiration_time
When does the record expire?
#define GNUNET_GNSRECORD_TYPE_LEHO
Record type for GNS legacy hostnames ("LEHO").
static void fail_resolution(struct GNS_ResolverHandle *rh)
Function called to asynchronously fail a resolution.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
uint16_t original_dns_id
16 bit random ID we used in the dns_request.
static void handle_gns_cname_result(struct GNS_ResolverHandle *rh, const char *cname)
We encountered a CNAME record during our resolution.
struct GNUNET_VPN_Handle * GNUNET_VPN_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the VPN service.
Definition: vpn_api.c:512
The identity of the host (wraps the signing key of the peer).
struct GNUNET_DNSPARSER_MxRecord * mx
MX data for MX records.
struct GNUNET_RESOLVER_RequestHandle * dns_rh
Handle for DNS resolution of the DNS nameserver.
uint32_t record_type
Type of the GNS/DNS record.
#define GNUNET_DNSPARSER_TYPE_AAAA
configuration data
Definition: configuration.c:85
Closure for vpn_allocation_cb.
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition: dnsstub.c:540
#define GNUNET_DNSPARSER_TYPE_NS
const char * name
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.
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:1067
static struct GNUNET_CRYPTO_EddsaPublicKey pub
Definition: gnunet-scrypt.c:39
Easy-to-process, parsed version of a DNS packet.
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 dns_result_parser(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
Function called with the result of a DNS resolution.
int GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls)
Decrypt block.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
static void handle_gns_resolution_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process a records that were decrypted from a block.
Connection to the NAMECACHE service.
Definition: namecache_api.c:94
struct DnsResult * next
Kept in DLL.
static void handle_revocation_result(void *cls, int is_valid)
Function called with the result from a revocation check.
#define GNUNET_log(kind,...)
static struct GNS_ResolverHandle * rlh_head
Head of resolver lookup list.
Entry in list of pending tasks.
Definition: scheduler.c:134
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
static struct GNS_ResolverHandle * rlh_tail
Tail of resolver lookup list.
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EcdsaPublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.
static char * rp
Relying party.
char * name
Name of the record that the query is for (0-terminated).
#define GNUNET_TUN_DNS_OPCODE_QUERY
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:331
struct CacheOps * next
Organized in a DLL.
unsigned int num_queries
Number of queries in the packet.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct Gns2DnsPending * next
Kept in a DLL.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_REVOCATION_Query * rev_check
Pending revocation check.
An QueueEntry used to store information for a pending NAMECACHE record operation. ...
Definition: namecache_api.c:47
Defaults, look in cache, then in DHT.
struct DnsResult * dns_result_tail
DLL of results we got from DNS.
void GNUNET_GNSRECORD_query_from_public_key(const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
struct Gns2DnsPending * gp_head
List of resolutions of the &#39;ip&#39; of the name server that are still pending.
static struct CacheOps * co_tail
Organized in a DLL.
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
This flag is currently unused; former RF_PENDING flag.
union AuthorityChain::@19 authority_info
Information about the resolver authority for this label.
struct GNUNET_TUN_DnsFlags flags
Bitfield of DNS flags.
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:889
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:742
ssize_t rd_data_size
Number of bytes in rd_data.
UDP socket we are using for sending DNS requests to the Internet.
Definition: dnsstub.c:44
int 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".
static void recursive_dns_resolution(struct GNS_ResolverHandle *rh)
Perform recursive DNS resolution.
char * leho
Legacy Hostname to use if we encountered GNS2DNS record and thus can deduct the LEHO from that transi...
#define GNUNET_DNSPARSER_TYPE_SRV
uint32_t data
The data value.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
struct AuthorityChain * next
This is a DLL.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Number of bytes signed; also specifies the number of bytes of encrypted data that follow...
static struct GNUNET_DHT_Handle * dht
Handle to the DHT.
static char * address
GNS address for this phone.
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
void GNUNET_DNSPARSER_free_mx(struct GNUNET_DNSPARSER_MxRecord *mx)
Free MX information record.
Definition: dnsparser.c:154
#define GNUNET_DNSPARSER_TYPE_A
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
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:643
unsigned int loop_limiter
We increment the loop limiter for each step in a recursive resolution.
Each peer along the way should look at &#39;enc&#39; (otherwise only the k-peers closest to the key should lo...
struct AuthorityChain::@19::@20 dns_authority
static void handle_dht_response(void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *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. ...
#define GNUNET_malloc(size)
Wrapper around malloc.
struct DnsResult * dns_result_head
DLL of results we got from DNS.
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.
struct GNS_ResolverHandle * prev
DLL.
Information from SRV records (RFC 2782).
#define GNUNET_free(ptr)
Wrapper around free.
unsigned int rd_count
Number of records serialized in rd_data.
struct GNUNET_DNSSTUB_Context * dns_handle
Handle to perform DNS lookups with this authority (in GNS2DNS handling).
enum GNUNET_GNS_LocalOptions options
Use only cache.
static struct CacheOps * co_head
Organized in a DLL.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966