GNUnet  0.16.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 #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_dnsstub_lib.h"
43 #include "gnunet_dht_service.h"
44 #include "gnunet_gnsrecord_lib.h"
46 #include "gnunet_dns_service.h"
49 #include "gnunet_dnsparser_lib.h"
50 #include "gnunet_tun_lib.h"
51 #include "gnunet_gns_service.h"
52 #include "gns.h"
53 #include "gnunet-service-gns.h"
55 
56 
60 #define DHT_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
61  GNUNET_TIME_UNIT_SECONDS, 60)
62 
66 #define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
67  GNUNET_TIME_UNIT_SECONDS, 15)
68 
72 #define DHT_GNS_REPLICATION_LEVEL 10
73 
74 
79 struct AuthorityChain;
80 
81 
88 {
93 
98 
103 
110 
115 
119  unsigned int num_results;
120 };
121 
122 
127 struct GNS_ResolverHandle;
128 
129 
135 {
140 
145 
150 
154  char *label;
155 
161 
165  union
166  {
171 
172  struct
173  {
180 
186 
192 
197 
202  int found;
203 
207  int launched;
210 };
211 
212 
216 struct DnsResult
217 {
221  struct DnsResult *next;
222 
226  struct DnsResult *prev;
227 
231  const void *data;
232 
237  uint64_t expiration_time;
238 
242  size_t data_size;
243 
247  uint32_t record_type;
248 };
249 
250 
256 {
261 
266 
271 
276 
280  void *proc_cls;
281 
286 
287 
292 
297 
302 
307 
313 
318 
323 
328 
332  char *name;
333 
338  char *leho;
339 
344 
349 
354 
359 
364  int protocol;
365 
370  int service;
371 
376 
382  unsigned int loop_limiter;
383 
387  unsigned int loop_threshold;
388 
392  uint16_t original_dns_id;
393 };
394 
395 
399 struct CacheOps
400 {
404  struct CacheOps *next;
405 
409  struct CacheOps *prev;
410 
415 };
416 
417 
422 
427 
432 
436 static unsigned long long max_allowed_background_queries;
437 
442 
447 
451 static struct CacheOps *co_head;
452 
456 static struct CacheOps *co_tail;
457 
461 static int disable_cache;
462 
466 static const struct GNUNET_CONFIGURATION_Handle *cfg;
467 
468 
484 /* dead, but keep for now */ int
485 is_canonical (const char *name)
486 {
487  const char *pos;
488  const char *dot;
489 
490  if (NULL == strchr (name,
491  (unsigned char) '.'))
492  return GNUNET_YES;
493  if ('_' != name[0])
494  return GNUNET_NO;
495  pos = &name[1];
496  while (NULL != (dot = strchr (pos,
497  (unsigned char) '.')))
498  if ('_' != dot[1])
499  return GNUNET_NO;
500  else
501  pos = dot + 1;
502  return GNUNET_YES;
503 }
504 
505 
506 /* ************************** Resolution **************************** */
507 
515 static char *
517  char *name)
518 {
519  char *ret;
520  size_t s_len = strlen (name);
521 
522  if (0 != strcmp (&name[s_len - 2],
523  ".+"))
524  return name; /* did not end in ".+" */
527  "%.*s.%s",
528  (int) (s_len - 2),
529  name,
532  GNUNET_free (name);
533  return ret;
534 }
535 
536 
543 static void
545 {
546  struct GNS_ResolverHandle *rh = cls;
547 
548  rh->task_id = NULL;
550 }
551 
552 
558 static void
560 {
561  rh->proc (rh->proc_cls,
562  0,
563  NULL);
564  GNUNET_assert (NULL == rh->task_id);
566  rh);
567 }
568 
569 
575 static void
577 {
578  struct GNS_ResolverHandle *rh = cls;
579 
580  rh->task_id = NULL;
581  fail_resolution (rh);
582 }
583 
584 
602 static char *
604 {
605  const char *rp;
606  const char *dot;
607  size_t len;
608  char *ret;
609  char *srv_name;
610  char *proto_name;
611  struct protoent *pe;
612  struct servent *se;
613 
614  if (0 == rh->name_resolution_pos)
615  return NULL;
616  dot = memrchr (rh->name,
617  (int) '.',
618  rh->name_resolution_pos);
619  if (NULL == dot)
620  {
621  /* done, this was the last one */
622  len = rh->name_resolution_pos;
623  rp = rh->name;
624  rh->name_resolution_pos = 0;
625  }
626  else if (('_' == dot[1]) &&
627  ('_' == rh->name[0]) &&
628  (dot == memchr (rh->name, (int) '.', rh->name_resolution_pos)))
629  {
637  len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
638  }
639  else
640  {
641  /* advance by one label */
642  len = rh->name_resolution_pos - (dot - rh->name) - 1;
643  rp = dot + 1;
644  rh->name_resolution_pos = dot - rh->name;
645  }
646  rh->protocol = 0;
647  rh->service = 0;
648  ret = GNUNET_strndup (rp, len);
649  /* If we have labels starting with underscore with label on
650  * the right (SRV/DANE/BOX case), determine port/protocol;
651  * The format of `rh->name` must be "_PORT._PROTOCOL".
652  */
653  if (('_' == rh->name[0]) &&
654  (NULL != (dot = memrchr (rh->name,
655  (int) '.',
656  rh->name_resolution_pos))) &&
657  ('_' == dot[1]) &&
658  (NULL == memrchr (rh->name,
659  (int) '.',
660  dot - rh->name)))
661  {
662  srv_name = GNUNET_strndup (&rh->name[1],
663  (dot - rh->name) - 1);
664  proto_name = GNUNET_strndup (&dot[2],
665  rh->name_resolution_pos - (dot - rh->name)
666  - 2);
667  rh->name_resolution_pos = 0;
668  pe = getprotobyname (proto_name);
669  if (NULL == pe)
670  {
672  _ ("Protocol `%s' unknown, skipping labels.\n"),
673  proto_name);
674  GNUNET_free (proto_name);
675  GNUNET_free (srv_name);
676  return ret;
677  }
678  se = getservbyname (srv_name,
679  proto_name);
680  if (NULL == se)
681  {
683  _ (
684  "Service `%s' unknown for protocol `%s', trying as number.\n"),
685  srv_name,
686  proto_name);
687  if (1 != sscanf (srv_name, "%u", &rh->service))
688  {
690  _ ("Service `%s' not a port, skipping service labels.\n"),
691  srv_name);
692  GNUNET_free (proto_name);
693  GNUNET_free (srv_name);
694  return ret;
695  }
696  }
697  else
698  {
699  rh->service = ntohs (se->s_port);
700  }
701  rh->protocol = pe->p_proto;
702  GNUNET_free (proto_name);
703  GNUNET_free (srv_name);
704  }
705  return ret;
706 }
707 
708 
714 static void
716 {
717  struct DnsResult *pos;
718  unsigned int n;
719  unsigned int i;
720 
721  n = 0;
722  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
723  n++;
724  {
725  struct GNUNET_GNSRECORD_Data rd[n];
726 
727  i = 0;
728  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
729  {
730  rd[i].data = pos->data;
731  rd[i].data_size = pos->data_size;
732  rd[i].record_type = pos->record_type;
740  if (0 == pos->expiration_time)
741  {
743  rd[i].expiration_time = 0;
744  }
745  else
746  {
747  rd[i].expiration_time = pos->expiration_time;
748  }
749  i++;
750  }
751  GNUNET_assert (i == n);
753  "Transmitting standard DNS result with %u records\n",
754  n);
755  rh->proc (rh->proc_cls,
756  n,
757  rd);
758  }
760 }
761 
762 
772 static void
774  uint64_t expiration_time,
775  uint32_t record_type,
776  size_t data_size,
777  const void *data)
778 {
779  struct DnsResult *res;
780 
781  res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
782  res->expiration_time = expiration_time;
783  res->data_size = data_size;
784  res->record_type = record_type;
785  res->data = &res[1];
786  GNUNET_memcpy (&res[1],
787  data,
788  data_size);
790  rh->dns_result_tail,
791  res);
792 }
793 
794 
803 static void
804 handle_dns_result (void *cls,
805  const struct sockaddr *addr,
806  socklen_t addrlen)
807 {
808  struct GNS_ResolverHandle *rh = cls;
809  const struct sockaddr_in *sa4;
810  const struct sockaddr_in6 *sa6;
811 
812  if (NULL == addr)
813  {
814  rh->std_resolve = NULL;
816  return;
817  }
819  "Received %u bytes of DNS IP data\n",
820  addrlen);
821  switch (addr->sa_family)
822  {
823  case AF_INET:
824  sa4 = (const struct sockaddr_in *) addr;
825  add_dns_result (rh,
826  0 /* expiration time is unknown */,
828  sizeof(struct in_addr),
829  &sa4->sin_addr);
830  break;
831 
832  case AF_INET6:
833  sa6 = (const struct sockaddr_in6 *) addr;
834  add_dns_result (rh,
835  0 /* expiration time is unknown */,
837  sizeof(struct in6_addr),
838  &sa6->sin6_addr);
839  break;
840 
841  default:
842  GNUNET_break (0);
843  break;
844  }
845 }
846 
847 
854 static void
855 recursive_resolution (void *cls);
856 
857 
864 static void
865 start_resolver_lookup (void *cls);
866 
867 
876 static void
877 dns_result_parser (void *cls,
878  const struct GNUNET_TUN_DnsHeader *dns,
879  size_t dns_len)
880 {
881  struct GNS_ResolverHandle *rh = cls;
882  struct GNUNET_DNSPARSER_Packet *p;
883  const struct GNUNET_DNSPARSER_Record *rec;
884  unsigned int rd_count;
885 
886  if (NULL == dns)
887  {
888  rh->dns_request = NULL;
890  rh->task_id = NULL;
891  fail_resolution (rh);
892  return;
893  }
894  if (rh->original_dns_id != dns->id)
895  {
896  /* DNS answer, but for another query */
897  return;
898  }
899  p = GNUNET_DNSPARSER_parse ((const char *) dns,
900  dns_len);
901  if (NULL == p)
902  {
904  _ ("Failed to parse DNS response\n"));
905  return;
906  }
907 
908  /* We got a result from DNS */
910  "Received DNS response for `%s' with %u answers\n",
911  rh->ac_tail->label,
912  (unsigned int) p->num_answers);
913  if ((p->num_answers > 0) &&
914  (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
916  {
917  int af;
918 
920  "Got CNAME `%s' from DNS for `%s'\n",
921  p->answers[0].data.hostname,
922  rh->name);
923  if (NULL != rh->std_resolve)
924  {
926  "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
927  rh->name);
929  }
930  GNUNET_free (rh->name);
931  rh->name = GNUNET_strdup (p->answers[0].data.hostname);
932  rh->name_resolution_pos = strlen (rh->name);
933  switch (rh->record_type)
934  {
936  af = AF_INET;
937  break;
938 
940  af = AF_INET6;
941  break;
942 
943  default:
944  af = AF_UNSPEC;
945  break;
946  }
947  if (NULL != rh->leho)
948  add_dns_result (rh,
949  GNUNET_TIME_UNIT_HOURS.rel_value_us,
951  strlen (rh->leho),
952  rh->leho);
954  af,
957  rh);
960  rh->dns_request = NULL;
961  return;
962  }
963 
964  /* convert from (parsed) DNS to (binary) GNS format! */
965  rd_count = p->num_answers + p->num_authority_records
966  + p->num_additional_records;
967  {
968  struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
969  int skip;
970  char buf[UINT16_MAX];
971  size_t buf_off;
972  size_t buf_start;
973 
974  buf_off = 0;
975  skip = 0;
976  memset (rd,
977  0,
978  sizeof(rd));
979  for (unsigned int i = 0; i < rd_count; i++)
980  {
981  if (i < p->num_answers)
982  rec = &p->answers[i];
983  else if (i < p->num_answers + p->num_authority_records)
984  rec = &p->authority_records[i - p->num_answers];
985  else
986  rec = &p->additional_records[i - p->num_answers
987  - p->num_authority_records];
988  /* As we copied the full DNS name to 'rh->ac_tail->label', this
989  should be the correct check to see if this record is actually
990  a record for our label... */
991  if (0 != strcmp (rec->name,
992  rh->ac_tail->label))
993  {
995  "Dropping record `%s', does not match desired name `%s'\n",
996  rec->name,
997  rh->ac_tail->label);
998  skip++;
999  continue;
1000  }
1001  rd[i - skip].record_type = rec->type;
1002  rd[i - skip].expiration_time = rec->expiration_time.abs_value_us;
1003  switch (rec->type)
1004  {
1006  if (rec->data.raw.data_len != sizeof(struct in_addr))
1007  {
1008  GNUNET_break_op (0);
1009  skip++;
1010  continue;
1011  }
1012  rd[i - skip].data_size = rec->data.raw.data_len;
1013  rd[i - skip].data = rec->data.raw.data;
1014  break;
1015 
1017  if (rec->data.raw.data_len != sizeof(struct in6_addr))
1018  {
1019  GNUNET_break_op (0);
1020  skip++;
1021  continue;
1022  }
1023  rd[i - skip].data_size = rec->data.raw.data_len;
1024  rd[i - skip].data = rec->data.raw.data;
1025  break;
1026 
1030  buf_start = buf_off;
1031  if (GNUNET_OK !=
1033  sizeof(buf),
1034  &buf_off,
1035  rec->data.hostname))
1036  {
1037  GNUNET_break (0);
1038  skip++;
1039  continue;
1040  }
1041  rd[i - skip].data_size = buf_off - buf_start;
1042  rd[i - skip].data = &buf[buf_start];
1043  break;
1044 
1046  buf_start = buf_off;
1047  if (GNUNET_OK !=
1049  sizeof(buf),
1050  &buf_off,
1051  rec->data.soa))
1052  {
1053  GNUNET_break (0);
1054  skip++;
1055  continue;
1056  }
1057  rd[i - skip].data_size = buf_off - buf_start;
1058  rd[i - skip].data = &buf[buf_start];
1059  break;
1060 
1062  buf_start = buf_off;
1063  if (GNUNET_OK !=
1065  sizeof(buf),
1066  &buf_off,
1067  rec->data.mx))
1068  {
1069  GNUNET_break (0);
1070  skip++;
1071  continue;
1072  }
1073  rd[i - skip].data_size = buf_off - buf_start;
1074  rd[i - skip].data = &buf[buf_start];
1075  break;
1076 
1078  buf_start = buf_off;
1079  if (GNUNET_OK !=
1081  sizeof(buf),
1082  &buf_off,
1083  rec->data.srv))
1084  {
1085  GNUNET_break (0);
1086  skip++;
1087  continue;
1088  }
1089  rd[i - skip].data_size = buf_off - buf_start;
1090  rd[i - skip].data = &buf[buf_start];
1091  break;
1092 
1093  default:
1095  _ ("Skipping record of unsupported type %d\n"),
1096  rec->type);
1097  skip++;
1098  continue;
1099  }
1100  } /* end of for all records in answer */
1101  if (NULL != rh->leho)
1102  {
1103  rd[rd_count - skip].record_type = GNUNET_GNSRECORD_TYPE_LEHO;
1104  rd[rd_count - skip].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1105  rd[rd_count - skip].flags |= GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
1106  rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1107  rd[rd_count - skip].data = rh->leho;
1108  rd[rd_count - skip].data_size = strlen (rh->leho);
1109  skip--; /* skip one LESS */
1111  "Adding LEHO %s\n",
1112  rh->leho);
1113  }
1115  "Returning DNS response for `%s' with %u answers\n",
1116  rh->ac_tail->label,
1117  (unsigned int) (rd_count - skip));
1118  rh->proc (rh->proc_cls,
1119  rd_count - skip,
1120  rd);
1122  rh->dns_request = NULL;
1123  }
1125  if (NULL != rh->task_id)
1126  GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1128  rh);
1129 }
1130 
1131 
1140 static void
1142 {
1143  struct AuthorityChain *ac;
1144  struct GNUNET_DNSPARSER_Query *query;
1145  struct GNUNET_DNSPARSER_Packet *p;
1146  char *dns_request;
1147  size_t dns_request_length;
1148  int ret;
1149 
1150  ac = rh->ac_tail;
1151  GNUNET_assert (NULL != ac);
1153  "Starting DNS lookup for `%s'\n",
1154  ac->label);
1155  GNUNET_assert (GNUNET_NO == ac->gns_authority);
1156  query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1157  query->name = GNUNET_strdup (ac->label);
1158  query->type = rh->record_type;
1161  p->queries = query;
1162  p->num_queries = 1;
1164  UINT16_MAX);
1165  p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1166  p->flags.recursion_desired = 1;
1168  1024,
1169  &dns_request,
1170  &dns_request_length);
1171  if (GNUNET_OK != ret)
1172  {
1173  GNUNET_break (0);
1174  rh->proc (rh->proc_cls,
1175  0,
1176  NULL);
1177  GNUNET_assert (NULL == rh->task_id);
1179  rh);
1180  }
1181  else
1182  {
1183  rh->original_dns_id = p->id;
1184  GNUNET_assert (NULL != ac->authority_info.dns_authority.dns_handle);
1185  GNUNET_assert (NULL == rh->dns_request);
1186  rh->leho = GNUNET_strdup (ac->label);
1188  ac->authority_info.dns_authority.dns_handle,
1189  dns_request,
1190  dns_request_length,
1192  rh);
1195  rh);
1196  }
1197  if (GNUNET_SYSERR != ret)
1198  GNUNET_free (dns_request);
1200 }
1201 
1202 
1211 static void
1213  const char *rname)
1214 {
1215  size_t nlen;
1216  char *res;
1217  const char *tld;
1218  struct AuthorityChain *ac;
1219  int af;
1221 
1223  "Handling GNS REDIRECT result `%s'\n",
1224  rname);
1225  nlen = strlen (rname);
1226  tld = GNS_get_tld (rname);
1227  if (0 == strcmp ("+", tld))
1228  {
1229  /* REDIRECT resolution continues relative to current domain */
1230  if (0 == rh->name_resolution_pos)
1231  {
1232  res = GNUNET_strndup (rname, nlen - 2);
1233  rh->name_resolution_pos = nlen - 2;
1234  }
1235  else
1236  {
1237  GNUNET_asprintf (&res,
1238  "%.*s.%.*s",
1239  (int) rh->name_resolution_pos,
1240  rh->name,
1241  (int) (nlen - 2),
1242  rname);
1243  rh->name_resolution_pos = strlen (res);
1244  }
1245  GNUNET_free (rh->name);
1246  rh->name = res;
1247  ac = GNUNET_new (struct AuthorityChain);
1248  ac->rh = rh;
1249  ac->gns_authority = GNUNET_YES;
1250  ac->authority_info.gns_authority =
1252  ac->label = resolver_lookup_get_next_label (rh);
1253  /* add AC to tail */
1255  rh->ac_tail,
1256  ac);
1258  rh);
1259  return;
1260  }
1262  {
1263  /* REDIRECT resolution continues relative to current domain */
1264  if (0 == rh->name_resolution_pos)
1265  {
1266  GNUNET_asprintf (&res,
1267  "%.*s",
1268  (int) (strlen (rname) - (strlen (tld) + 1)),
1269  rname);
1270  }
1271  else
1272  {
1273  GNUNET_asprintf (&res,
1274  "%.*s.%.*s",
1275  (int) rh->name_resolution_pos,
1276  rh->name,
1277  (int) (strlen (rname) - (strlen (tld) + 1)),
1278  rname);
1279  }
1280  rh->name_resolution_pos = strlen (res);
1281  GNUNET_free (rh->name);
1282  rh->name = res;
1283  ac = GNUNET_new (struct AuthorityChain);
1284  ac->rh = rh;
1285  ac->gns_authority = GNUNET_YES;
1286  ac->authority_info.gns_authority = zone;
1287  ac->label = resolver_lookup_get_next_label (rh);
1288  /* add AC to tail */
1290  rh->ac_tail,
1291  ac);
1293  rh);
1294  return;
1295  }
1296 
1298  "Got REDIRECT `%s' from GNS for `%s'\n",
1299  rname,
1300  rh->name);
1301  if (NULL != rh->std_resolve)
1302  {
1304  "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1305  rh->name);
1307  }
1308  /* name is absolute, go to DNS */
1309  GNUNET_free (rh->name);
1310  rh->name = GNUNET_strdup (rname);
1311  rh->name_resolution_pos = strlen (rh->name);
1312  switch (rh->record_type)
1313  {
1315  af = AF_INET;
1316  break;
1317 
1319  af = AF_INET6;
1320  break;
1321 
1322  default:
1323  af = AF_UNSPEC;
1324  break;
1325  }
1327  "Doing standard DNS lookup for `%s'\n",
1328  rh->name);
1329 
1331  af,
1334  rh);
1335 }
1336 
1337 
1338 
1347 static void
1349  const char *cname)
1350 {
1351  int af;
1352 
1353  GNUNET_free (rh->name);
1354  rh->name = GNUNET_strdup (cname);
1355  rh->name_resolution_pos = strlen (rh->name);
1356  switch (rh->record_type)
1357  {
1359  af = AF_INET;
1360  break;
1361 
1363  af = AF_INET6;
1364  break;
1365 
1366  default:
1367  af = AF_UNSPEC;
1368  break;
1369  }
1371  "Doing standard DNS lookup for `%s'\n",
1372  rh->name);
1373 
1375  af,
1378  rh);
1379 }
1380 
1381 
1389 static void
1390 handle_gns_resolution_result (void *cls,
1391  unsigned int rd_count,
1392  const struct GNUNET_GNSRECORD_Data *rd);
1393 
1394 
1395 
1403 static void
1405 {
1406  struct GNS_ResolverHandle *rh = ac->rh;
1407 
1408  if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1409  (GNUNET_NO == ac->authority_info.dns_authority.found))
1410  return; /* more pending and none found yet */
1411  if (GNUNET_NO == ac->authority_info.dns_authority.found)
1412  {
1414  "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1415  ac->authority_info.dns_authority.name);
1416  fail_resolution (rh);
1417  return;
1418  }
1419  if (GNUNET_NO != ac->authority_info.dns_authority.launched)
1420  return; /* already running, do not launch again! */
1421  /* recurse */
1422  ac->authority_info.dns_authority.launched = GNUNET_YES;
1424  "Will continue resolution using DNS to resolve `%s'\n",
1425  ac->label);
1426  GNUNET_assert (NULL == rh->task_id);
1428  rh);
1429 }
1430 
1431 
1440 static void
1442  unsigned int rd_count,
1443  const struct GNUNET_GNSRECORD_Data *rd)
1444 {
1445  struct Gns2DnsPending *gp = cls;
1446  struct AuthorityChain *ac = gp->ac;
1447 
1448  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
1449  ac->authority_info.dns_authority.gp_tail,
1450  gp);
1451  /* enable cleanup of 'rh' handle that automatically comes after we return,
1452  and which expects 'rh' to be in the #rlh_head DLL. */
1453  if (NULL != gp->rh)
1454  {
1456  rlh_tail,
1457  gp->rh);
1458  gp->rh = NULL;
1459  }
1460  GNUNET_free (gp);
1462  "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1463  rd_count);
1464  /* find suitable A/AAAA record */
1465  for (unsigned int j = 0; j < rd_count; j++)
1466  {
1467  switch (rd[j].record_type)
1468  {
1470  {
1471  struct sockaddr_in v4;
1472 
1473  if (sizeof(struct in_addr) != rd[j].data_size)
1474  {
1475  GNUNET_break_op (0);
1476  continue;
1477  }
1478  memset (&v4,
1479  0,
1480  sizeof(v4));
1481  v4.sin_family = AF_INET;
1482  v4.sin_port = htons (53);
1483 #if HAVE_SOCKADDR_IN_SIN_LEN
1484  v4.sin_len = (u_char) sizeof(v4);
1485 #endif
1486  GNUNET_memcpy (&v4.sin_addr,
1487  rd[j].data,
1488  sizeof(struct in_addr));
1489  if (GNUNET_OK ==
1491  ac->authority_info.dns_authority.dns_handle,
1492  (const struct sockaddr *) &v4))
1493  ac->authority_info.dns_authority.found = GNUNET_YES;
1494  break;
1495  }
1496 
1498  {
1499  struct sockaddr_in6 v6;
1500 
1501  if (sizeof(struct in6_addr) != rd[j].data_size)
1502  {
1503  GNUNET_break_op (0);
1504  continue;
1505  }
1506  /* FIXME: might want to check if we support IPv6 here,
1507  and otherwise skip this one and hope we find another */
1508  memset (&v6,
1509  0,
1510  sizeof(v6));
1511  v6.sin6_family = AF_INET6;
1512  v6.sin6_port = htons (53);
1513 #if HAVE_SOCKADDR_IN_SIN_LEN
1514  v6.sin6_len = (u_char) sizeof(v6);
1515 #endif
1516  GNUNET_memcpy (&v6.sin6_addr,
1517  rd[j].data,
1518  sizeof(struct in6_addr));
1519  if (GNUNET_OK ==
1521  ac->authority_info.dns_authority.dns_handle,
1522  (const struct sockaddr *) &v6))
1523  ac->authority_info.dns_authority.found = GNUNET_YES;
1524  break;
1525  }
1526 
1527  default:
1528  break;
1529  }
1530  }
1532 }
1533 
1534 
1542 static void
1544  const struct sockaddr *addr,
1545  socklen_t addrlen)
1546 {
1547  struct Gns2DnsPending *gp = cls;
1548  struct AuthorityChain *ac = gp->ac;
1549  struct sockaddr_storage ss;
1550  struct sockaddr_in *v4;
1551  struct sockaddr_in6 *v6;
1552 
1553  if (NULL == addr)
1554  {
1555  /* DNS resolution finished */
1556  if (0 == gp->num_results)
1558  "Failed to use DNS to resolve name of DNS resolver\n");
1559  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
1560  ac->authority_info.dns_authority.gp_tail,
1561  gp);
1562  GNUNET_free (gp);
1564  return;
1565  }
1566  GNUNET_memcpy (&ss,
1567  addr,
1568  addrlen);
1569  switch (ss.ss_family)
1570  {
1571  case AF_INET:
1572  v4 = (struct sockaddr_in *) &ss;
1573  v4->sin_port = htons (53);
1574  gp->num_results++;
1575  break;
1576 
1577  case AF_INET6:
1578  v6 = (struct sockaddr_in6 *) &ss;
1579  v6->sin6_port = htons (53);
1580  gp->num_results++;
1581  break;
1582 
1583  default:
1585  "Unsupported AF %d\n",
1586  ss.ss_family);
1587  return;
1588  }
1589  if (GNUNET_OK ==
1590  GNUNET_DNSSTUB_add_dns_sa (ac->authority_info.dns_authority.dns_handle,
1591  (struct sockaddr *) &ss))
1592  ac->authority_info.dns_authority.found = GNUNET_YES;
1593 }
1594 
1601 static void
1603  const struct GNUNET_GNSRECORD_Data *rd)
1604 {
1606  rd->data);
1607 }
1608 
1609 
1616 static void
1618  const struct GNUNET_GNSRECORD_Data *rd)
1619 {
1620  char *cname;
1621  size_t off;
1622 
1623  off = 0;
1624  cname = GNUNET_DNSPARSER_parse_name (rd->data,
1625  rd->data_size,
1626  &off);
1627  if ((NULL == cname) ||
1628  (off != rd->data_size))
1629  {
1630  GNUNET_break_op (0); /* record not well-formed */
1631  GNUNET_free (cname);
1632  fail_resolution (rh);
1633  return;
1634  }
1636  cname);
1637  GNUNET_free (cname);
1638 }
1639 
1640 
1647 static void
1649  const struct GNUNET_GNSRECORD_Data *rd)
1650 {
1651  struct AuthorityChain *ac;
1652  struct GNUNET_IDENTITY_PublicKey auth;
1653 
1654  /* delegation to another zone */
1656  rd->data_size,
1657  rd->record_type,
1658  &auth))
1659  {
1660  GNUNET_break_op (0);
1661  fail_resolution (rh);
1662  return;
1663  }
1664  /* expand authority chain */
1665  ac = GNUNET_new (struct AuthorityChain);
1666  ac->rh = rh;
1667  ac->gns_authority = GNUNET_YES;
1668  ac->authority_info.gns_authority = auth;
1669  ac->label = resolver_lookup_get_next_label (rh);
1670  /* add AC to tail */
1672  rh->ac_tail,
1673  ac);
1674  /* recurse */
1676  rh);
1677 }
1678 
1679 
1690 static int
1692  unsigned int rd_count,
1693  const struct GNUNET_GNSRECORD_Data *rd)
1694 {
1695  struct AuthorityChain *ac;
1696  const char *tld;
1697  char *ns;
1698 
1699  ns = NULL;
1700  /* expand authority chain */
1701  ac = GNUNET_new (struct AuthorityChain);
1702  ac->rh = rh;
1703  ac->authority_info.dns_authority.dns_handle = GNUNET_DNSSTUB_start (4);
1704 
1705  for (unsigned int i = 0; i < rd_count; i++)
1706  {
1707  char *ip;
1708  char *n;
1709  size_t off;
1710  struct Gns2DnsPending *gp;
1712  struct sockaddr_in v4;
1713  struct sockaddr_in6 v6;
1714 
1715  if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1716  {
1720  GNUNET_free (ns);
1721  GNUNET_free (ac);
1722  return GNUNET_SYSERR;
1723  }
1724  off = 0;
1725  n = GNUNET_DNSPARSER_parse_name (rd[i].data,
1726  rd[i].data_size,
1727  &off);
1728  ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1729  if ((NULL == n) ||
1730  (NULL == ip))
1731  {
1732  GNUNET_break_op (0);
1733  GNUNET_free (n);
1734  GNUNET_free (ip);
1735  continue;
1736  }
1737 
1738  off += strlen (ip) + 1;
1739 
1740  if (off != rd[i].data_size)
1741  {
1742  GNUNET_break_op (0);
1743  GNUNET_free (n);
1744  GNUNET_free (ip);
1745  continue;
1746  }
1747  /* resolve 'ip' to determine the IP(s) of the DNS
1748  resolver to use for lookup of 'ns' */
1749  if (NULL != ns)
1750  {
1751  if (0 != strcasecmp (ns,
1752  n))
1753  {
1754  /* NS values must all be the same for all GNS2DNS records,
1755  anything else leads to insanity */
1756  GNUNET_break_op (0);
1757  GNUNET_free (n);
1758  GNUNET_free (ip);
1759  continue;
1760  }
1761  GNUNET_free (n);
1762  }
1763  else
1764  {
1765  ns = n;
1766  }
1767 
1768  /* check if 'ip' is already an IPv4/IPv6 address */
1769  if ((1 == inet_pton (AF_INET,
1770  ip,
1771  &v4)) ||
1772  (1 == inet_pton (AF_INET6,
1773  ip,
1774  &v6)))
1775  {
1778  ac->authority_info.dns_authority.dns_handle,
1779  ip));
1780  ac->authority_info.dns_authority.found = GNUNET_YES;
1781  GNUNET_free (ip);
1782  continue;
1783  }
1784  tld = GNS_get_tld (ip);
1785  if ((0 != strcmp (tld, "+")) &&
1787  {
1788  /* 'ip' is a DNS name */
1789  gp = GNUNET_new (struct Gns2DnsPending);
1790  gp->ac = ac;
1791  GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
1792  ac->authority_info.dns_authority.gp_tail,
1793  gp);
1794  gp->dns_rh = GNUNET_RESOLVER_ip_get (ip,
1795  AF_UNSPEC,
1798  gp);
1799  GNUNET_free (ip);
1800  continue;
1801  }
1802  /* 'ip' should be a GNS name */
1803  gp = GNUNET_new (struct Gns2DnsPending);
1804  gp->ac = ac;
1805  GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
1806  ac->authority_info.dns_authority.gp_tail,
1807  gp);
1808  gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1809  if (0 == strcmp (tld, "+"))
1810  {
1811  ip = translate_dot_plus (rh,
1812  ip);
1813  tld = GNS_get_tld (ip);
1814  if (GNUNET_OK !=
1816  &zone))
1817  {
1818  GNUNET_break_op (0);
1819  GNUNET_free (ip);
1820  continue;
1821  }
1822  }
1823  gp->rh->authority_zone = zone;
1825  "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1826  ip,
1827  ns);
1828  gp->rh->name = ip;
1829  gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1830  gp->rh->proc = &handle_gns2dns_result;
1831  gp->rh->proc_cls = gp;
1834  gp->rh->loop_limiter = rh->loop_limiter + 1;
1835  gp->rh->loop_threshold = rh->loop_threshold;
1836  gp->rh->task_id
1838  gp->rh);
1839  } /* end 'for all records' */
1840 
1841  if (NULL == ns)
1842  {
1843  /* not a single GNS2DNS record found */
1844  GNUNET_free (ac);
1845  return GNUNET_SYSERR;
1846  }
1848  strcpy (ac->authority_info.dns_authority.name,
1849  ns);
1850  /* for DNS recursion, the label is the full DNS name,
1851  created from the remainder of the GNS name and the
1852  name in the NS record */
1853  GNUNET_asprintf (&ac->label,
1854  "%.*s%s%s",
1855  (int) rh->name_resolution_pos,
1856  rh->name,
1857  (0 != rh->name_resolution_pos) ? "." : "",
1858  ns);
1859  GNUNET_free (ns);
1860 
1861  {
1862  /* the GNS name is UTF-8 and may include multibyte chars.
1863  * We have to convert the combined name to a DNS-compatible IDNA.
1864  */
1865  char *tmp = ac->label;
1866 
1867  if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1868  &ac->label,
1869  IDNA_ALLOW_UNASSIGNED))
1870  {
1872  _ ("Name `%s' cannot be converted to IDNA."),
1873  tmp);
1874  GNUNET_free (tmp);
1875  GNUNET_free (ac);
1876  return GNUNET_SYSERR;
1877  }
1878  GNUNET_free (tmp);
1879  }
1880 
1882  rh->ac_tail,
1883  ac);
1884  if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1885  {
1887  _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1888  ac->label);
1889  GNUNET_free (ac->label);
1890  GNUNET_free (ac);
1891  return GNUNET_SYSERR;
1892  }
1894  return GNUNET_OK;
1895 }
1896 
1897 
1905 static void
1907  unsigned int rd_count,
1908  const struct GNUNET_GNSRECORD_Data *rd)
1909 {
1910  struct GNS_ResolverHandle *rh = cls;
1911  char *cname;
1912  char scratch[UINT16_MAX];
1913  size_t scratch_off;
1914  size_t scratch_start;
1915  size_t off;
1916  struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1917  unsigned int rd_off;
1918 
1920  "Resolution succeeded for `%s' in zone %s, got %u records\n",
1921  rh->ac_tail->label,
1923  rd_count);
1924  if (0 == rd_count)
1925  {
1927  _ ("GNS lookup failed (zero records found for `%s')\n"),
1928  rh->name);
1929  fail_resolution (rh);
1930  return;
1931  }
1932 
1933  if (0 == rh->name_resolution_pos)
1934  {
1935  /* top-level match, are we done yet? */
1936  if ((rd_count > 0) &&
1939  {
1940  off = 0;
1941  cname = GNUNET_DNSPARSER_parse_name (rd[0].data,
1942  rd[0].data_size,
1943  &off);
1944  if ((NULL == cname) ||
1945  (off != rd[0].data_size))
1946  {
1947  GNUNET_break_op (0);
1948  GNUNET_free (cname);
1949  fail_resolution (rh);
1950  return;
1951  }
1953  cname);
1954  GNUNET_free (cname);
1955  return;
1956  }
1957  if ((rd_count > 0) &&
1960  {
1962  rd[0].data);
1963  return;
1964  }
1965 
1966 
1967  /* If A/AAAA was requested,
1968  * but we got a GNS2DNS record */
1969  if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
1971  {
1972  for (unsigned int i = 0; i < rd_count; i++)
1973  {
1974  switch (rd[i].record_type)
1975  {
1977  {
1978  /* delegation to DNS */
1980  "Found GNS2DNS record, delegating to DNS!\n");
1981  if (GNUNET_OK ==
1983  rd_count,
1984  rd))
1985  return;
1986  else
1987  goto fail;
1988  }
1989 
1990  default:
1991  break;
1992  } /* end: switch */
1993  } /* end: for rd */
1994  } /* end: name_resolution_pos */
1995  /* convert relative names in record values to absolute names,
1996  using 'scratch' array for memory allocations */
1997  scratch_off = 0;
1998  rd_off = 0;
1999  for (unsigned int i = 0; i < rd_count; i++)
2000  {
2001  GNUNET_assert (rd_off <= i);
2002  if ((0 != rh->protocol) &&
2003  (0 != rh->service) &&
2005  continue; /* we _only_ care about boxed records */
2006 
2007  GNUNET_assert (rd_off < rd_count);
2008  rd_new[rd_off] = rd[i];
2009  /* Check if the embedded name(s) end in "+", and if so,
2010  replace the "+" with the zone at "ac_tail", changing the name
2011  to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2012  so we can free it afterwards. */
2013  switch (rd[i].record_type)
2014  {
2016  {
2017  char *rname;
2018  rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2019  rname = translate_dot_plus (rh, rname);
2020  GNUNET_break (NULL != rname);
2021  scratch_start = scratch_off;
2022  memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2023  scratch_off += strlen (rname) + 1;
2024  GNUNET_assert (rd_off < rd_count);
2025  rd_new[rd_off].data = &scratch[scratch_start];
2026  rd_new[rd_off].data_size = scratch_off - scratch_start;
2027  rd_off++;
2028  GNUNET_free (rname);
2029  }
2030  break;
2031 
2033  {
2034  char *cname;
2035 
2036  off = 0;
2037  cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
2038  rd[i].data_size,
2039  &off);
2040  if ((NULL == cname) ||
2041  (off != rd[i].data_size))
2042  {
2043  GNUNET_break_op (0); /* record not well-formed */
2044  }
2045  else
2046  {
2047  cname = translate_dot_plus (rh, cname);
2048  GNUNET_break (NULL != cname);
2049  scratch_start = scratch_off;
2050  if (GNUNET_OK !=
2052  sizeof(scratch),
2053  &scratch_off,
2054  cname))
2055  {
2056  GNUNET_break (0);
2057  }
2058  else
2059  {
2060  GNUNET_assert (rd_off < rd_count);
2061  rd_new[rd_off].data = &scratch[scratch_start];
2062  rd_new[rd_off].data_size = scratch_off - scratch_start;
2063  rd_off++;
2064  }
2065  }
2066  GNUNET_free (cname);
2067  }
2068  break;
2069 
2071  {
2072  struct GNUNET_DNSPARSER_SoaRecord *soa;
2073 
2074  off = 0;
2075  soa = GNUNET_DNSPARSER_parse_soa (rd[i].data,
2076  rd[i].data_size,
2077  &off);
2078  if ((NULL == soa) ||
2079  (off != rd[i].data_size))
2080  {
2081  GNUNET_break_op (0); /* record not well-formed */
2082  }
2083  else
2084  {
2085  soa->mname = translate_dot_plus (rh, soa->mname);
2086  soa->rname = translate_dot_plus (rh, soa->rname);
2087  scratch_start = scratch_off;
2088  if (GNUNET_OK !=
2090  sizeof(scratch),
2091  &scratch_off,
2092  soa))
2093  {
2094  GNUNET_break (0);
2095  }
2096  else
2097  {
2098  GNUNET_assert (rd_off < rd_count);
2099  rd_new[rd_off].data = &scratch[scratch_start];
2100  rd_new[rd_off].data_size = scratch_off - scratch_start;
2101  rd_off++;
2102  }
2103  }
2104  if (NULL != soa)
2106  }
2107  break;
2108 
2110  {
2111  struct GNUNET_DNSPARSER_MxRecord *mx;
2112 
2113  off = 0;
2114  mx = GNUNET_DNSPARSER_parse_mx (rd[i].data,
2115  rd[i].data_size,
2116  &off);
2117  if ((NULL == mx) ||
2118  (off != rd[i].data_size))
2119  {
2120  GNUNET_break_op (0); /* record not well-formed */
2121  }
2122  else
2123  {
2124  mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2125  scratch_start = scratch_off;
2126  if (GNUNET_OK !=
2128  sizeof(scratch),
2129  &scratch_off,
2130  mx))
2131  {
2132  GNUNET_break (0);
2133  }
2134  else
2135  {
2136  GNUNET_assert (rd_off < rd_count);
2137  rd_new[rd_off].data = &scratch[scratch_start];
2138  rd_new[rd_off].data_size = scratch_off - scratch_start;
2139  rd_off++;
2140  }
2141  }
2142  if (NULL != mx)
2144  }
2145  break;
2146 
2148  {
2149  struct GNUNET_DNSPARSER_SrvRecord *srv;
2150 
2151  off = 0;
2152  srv = GNUNET_DNSPARSER_parse_srv (rd[i].data,
2153  rd[i].data_size,
2154  &off);
2155  if ((NULL == srv) ||
2156  (off != rd[i].data_size))
2157  {
2158  GNUNET_break_op (0); /* record not well-formed */
2159  }
2160  else
2161  {
2162  srv->target = translate_dot_plus (rh, srv->target);
2163  scratch_start = scratch_off;
2164  if (GNUNET_OK !=
2166  sizeof(scratch),
2167  &scratch_off,
2168  srv))
2169  {
2170  GNUNET_break (0);
2171  }
2172  else
2173  {
2174  GNUNET_assert (rd_off < rd_count);
2175  rd_new[rd_off].data = &scratch[scratch_start];
2176  rd_new[rd_off].data_size = scratch_off - scratch_start;
2177  rd_off++;
2178  }
2179  }
2180  if (NULL != srv)
2182  }
2183  break;
2184 
2187  {
2189  if (rd[i].data_size < sizeof(uint32_t))
2190  {
2191  GNUNET_break_op (0);
2192  break;
2193  }
2194  if (GNUNET_OK !=
2196  rd[i].data_size,
2197  rd[i].record_type,
2198  &pubkey))
2199  {
2200  GNUNET_break_op (0);
2201  break;
2202  }
2203  rd_off++;
2204  if (rd[i].record_type != rh->record_type)
2205  {
2206  /* try to resolve "@" */
2207  struct AuthorityChain *ac;
2208 
2209  ac = GNUNET_new (struct AuthorityChain);
2210  ac->rh = rh;
2211  ac->gns_authority = GNUNET_YES;
2212  ac->authority_info.gns_authority = pubkey;
2215  rh->ac_tail,
2216  ac);
2218  rh);
2219  return;
2220  }
2221  }
2222  break;
2223 
2225  {
2226  /* delegation to DNS */
2228  {
2229  rd_off++;
2230  break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2231  }
2233  "Found GNS2DNS record, delegating to DNS!\n");
2234  if (GNUNET_OK ==
2236  rd_count,
2237  rd))
2238  return;
2239  else
2240  goto fail;
2241  }
2242 
2244  {
2245  /* unbox SRV/TLSA records if a specific one was requested */
2246  if ((0 != rh->protocol) &&
2247  (0 != rh->service) &&
2248  (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2249  {
2250  const struct GNUNET_GNSRECORD_BoxRecord *box;
2251 
2252  box = rd[i].data;
2254  "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2255  ntohs (box->protocol), ntohs (box->service),
2256  rh->protocol, rh->service);
2257  if ((ntohs (box->protocol) == rh->protocol) &&
2258  (ntohs (box->service) == rh->service))
2259  {
2260  /* Box matches, unbox! */
2261  GNUNET_assert (rd_off < rd_count);
2262  rd_new[rd_off].record_type = ntohl (box->record_type);
2263  rd_new[rd_off].data_size -= sizeof(struct
2265  rd_new[rd_off].data = &box[1];
2266  rd_off++;
2267  }
2268  }
2269  else
2270  {
2271  /* no specific protocol/service specified, preserve all BOX
2272  records (for modern, GNS-enabled applications) */
2273  rd_off++;
2274  }
2275  break;
2276  }
2277 
2278  default:
2279  rd_off++;
2280  break;
2281  } /* end: switch */
2282  } /* end: for rd_count */
2283 
2284  /* yes, we are done, return result */
2286  "Returning GNS response for `%s' with %u answers\n",
2287  rh->ac_tail->label,
2288  rd_off);
2289  rh->proc (rh->proc_cls,
2290  rd_off,
2291  rd_new);
2293  rh);
2294  return;
2295  }
2296 
2297  switch (rd[0].record_type)
2298  {
2300  GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2302  &rd[0]);
2303  return;
2304 
2306  GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2308  &rd[0]);
2309  return;
2310 
2313  GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2315  &rd[0]);
2316  return;
2317 
2319  if (GNUNET_OK ==
2321  rd_count,
2322  rd))
2323  return;
2324  break;
2325  default:
2327  return;
2329  _ ("Unable to process critical delegation record\n"));
2330  break;
2331  }
2332  fail:
2334  _ ("GNS lookup recursion failed (no delegation record found)\n"));
2335  fail_resolution (rh);
2336 }
2337 
2338 
2347 static void
2349  int32_t success,
2350  const char *emsg)
2351 {
2352  struct CacheOps *co = cls;
2353 
2354  co->namecache_qe_cache = NULL;
2355  if (GNUNET_OK != success)
2357  _ ("Failed to cache GNS resolution: %s\n"),
2358  emsg);
2360  co_tail,
2361  co);
2362  GNUNET_free (co);
2363 }
2364 
2365 
2383 static void
2385  struct GNUNET_TIME_Absolute exp,
2386  const struct GNUNET_HashCode *key,
2387  const struct GNUNET_DHT_PathElement *get_path,
2388  unsigned int get_path_length,
2389  const struct GNUNET_DHT_PathElement *put_path,
2390  unsigned int put_path_length,
2391  enum GNUNET_BLOCK_Type type,
2392  size_t size,
2393  const void *data)
2394 {
2395  struct GNS_ResolverHandle *rh = cls;
2396  struct AuthorityChain *ac = rh->ac_tail;
2397  const struct GNUNET_GNSRECORD_Block *block;
2398  struct CacheOps *co;
2399 
2400  (void) exp;
2401  (void) key;
2402  (void) get_path;
2403  (void) get_path_length;
2404  (void) put_path;
2405  (void) put_path_length;
2406  (void) type;
2408  rh->get_handle = NULL;
2410  rh->dht_heap_node = NULL;
2412  "Handling response from the DHT\n");
2413  if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2414  {
2415  /* how did this pass DHT block validation!? */
2416  GNUNET_break (0);
2417  fail_resolution (rh);
2418  return;
2419  }
2420  block = data;
2421  if (size != GNUNET_GNSRECORD_block_get_size (block))
2422  {
2423  /* how did this pass DHT block validation!? */
2424  GNUNET_break (0);
2425  fail_resolution (rh);
2426  return;
2427  }
2429  "Decrypting DHT block of size %lu for `%s', expires %s\n",
2431  rh->name,
2433  if (GNUNET_OK !=
2435  &ac->authority_info.gns_authority,
2436  ac->label,
2438  rh))
2439  {
2440  GNUNET_break_op (0); /* block was ill-formed */
2441  fail_resolution (rh);
2442  return;
2443  }
2446  rel_value_us)
2447  {
2449  "Received expired block from the DHT, will not cache it.\n");
2450  return;
2451  }
2452  if (GNUNET_YES == disable_cache)
2453  return;
2454  /* Cache well-formed blocks */
2456  "Caching response from the DHT in namecache\n");
2457  co = GNUNET_new (struct CacheOps);
2459  block,
2460  &
2462  co);
2464  co_tail,
2465  co);
2466 }
2467 
2468 
2475 static void
2477  const struct GNUNET_HashCode *query)
2478 {
2479  struct GNS_ResolverHandle *rx;
2480 
2481  GNUNET_assert (NULL == rh->get_handle);
2484  query,
2487  NULL, 0,
2488  &handle_dht_response, rh);
2490  rh,
2492  abs_value_us);
2495  {
2496  /* fail longest-standing DHT request */
2498  rx->dht_heap_node = NULL;
2499  GNUNET_assert (NULL != rx);
2500  fail_resolution (rx);
2501  }
2502 }
2503 
2504 
2513 static void
2515  unsigned int rd_count,
2516  const struct GNUNET_GNSRECORD_Data *rd)
2517 {
2518  struct GNS_ResolverHandle *rh = cls;
2519 
2520  if (0 == rd_count)
2522  _ ("GNS namecache returned empty result for `%s'\n"),
2523  rh->name);
2525  rd_count,
2526  rd);
2527 }
2528 
2529 
2536 static void
2538  const struct GNUNET_GNSRECORD_Block *block)
2539 {
2540  struct GNS_ResolverHandle *rh = cls;
2541  struct AuthorityChain *ac = rh->ac_tail;
2542  const char *label = ac->label;
2543  const struct GNUNET_IDENTITY_PublicKey *auth =
2544  &ac->authority_info.gns_authority;
2545  struct GNUNET_HashCode query;
2546 
2547  GNUNET_assert (NULL != rh->namecache_qe);
2548  rh->namecache_qe = NULL;
2549  if (NULL == block)
2551  "No block found\n");
2552  else
2554  "Got block with expiration %s\n",
2556  if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2557  ((GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2558  (ac != rh->ac_head))) &&
2559  ((NULL == block) ||
2562  rel_value_us)))
2563  {
2564  /* namecache knows nothing; try DHT lookup */
2566  label,
2567  &query);
2569  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2570  ac->label,
2571  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority),
2572  GNUNET_h2s (&query));
2573  start_dht_request (rh, &query);
2574  return;
2575  }
2576 
2577  if ((NULL == block) ||
2580  rel_value_us))
2581  {
2582  /* DHT not permitted and no local result, fail */
2584  "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2585  ac->label,
2586  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2587  fail_resolution (rh);
2588  return;
2589  }
2591  "Received result from namecache for label `%s'\n",
2592  ac->label);
2593 
2594  if (GNUNET_OK !=
2596  auth,
2597  label,
2599  rh))
2600  {
2601  GNUNET_break_op (0); /* block was ill-formed */
2602  /* try DHT instead */
2604  label,
2605  &query);
2607  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2608  ac->label,
2609  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority),
2610  GNUNET_h2s (&query));
2611  start_dht_request (rh, &query);
2612  return;
2613  }
2614 }
2615 
2616 
2622 static void
2624 {
2625  struct AuthorityChain *ac = rh->ac_tail;
2626  struct GNUNET_HashCode query;
2627 
2629  "Starting GNS resolution for `%s' in zone %s\n",
2630  ac->label,
2631  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2632  GNUNET_GNSRECORD_query_from_public_key (&ac->authority_info.gns_authority,
2633  ac->label,
2634  &query);
2635  if (GNUNET_YES != disable_cache)
2636  {
2637  rh->namecache_qe
2639  &query,
2641  rh);
2642  GNUNET_assert (NULL != rh->namecache_qe);
2643  }
2644  else
2645  {
2646  start_dht_request (rh,
2647  &query);
2648  }
2649 }
2650 
2651 
2658 static void
2660  int is_valid)
2661 {
2662  struct GNS_ResolverHandle *rh = cls;
2663  struct AuthorityChain *ac = rh->ac_tail;
2664 
2665  rh->rev_check = NULL;
2666  if (GNUNET_YES != is_valid)
2667  {
2669  _ ("Zone %s was revoked, resolution fails\n"),
2670  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2671  fail_resolution (rh);
2672  return;
2673  }
2675 }
2676 
2677 
2683 static void
2685 {
2686  struct AuthorityChain *ac = rh->ac_tail;
2687 
2689  "Starting revocation check for zone %s\n",
2690  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2692  &ac->authority_info.gns_authority,
2694  rh);
2695  GNUNET_assert (NULL != rh->rev_check);
2696 }
2697 
2698 
2704 static void
2706 {
2707  struct GNS_ResolverHandle *rh = cls;
2708 
2709  rh->task_id = NULL;
2710  if (rh->loop_threshold < rh->loop_limiter++)
2711  {
2713  "Encountered unbounded recursion resolving `%s'\n",
2714  rh->name);
2715  fail_resolution (rh);
2716  return;
2717  }
2718  if (GNUNET_YES == rh->ac_tail->gns_authority)
2720  else
2722 }
2723 
2724 
2731 static void
2733 {
2734  struct GNS_ResolverHandle *rh = cls;
2735  struct AuthorityChain *ac;
2736  struct in_addr v4;
2737  struct in6_addr v6;
2738 
2739  rh->task_id = NULL;
2740  if (1 == inet_pton (AF_INET,
2741  rh->name,
2742  &v4))
2743  {
2744  /* name is IPv4 address, pretend it's an A record */
2745  struct GNUNET_GNSRECORD_Data rd;
2746 
2747  rd.data = &v4;
2748  rd.data_size = sizeof(v4);
2749  rd.expiration_time = UINT64_MAX;
2751  rd.flags = 0;
2752  rh->proc (rh->proc_cls,
2753  1,
2754  &rd);
2755  GNUNET_assert (NULL == rh->task_id);
2757  rh);
2758  return;
2759  }
2760  if (1 == inet_pton (AF_INET6,
2761  rh->name,
2762  &v6))
2763  {
2764  /* name is IPv6 address, pretend it's an AAAA record */
2765  struct GNUNET_GNSRECORD_Data rd;
2766 
2767  rd.data = &v6;
2768  rd.data_size = sizeof(v6);
2769  rd.expiration_time = UINT64_MAX;
2771  rd.flags = 0;
2772  rh->proc (rh->proc_cls,
2773  1,
2774  &rd);
2775  GNUNET_assert (NULL == rh->task_id);
2777  rh);
2778  return;
2779  }
2780 
2781  ac = GNUNET_new (struct AuthorityChain);
2782  ac->rh = rh;
2783  ac->label = resolver_lookup_get_next_label (rh);
2784  if (NULL == ac->label)
2785  /* name was just the "TLD", so we default to label
2786  #GNUNET_GNS_EMPTY_LABEL_AT */
2788  ac->gns_authority = GNUNET_YES;
2789  ac->authority_info.gns_authority = rh->authority_zone;
2791  rh->ac_tail,
2792  ac);
2794  rh);
2795 }
2796 
2797 
2812 struct GNS_ResolverHandle *
2814  uint32_t record_type,
2815  const char *name,
2817  uint16_t recursion_depth_limit,
2819  void *proc_cls)
2820 {
2821  struct GNS_ResolverHandle *rh;
2822 
2824  "Starting lookup for `%s'\n",
2825  name);
2826  rh = GNUNET_new (struct GNS_ResolverHandle);
2828  rlh_tail,
2829  rh);
2830  rh->authority_zone = *zone;
2831  rh->proc = proc;
2832  rh->proc_cls = proc_cls;
2833  rh->options = options;
2834  rh->record_type = record_type;
2835  rh->name = GNUNET_strdup (name);
2836  rh->name_resolution_pos = strlen (name);
2837  rh->loop_threshold = recursion_depth_limit;
2839  rh);
2840  return rh;
2841 }
2842 
2843 
2849 void
2851 {
2852  struct DnsResult *dr;
2853  struct AuthorityChain *ac;
2854 
2856  rlh_tail,
2857  rh);
2858  if (NULL != rh->dns_request)
2859  {
2861  rh->dns_request = NULL;
2862  }
2863  while (NULL != (ac = rh->ac_head))
2864  {
2866  rh->ac_tail,
2867  ac);
2868  if (GNUNET_NO == ac->gns_authority)
2869  {
2870  struct Gns2DnsPending *gp;
2871 
2872  while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2873  {
2874  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
2875  ac->authority_info.dns_authority.gp_tail,
2876  gp);
2877  if (NULL != gp->rh)
2878  {
2879  /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2880  using GNS_resolver_lookup_cancel here, we need to
2881  add it first... */
2883  rlh_tail,
2884  gp->rh);
2885  GNUNET_assert (NULL == gp->rh->task_id);
2888  gp->rh);
2889  gp->rh = NULL;
2890  }
2891  if (NULL != gp->dns_rh)
2892  {
2894  gp->dns_rh = NULL;
2895  }
2896  GNUNET_free (gp);
2897  }
2898  GNUNET_DNSSTUB_stop (ac->authority_info.dns_authority.dns_handle);
2899  }
2900  GNUNET_free (ac->label);
2901  GNUNET_free (ac);
2902  }
2903  if (NULL != rh->task_id)
2904  {
2906  rh->task_id = NULL;
2907  }
2908  if (NULL != rh->get_handle)
2909  {
2911  rh->get_handle = NULL;
2912  }
2913  if (NULL != rh->dht_heap_node)
2914  {
2916  rh->dht_heap_node = NULL;
2917  }
2918  if (NULL != rh->namecache_qe)
2919  {
2921  rh->namecache_qe = NULL;
2922  }
2923  if (NULL != rh->rev_check)
2924  {
2926  rh->rev_check = NULL;
2927  }
2928  if (NULL != rh->std_resolve)
2929  {
2931  "Canceling standard DNS resolution\n");
2933  rh->std_resolve = NULL;
2934  }
2935  while (NULL != (dr = rh->dns_result_head))
2936  {
2939  dr);
2940  GNUNET_free (dr);
2941  }
2942  GNUNET_free (rh->leho);
2943  GNUNET_free (rh->name);
2944  GNUNET_free (rh);
2945 }
2946 
2947 
2948 /* ***************** Resolver initialization ********************* */
2949 
2950 
2959 void
2961  struct GNUNET_DHT_Handle *dht,
2962  const struct GNUNET_CONFIGURATION_Handle *c,
2963  unsigned long long max_bg_queries)
2964 {
2965  cfg = c;
2966  namecache_handle = nc;
2967  dht_handle = dht;
2968  dht_lookup_heap =
2970  max_allowed_background_queries = max_bg_queries;
2972  "namecache",
2973  "DISABLE");
2974  if (GNUNET_YES == disable_cache)
2976  "Namecache disabled\n");
2977 }
2978 
2979 
2983 void
2985 {
2986  struct GNS_ResolverHandle *rh;
2987  struct CacheOps *co;
2988 
2989  /* abort active resolutions */
2990  while (NULL != (rh = rlh_head))
2991  {
2992  rh->proc (rh->proc_cls,
2993  0,
2994  NULL);
2996  }
2997  while (NULL != (co = co_head))
2998  {
3000  co_tail,
3001  co);
3003  GNUNET_free (co);
3004  }
3006  dht_lookup_heap = NULL;
3007  dht_handle = NULL;
3008  namecache_handle = NULL;
3009 }
3010 
3011 
3012 /* end of gnunet-service-gns_resolver.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
#define memrchr(s, c, n)
Definition: compat.h:49
IPC messages between GNS API and GNS service.
#define GNUNET_GNSRECORD_TYPE_BOX
Boxed records (see TLSA/SRV handling in GNS)
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Delegation to DNS.
#define GNUNET_GNSRECORD_TYPE_REDIRECT
Resolver redirects.
#define GNUNET_GNSRECORD_TYPE_LEHO
legacy hostnames
#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
Record type for EDKEY zone delegations.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_NAMESTORE_Handle * ns
Handle to the namestore.
Definition: gnunet-abd.c:41
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static int res
static struct GNUNET_DHT_Handle * dht
Handle to the DHT.
struct GNUNET_HashCode key
The key used in the DHT.
uint32_t data
The data value.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static struct GNUNET_IDENTITY_PublicKey pubkey
Public key of the zone to look in.
static char * zone
Name of the zone being managed.
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
static char * rp
Relying party.
static struct GNUNET_PEERINFO_NotifyContext * nc
Iterator context.
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.
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 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 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 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 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 char * translate_dot_plus(struct GNS_ResolverHandle *rh, char *name)
Expands a name ending in .
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.
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_IDENTITY_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 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 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.
static void handle_dht_response(void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, 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.
#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 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 a 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.
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 char buf[2048]
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:37
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
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.
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:1187
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:1114
@ 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.
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
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
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:854
#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_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
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
#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:1077
#define GNUNET_DNSPARSER_TYPE_CNAME
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
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:1118
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_DNSPARSER_free_mx(struct GNUNET_DNSPARSER_MxRecord *mx)
Free MX information record.
Definition: dnsparser.c:154
#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:1257
#define GNUNET_DNSPARSER_TYPE_MX
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
#define GNUNET_DNSPARSER_MAX_NAME_LENGTH
Maximum length of a name in DNS.
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:617
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition: dnsstub.c:716
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition: dnsstub.c:590
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition: dnsstub.c:566
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:530
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:669
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_IDENTITY_PublicKey *pub, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_IDENTITY_PublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_IDENTITY_PublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls)
Decrypt block.
size_t GNUNET_GNSRECORD_block_get_size(const struct GNUNET_GNSRECORD_Block *block)
Returns the length of this block in bytes.
#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:264
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_IDENTITY_PublicKey *pkey)
Convert an absolute domain name to the respective public key.
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_IDENTITY_PublicKey *z)
Convert a zone key to a string (for printing debug messages).
#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.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_IDENTITY_PublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
@ 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
No special options.
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from 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_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.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
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
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_IDENTITY_PublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.
void GNUNET_REVOCATION_query_cancel(struct GNUNET_REVOCATION_Query *q)
Cancel key revocation check.
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:1281
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:957
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:1254
#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:404
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:110
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:67
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
const char * name
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.
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::@19::@20 dns_authority
struct AuthorityChain * prev
This is a DLL.
struct GNS_ResolverHandle * rh
Resolver handle this entry in the chain belongs to.
int launched
Did we start the recursive resolution via DNS?
union AuthorityChain::@19 authority_info
Information about the resolver authority for this label.
struct Gns2DnsPending * gp_head
List of resolutions of the 'ip' of the name server that are still pending.
struct Gns2DnsPending * gp_tail
Tail of list of resolutions of the 'ip' of the name server that are still pending.
Active namestore caching operations.
struct CacheOps * prev
Organized in a DLL.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe_cache
Pending Namestore caching task.
struct CacheOps * next
Organized in a DLL.
A result we got from DNS.
struct DnsResult * next
Kept in DLL.
size_t data_size
Number of bytes in data.
uint32_t record_type
Type of the GNS/DNS record.
struct DnsResult * prev
Kept in DLL.
uint64_t expiration_time
Expiration time for the DNS record, 0 if we didn't get anything useful (i.e.
const void * data
Binary value stored in the DNS record (appended to this struct)
Handle to a currently pending resolution.
size_t name_resolution_pos
Current offset in name where we are resolving.
int service
For SRV and TLSA records, the number of the service specified in the name.
char * leho
Legacy Hostname to use if we encountered GNS2DNS record and thus can deduct the LEHO from that transi...
struct GNUNET_CONTAINER_HeapNode * dht_heap_node
Heap node associated with this lookup.
void * proc_cls
closure passed to proc
struct GNS_ResolverHandle * next
DLL.
struct GNUNET_DHT_GetHandle * get_handle
Handle for DHT lookups.
struct DnsResult * dns_result_tail
DLL of results we got from DNS.
struct GNUNET_REVOCATION_Query * rev_check
Pending revocation check.
unsigned int loop_limiter
We increment the loop limiter for each step in a recursive resolution.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe
Pending Namecache lookup task.
struct GNUNET_RESOLVER_RequestHandle * std_resolve
Handle for standard DNS resolution, NULL if none is active.
int record_type
Desired type for the resolution.
struct 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.
struct GNUNET_IDENTITY_PublicKey authority_zone
The top-level GNS authoritative zone to query.
char * name
The name to resolve.
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.
Handle to a GET request.
Definition: dht_api.c:81
Connection to the DHT service.
Definition: dht_api.c:237
A (signed) path tracking a block's flow through the DHT is represented by an array of path elements,...
Information from MX records (RFC 1035).
char * mxhost
Name of the mail server.
Easy-to-process, parsed version of a DNS packet.
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
char * name
Name of the record that the query is for (0-terminated).
void * data
Binary record data.
size_t data_len
Number of bytes in data.
A DNS response record.
struct GNUNET_DNSPARSER_SoaRecord * soa
SOA data for SOA records.
struct GNUNET_DNSPARSER_SrvRecord * srv
SRV data for SRV records.
struct GNUNET_DNSPARSER_MxRecord * mx
MX data for MX records.
char * hostname
For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
struct GNUNET_TIME_Absolute expiration_time
When does the record expire?
union GNUNET_DNSPARSER_Record::@24 data
Payload of the record (which one of these is valid depends on the 'type').
char * name
Name of the record that the query is for (0-terminated).
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
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.
Handle to the stub resolver.
Definition: dnsstub.c:124
UDP socket we are using for sending DNS requests to the Internet.
Definition: dnsstub.c:45
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.
A 512-bit hashcode.
An identity key as per LSD0001.
Connection to the NAMECACHE service.
Definition: namecache_api.c:95
An QueueEntry used to store information for a pending NAMECACHE record operation.
Definition: namecache_api.c:48
Handle to a request given to the resolver.
Definition: resolver_api.c:103
Handle for the key revocation query.
Entry in list of pending tasks.
Definition: scheduler.c:135
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?
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model