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 #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 #include "gnunet_vpn_service.h"
56 
57 
61 #define DHT_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
62  GNUNET_TIME_UNIT_SECONDS, 60)
63 
67 #define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
68  GNUNET_TIME_UNIT_SECONDS, 15)
69 
73 #define VPN_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
74 
78 #define DHT_GNS_REPLICATION_LEVEL 10
79 
80 
85 struct AuthorityChain;
86 
87 
94 {
99 
104 
109 
116 
121 
125  unsigned int num_results;
126 };
127 
128 
133 struct GNS_ResolverHandle;
134 
135 
141 {
146 
151 
156 
160  char *label;
161 
167 
171  union
172  {
176  struct GNUNET_CRYPTO_EcdsaPublicKey gns_authority;
177 
178  struct
179  {
186 
192 
198 
203 
208  int found;
209 
213  int launched;
214  } dns_authority;
215  } authority_info;
216 };
217 
218 
222 struct DnsResult
223 {
227  struct DnsResult *next;
228 
232  struct DnsResult *prev;
233 
237  const void *data;
238 
243  uint64_t expiration_time;
244 
248  size_t data_size;
249 
253  uint32_t record_type;
254 };
255 
256 
261 {
266 
271 
275  unsigned int rd_count;
276 
280  char *rd_data;
281 
285  ssize_t rd_data_size;
286 };
287 
288 
294 {
299 
304 
308  struct GNUNET_CRYPTO_EcdsaPublicKey authority_zone;
309 
314 
318  void *proc_cls;
319 
324 
329 
334 
339 
344 
349 
355 
360 
365 
370 
374  char *name;
375 
380  char *leho;
381 
386 
391 
396 
401 
406  int protocol;
407 
412  int service;
413 
418 
424  unsigned int loop_limiter;
425 
429  unsigned int loop_threshold;
430 
434  uint16_t original_dns_id;
435 };
436 
437 
441 struct CacheOps
442 {
446  struct CacheOps *next;
447 
451  struct CacheOps *prev;
452 
457 };
458 
459 
464 
469 
474 
479 
483 static unsigned long long max_allowed_background_queries;
484 
489 
494 
498 static struct CacheOps *co_head;
499 
503 static struct CacheOps *co_tail;
504 
508 static int disable_cache;
509 
513 static const struct GNUNET_CONFIGURATION_Handle *cfg;
514 
515 
531 /* dead, but keep for now */ int
532 is_canonical (const char *name)
533 {
534  const char *pos;
535  const char *dot;
536 
537  if (NULL == strchr (name,
538  (unsigned char) '.'))
539  return GNUNET_YES;
540  if ('_' != name[0])
541  return GNUNET_NO;
542  pos = &name[1];
543  while (NULL != (dot = strchr (pos,
544  (unsigned char) '.')))
545  if ('_' != dot[1])
546  return GNUNET_NO;
547  else
548  pos = dot + 1;
549  return GNUNET_YES;
550 }
551 
552 
553 /* ************************** Resolution **************************** */
554 
562 static char *
564  char *name)
565 {
566  char *ret;
567  size_t s_len = strlen (name);
568 
569  if (0 != strcmp (&name[s_len - 2],
570  ".+"))
571  return name; /* did not end in ".+" */
573  GNUNET_asprintf (&ret,
574  "%.*s.%s",
575  (int) (s_len - 2),
576  name,
579  GNUNET_free (name);
580  return ret;
581 }
582 
583 
590 static void
592 {
593  struct GNS_ResolverHandle *rh = cls;
594 
595  rh->task_id = NULL;
597 }
598 
599 
605 static void
607 {
608  rh->proc (rh->proc_cls,
609  0,
610  NULL);
611  GNUNET_assert (NULL == rh->task_id);
613  rh);
614 }
615 
616 
622 static void
624 {
625  struct GNS_ResolverHandle *rh = cls;
626 
627  rh->task_id = NULL;
628  fail_resolution (rh);
629 }
630 
631 
649 static char *
651 {
652  const char *rp;
653  const char *dot;
654  size_t len;
655  char *ret;
656  char *srv_name;
657  char *proto_name;
658  struct protoent *pe;
659  struct servent *se;
660 
661  if (0 == rh->name_resolution_pos)
662  return NULL;
663  dot = memrchr (rh->name,
664  (int) '.',
665  rh->name_resolution_pos);
666  if (NULL == dot)
667  {
668  /* done, this was the last one */
669  len = rh->name_resolution_pos;
670  rp = rh->name;
671  rh->name_resolution_pos = 0;
672  }
673  else
674  {
675  /* advance by one label */
676  len = rh->name_resolution_pos - (dot - rh->name) - 1;
677  rp = dot + 1;
678  rh->name_resolution_pos = dot - rh->name;
679  }
680  rh->protocol = 0;
681  rh->service = 0;
682  ret = GNUNET_strndup (rp, len);
683  /* If we have labels starting with underscore with label on
684  * the right (SRV/DANE/BOX case), determine port/protocol;
685  * The format of `rh->name` must be "_PORT._PROTOCOL".
686  */
687  if (('_' == rh->name[0]) &&
688  (NULL != (dot = memrchr (rh->name,
689  (int) '.',
690  rh->name_resolution_pos))) &&
691  ('_' == dot[1]) &&
692  (NULL == memrchr (rh->name,
693  (int) '.',
694  dot - rh->name)))
695  {
696  srv_name = GNUNET_strndup (&rh->name[1],
697  (dot - rh->name) - 1);
698  proto_name = GNUNET_strndup (&dot[2],
699  rh->name_resolution_pos - (dot - rh->name)
700  - 2);
701  rh->name_resolution_pos = 0;
702  pe = getprotobyname (proto_name);
703  if (NULL == pe)
704  {
706  _ ("Protocol `%s' unknown, skipping labels.\n"),
707  proto_name);
708  GNUNET_free (proto_name);
709  GNUNET_free (srv_name);
710  return ret;
711  }
712  se = getservbyname (srv_name,
713  proto_name);
714  if (NULL == se)
715  {
717  _ (
718  "Service `%s' unknown for protocol `%s', trying as number.\n"),
719  srv_name,
720  proto_name);
721  if (1 != sscanf (srv_name, "%u", &rh->service))
722  {
724  _ ("Service `%s' not a port, skipping service labels.\n"),
725  srv_name);
726  GNUNET_free (proto_name);
727  GNUNET_free (srv_name);
728  return ret;
729  }
730  }
731  else
732  {
733  rh->service = se->s_port;
734  }
735  rh->protocol = pe->p_proto;
736  GNUNET_free (proto_name);
737  GNUNET_free (srv_name);
738  }
739  return ret;
740 }
741 
742 
748 static void
750 {
751  struct DnsResult *pos;
752  unsigned int n;
753  unsigned int i;
754 
755  n = 0;
756  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
757  n++;
758  {
759  struct GNUNET_GNSRECORD_Data rd[n];
760 
761  i = 0;
762  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
763  {
764  rd[i].data = pos->data;
765  rd[i].data_size = pos->data_size;
766  rd[i].record_type = pos->record_type;
767  if (0 == pos->expiration_time)
768  {
770  rd[i].expiration_time = 0;
771  }
772  else
773  {
775  rd[i].expiration_time = pos->expiration_time;
776  }
777  i++;
778  }
779  GNUNET_assert (i == n);
781  "Transmitting standard DNS result with %u records\n",
782  n);
783  rh->proc (rh->proc_cls,
784  n,
785  rd);
786  }
788 }
789 
790 
800 static void
802  uint64_t expiration_time,
803  uint32_t record_type,
804  size_t data_size,
805  const void *data)
806 {
807  struct DnsResult *res;
808 
809  res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
811  res->data_size = data_size;
812  res->record_type = record_type;
813  res->data = &res[1];
814  GNUNET_memcpy (&res[1],
815  data,
816  data_size);
818  rh->dns_result_tail,
819  res);
820 }
821 
822 
831 static void
832 handle_dns_result (void *cls,
833  const struct sockaddr *addr,
834  socklen_t addrlen)
835 {
836  struct GNS_ResolverHandle *rh = cls;
837  const struct sockaddr_in *sa4;
838  const struct sockaddr_in6 *sa6;
839 
840  if (NULL == addr)
841  {
842  rh->std_resolve = NULL;
844  return;
845  }
847  "Received %u bytes of DNS IP data\n",
848  addrlen);
849  switch (addr->sa_family)
850  {
851  case AF_INET:
852  sa4 = (const struct sockaddr_in *) addr;
853  add_dns_result (rh,
854  0 /* expiration time is unknown */,
856  sizeof(struct in_addr),
857  &sa4->sin_addr);
858  break;
859 
860  case AF_INET6:
861  sa6 = (const struct sockaddr_in6 *) addr;
862  add_dns_result (rh,
863  0 /* expiration time is unknown */,
865  sizeof(struct in6_addr),
866  &sa6->sin6_addr);
867  break;
868 
869  default:
870  GNUNET_break (0);
871  break;
872  }
873 }
874 
875 
882 static void
883 recursive_resolution (void *cls);
884 
885 
892 static void
893 start_resolver_lookup (void *cls);
894 
895 
904 static void
905 dns_result_parser (void *cls,
906  const struct GNUNET_TUN_DnsHeader *dns,
907  size_t dns_len)
908 {
909  struct GNS_ResolverHandle *rh = cls;
910  struct GNUNET_DNSPARSER_Packet *p;
911  const struct GNUNET_DNSPARSER_Record *rec;
912  unsigned int rd_count;
913 
914  if (NULL == dns)
915  {
916  rh->dns_request = NULL;
918  rh->task_id = NULL;
919  fail_resolution (rh);
920  return;
921  }
922  if (rh->original_dns_id != dns->id)
923  {
924  /* DNS answer, but for another query */
925  return;
926  }
927  p = GNUNET_DNSPARSER_parse ((const char *) dns,
928  dns_len);
929  if (NULL == p)
930  {
932  _ ("Failed to parse DNS response\n"));
933  return;
934  }
935 
936  /* We got a result from DNS */
938  "Received DNS response for `%s' with %u answers\n",
939  rh->ac_tail->label,
940  (unsigned int) p->num_answers);
941  if ((p->num_answers > 0) &&
944  {
945  int af;
946 
948  "Got CNAME `%s' from DNS for `%s'\n",
949  p->answers[0].data.hostname,
950  rh->name);
951  if (NULL != rh->std_resolve)
952  {
954  "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
955  rh->name);
957  }
958  GNUNET_free (rh->name);
959  rh->name = GNUNET_strdup (p->answers[0].data.hostname);
960  rh->name_resolution_pos = strlen (rh->name);
961  switch (rh->record_type)
962  {
964  af = AF_INET;
965  break;
966 
968  af = AF_INET6;
969  break;
970 
971  default:
972  af = AF_UNSPEC;
973  break;
974  }
975  if (NULL != rh->leho)
976  add_dns_result (rh,
977  GNUNET_TIME_UNIT_HOURS.rel_value_us,
979  strlen (rh->leho),
980  rh->leho);
982  af,
985  rh);
988  rh->dns_request = NULL;
989  return;
990  }
991 
992  /* convert from (parsed) DNS to (binary) GNS format! */
993  rd_count = p->num_answers + p->num_authority_records
995  {
996  struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
997  int skip;
998  char buf[UINT16_MAX];
999  size_t buf_off;
1000  size_t buf_start;
1001 
1002  buf_off = 0;
1003  skip = 0;
1004  memset (rd,
1005  0,
1006  sizeof(rd));
1007  for (unsigned int i = 0; i < rd_count; i++)
1008  {
1009  if (i < p->num_answers)
1010  rec = &p->answers[i];
1011  else if (i < p->num_answers + p->num_authority_records)
1012  rec = &p->authority_records[i - p->num_answers];
1013  else
1014  rec = &p->additional_records[i - p->num_answers
1015  - p->num_authority_records];
1016  /* As we copied the full DNS name to 'rh->ac_tail->label', this
1017  should be the correct check to see if this record is actually
1018  a record for our label... */
1019  if (0 != strcmp (rec->name,
1020  rh->ac_tail->label))
1021  {
1023  "Dropping record `%s', does not match desired name `%s'\n",
1024  rec->name,
1025  rh->ac_tail->label);
1026  skip++;
1027  continue;
1028  }
1029  rd[i - skip].record_type = rec->type;
1030  rd[i - skip].expiration_time = rec->expiration_time.abs_value_us;
1031  switch (rec->type)
1032  {
1034  if (rec->data.raw.data_len != sizeof(struct in_addr))
1035  {
1036  GNUNET_break_op (0);
1037  skip++;
1038  continue;
1039  }
1040  rd[i - skip].data_size = rec->data.raw.data_len;
1041  rd[i - skip].data = rec->data.raw.data;
1042  break;
1043 
1045  if (rec->data.raw.data_len != sizeof(struct in6_addr))
1046  {
1047  GNUNET_break_op (0);
1048  skip++;
1049  continue;
1050  }
1051  rd[i - skip].data_size = rec->data.raw.data_len;
1052  rd[i - skip].data = rec->data.raw.data;
1053  break;
1054 
1058  buf_start = buf_off;
1059  if (GNUNET_OK !=
1061  sizeof(buf),
1062  &buf_off,
1063  rec->data.hostname))
1064  {
1065  GNUNET_break (0);
1066  skip++;
1067  continue;
1068  }
1069  rd[i - skip].data_size = buf_off - buf_start;
1070  rd[i - skip].data = &buf[buf_start];
1071  break;
1072 
1074  buf_start = buf_off;
1075  if (GNUNET_OK !=
1077  sizeof(buf),
1078  &buf_off,
1079  rec->data.soa))
1080  {
1081  GNUNET_break (0);
1082  skip++;
1083  continue;
1084  }
1085  rd[i - skip].data_size = buf_off - buf_start;
1086  rd[i - skip].data = &buf[buf_start];
1087  break;
1088 
1090  buf_start = buf_off;
1091  if (GNUNET_OK !=
1093  sizeof(buf),
1094  &buf_off,
1095  rec->data.mx))
1096  {
1097  GNUNET_break (0);
1098  skip++;
1099  continue;
1100  }
1101  rd[i - skip].data_size = buf_off - buf_start;
1102  rd[i - skip].data = &buf[buf_start];
1103  break;
1104 
1106  buf_start = buf_off;
1107  if (GNUNET_OK !=
1109  sizeof(buf),
1110  &buf_off,
1111  rec->data.srv))
1112  {
1113  GNUNET_break (0);
1114  skip++;
1115  continue;
1116  }
1117  rd[i - skip].data_size = buf_off - buf_start;
1118  rd[i - skip].data = &buf[buf_start];
1119  break;
1120 
1121  default:
1123  _ ("Skipping record of unsupported type %d\n"),
1124  rec->type);
1125  skip++;
1126  continue;
1127  }
1128  } /* end of for all records in answer */
1129  if (NULL != rh->leho)
1130  {
1131  rd[rd_count - skip].record_type = GNUNET_GNSRECORD_TYPE_LEHO;
1132  rd[rd_count - skip].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1133  rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1134  rd[rd_count - skip].data = rh->leho;
1135  rd[rd_count - skip].data_size = strlen (rh->leho);
1136  skip--; /* skip one LESS */
1138  "Adding LEHO %s\n",
1139  rh->leho);
1140  }
1142  "Returning DNS response for `%s' with %u answers\n",
1143  rh->ac_tail->label,
1144  (unsigned int) (rd_count - skip));
1145  rh->proc (rh->proc_cls,
1146  rd_count - skip,
1147  rd);
1149  rh->dns_request = NULL;
1150  }
1152  if (NULL != rh->task_id)
1153  GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1155  rh);
1156 }
1157 
1158 
1167 static void
1169 {
1170  struct AuthorityChain *ac;
1171  struct GNUNET_DNSPARSER_Query *query;
1172  struct GNUNET_DNSPARSER_Packet *p;
1173  char *dns_request;
1174  size_t dns_request_length;
1175  int ret;
1176 
1177  ac = rh->ac_tail;
1178  GNUNET_assert (NULL != ac);
1180  "Starting DNS lookup for `%s'\n",
1181  ac->label);
1183  query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1184  query->name = GNUNET_strdup (ac->label);
1185  query->type = rh->record_type;
1187  p = GNUNET_new (struct GNUNET_DNSPARSER_Packet);
1188  p->queries = query;
1189  p->num_queries = 1;
1191  UINT16_MAX);
1193  p->flags.recursion_desired = 1;
1194  ret = GNUNET_DNSPARSER_pack (p,
1195  1024,
1196  &dns_request,
1197  &dns_request_length);
1198  if (GNUNET_OK != ret)
1199  {
1200  GNUNET_break (0);
1201  rh->proc (rh->proc_cls,
1202  0,
1203  NULL);
1204  GNUNET_assert (NULL == rh->task_id);
1206  rh);
1207  }
1208  else
1209  {
1210  rh->original_dns_id = p->id;
1211  GNUNET_assert (NULL != ac->authority_info.dns_authority.dns_handle);
1212  GNUNET_assert (NULL == rh->dns_request);
1213  rh->leho = GNUNET_strdup (ac->label);
1215  ac->authority_info.dns_authority.dns_handle,
1216  dns_request,
1217  dns_request_length,
1219  rh);
1222  rh);
1223  }
1224  if (GNUNET_SYSERR != ret)
1225  GNUNET_free (dns_request);
1227 }
1228 
1229 
1238 static void
1240  const char *cname)
1241 {
1242  size_t nlen;
1243  char *res;
1244  const char *tld;
1245  struct AuthorityChain *ac;
1246  int af;
1247  struct GNUNET_CRYPTO_EcdsaPublicKey zone;
1248 
1249  nlen = strlen (cname);
1250  tld = GNS_get_tld (cname);
1251  if (0 == strcmp ("+", tld))
1252  {
1253  /* CNAME resolution continues relative to current domain */
1254  if (0 == rh->name_resolution_pos)
1255  {
1256  res = GNUNET_strndup (cname, nlen - 2);
1257  rh->name_resolution_pos = nlen - 2;
1258  }
1259  else
1260  {
1261  GNUNET_asprintf (&res,
1262  "%.*s.%.*s",
1263  (int) rh->name_resolution_pos,
1264  rh->name,
1265  (int) (nlen - 2),
1266  cname);
1267  rh->name_resolution_pos = strlen (res);
1268  }
1269  GNUNET_free (rh->name);
1270  rh->name = res;
1271  ac = GNUNET_new (struct AuthorityChain);
1272  ac->rh = rh;
1273  ac->gns_authority = GNUNET_YES;
1277  /* add AC to tail */
1279  rh->ac_tail,
1280  ac);
1282  rh);
1283  return;
1284  }
1285  if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1286  {
1287  /* CNAME resolution continues relative to current domain */
1288  if (0 == rh->name_resolution_pos)
1289  {
1290  GNUNET_asprintf (&res,
1291  "%.*s",
1292  strlen (cname) - (strlen (tld) + 1),
1293  cname);
1294  }
1295  else
1296  {
1297  GNUNET_asprintf (&res,
1298  "%.*s.%.*s",
1299  (int) rh->name_resolution_pos,
1300  rh->name,
1301  (int) strlen (cname) - (strlen (tld) + 1),
1302  cname);
1303  }
1304  rh->name_resolution_pos = strlen (res);
1305  GNUNET_free (rh->name);
1306  rh->name = res;
1307  ac = GNUNET_new (struct AuthorityChain);
1308  ac->rh = rh;
1309  ac->gns_authority = GNUNET_YES;
1312  /* add AC to tail */
1314  rh->ac_tail,
1315  ac);
1317  rh);
1318  return;
1319  }
1320 
1322  "Got CNAME `%s' from GNS for `%s'\n",
1323  cname,
1324  rh->name);
1325  if (NULL != rh->std_resolve)
1326  {
1328  "Multiple CNAME results from GNS resolving `%s'! Not really allowed...\n",
1329  rh->name);
1331  }
1332  /* name is absolute, go to DNS */
1333  GNUNET_free (rh->name);
1334  rh->name = GNUNET_strdup (cname);
1335  rh->name_resolution_pos = strlen (rh->name);
1336  switch (rh->record_type)
1337  {
1339  af = AF_INET;
1340  break;
1341 
1343  af = AF_INET6;
1344  break;
1345 
1346  default:
1347  af = AF_UNSPEC;
1348  break;
1349  }
1351  "Doing standard DNS lookup for `%s'\n",
1352  rh->name);
1354  af,
1357  rh);
1358 }
1359 
1360 
1368 static void
1369 handle_gns_resolution_result (void *cls,
1370  unsigned int rd_count,
1371  const struct GNUNET_GNSRECORD_Data *rd);
1372 
1373 
1388 static void
1390  int af,
1391  const void *address)
1392 {
1393  struct VpnContext *vpn_ctx = cls;
1394  struct GNS_ResolverHandle *rh = vpn_ctx->rh;
1395  struct GNUNET_GNSRECORD_Data rd[vpn_ctx->rd_count];
1396  unsigned int i;
1397 
1398  vpn_ctx->vpn_request = NULL;
1399  rh->vpn_ctx = NULL;
1402  (size_t) vpn_ctx->rd_data_size,
1403  vpn_ctx->rd_data,
1404  vpn_ctx->rd_count,
1405  rd));
1406  for (i = 0; i < vpn_ctx->rd_count; i++)
1407  {
1409  {
1410  switch (af)
1411  {
1412  case AF_INET:
1414  rd[i].data_size = sizeof(struct in_addr);
1417  rd[i].flags = 0;
1418  rd[i].data = address;
1419  break;
1420 
1421  case AF_INET6:
1425  rd[i].flags = 0;
1426  rd[i].data = address;
1427  rd[i].data_size = sizeof(struct in6_addr);
1428  break;
1429 
1430  default:
1431  GNUNET_assert (0);
1432  }
1433  break;
1434  }
1435  }
1436  GNUNET_assert (i < vpn_ctx->rd_count);
1437  if (0 == vpn_ctx->rd_count)
1439  _ ("VPN returned empty result for `%s'\n"),
1440  rh->name);
1442  vpn_ctx->rd_count,
1443  rd);
1444  GNUNET_free (vpn_ctx->rd_data);
1445  GNUNET_free (vpn_ctx);
1446 }
1447 
1448 
1456 static void
1458 {
1459  struct GNS_ResolverHandle *rh = ac->rh;
1460 
1461  if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1462  (GNUNET_NO == ac->authority_info.dns_authority.found))
1463  return; /* more pending and none found yet */
1464  if (GNUNET_NO == ac->authority_info.dns_authority.found)
1465  {
1467  "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1468  ac->authority_info.dns_authority.name);
1469  fail_resolution (rh);
1470  return;
1471  }
1472  if (GNUNET_NO != ac->authority_info.dns_authority.launched)
1473  return; /* already running, do not launch again! */
1474  /* recurse */
1475  ac->authority_info.dns_authority.launched = GNUNET_YES;
1477  "Will continue resolution using DNS to resolve `%s'\n",
1478  ac->label);
1479  GNUNET_assert (NULL == rh->task_id);
1481  rh);
1482 }
1483 
1484 
1493 static void
1495  unsigned int rd_count,
1496  const struct GNUNET_GNSRECORD_Data *rd)
1497 {
1498  struct Gns2DnsPending *gp = cls;
1499  struct AuthorityChain *ac = gp->ac;
1500 
1502  ac->authority_info.dns_authority.gp_tail,
1503  gp);
1504  /* enable cleanup of 'rh' handle that automatically comes after we return,
1505  and which expects 'rh' to be in the #rlh_head DLL. */
1506  if (NULL != gp->rh)
1507  {
1508  GNUNET_CONTAINER_DLL_insert (rlh_head,
1509  rlh_tail,
1510  gp->rh);
1511  gp->rh = NULL;
1512  }
1513  GNUNET_free (gp);
1515  "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1516  rd_count);
1517  /* find suitable A/AAAA record */
1518  for (unsigned int j = 0; j < rd_count; j++)
1519  {
1520  switch (rd[j].record_type)
1521  {
1523  {
1524  struct sockaddr_in v4;
1525 
1526  if (sizeof(struct in_addr) != rd[j].data_size)
1527  {
1528  GNUNET_break_op (0);
1529  continue;
1530  }
1531  memset (&v4,
1532  0,
1533  sizeof(v4));
1534  v4.sin_family = AF_INET;
1535  v4.sin_port = htons (53);
1536 #if HAVE_SOCKADDR_IN_SIN_LEN
1537  v4.sin_len = (u_char) sizeof(v4);
1538 #endif
1539  GNUNET_memcpy (&v4.sin_addr,
1540  rd[j].data,
1541  sizeof(struct in_addr));
1542  if (GNUNET_OK ==
1544  ac->authority_info.dns_authority.dns_handle,
1545  (const struct sockaddr *) &v4))
1547  break;
1548  }
1549 
1551  {
1552  struct sockaddr_in6 v6;
1553 
1554  if (sizeof(struct in6_addr) != rd[j].data_size)
1555  {
1556  GNUNET_break_op (0);
1557  continue;
1558  }
1559  /* FIXME: might want to check if we support IPv6 here,
1560  and otherwise skip this one and hope we find another */
1561  memset (&v6,
1562  0,
1563  sizeof(v6));
1564  v6.sin6_family = AF_INET6;
1565  v6.sin6_port = htons (53);
1566 #if HAVE_SOCKADDR_IN_SIN_LEN
1567  v6.sin6_len = (u_char) sizeof(v6);
1568 #endif
1569  GNUNET_memcpy (&v6.sin6_addr,
1570  rd[j].data,
1571  sizeof(struct in6_addr));
1572  if (GNUNET_OK ==
1574  ac->authority_info.dns_authority.dns_handle,
1575  (const struct sockaddr *) &v6))
1577  break;
1578  }
1579 
1580  default:
1581  break;
1582  }
1583  }
1584  continue_with_gns2dns (ac);
1585 }
1586 
1587 
1595 static void
1597  const struct sockaddr *addr,
1598  socklen_t addrlen)
1599 {
1600  struct Gns2DnsPending *gp = cls;
1601  struct AuthorityChain *ac = gp->ac;
1602  struct sockaddr_storage ss;
1603  struct sockaddr_in *v4;
1604  struct sockaddr_in6 *v6;
1605 
1606  if (NULL == addr)
1607  {
1608  /* DNS resolution finished */
1609  if (0 == gp->num_results)
1611  "Failed to use DNS to resolve name of DNS resolver\n");
1613  ac->authority_info.dns_authority.gp_tail,
1614  gp);
1615  GNUNET_free (gp);
1616  continue_with_gns2dns (ac);
1617  return;
1618  }
1619  GNUNET_memcpy (&ss,
1620  addr,
1621  addrlen);
1622  switch (ss.ss_family)
1623  {
1624  case AF_INET:
1625  v4 = (struct sockaddr_in *) &ss;
1626  v4->sin_port = htons (53);
1627  gp->num_results++;
1628  break;
1629 
1630  case AF_INET6:
1631  v6 = (struct sockaddr_in6 *) &ss;
1632  v6->sin6_port = htons (53);
1633  gp->num_results++;
1634  break;
1635 
1636  default:
1638  "Unsupported AF %d\n",
1639  ss.ss_family);
1640  return;
1641  }
1642  if (GNUNET_OK ==
1644  (struct sockaddr *) &ss))
1646 }
1647 
1648 
1655 static void
1657  const struct GNUNET_GNSRECORD_Data *rd)
1658 {
1659  char *cname;
1660  size_t off;
1661 
1662  off = 0;
1663  cname = GNUNET_DNSPARSER_parse_name (rd->data,
1664  rd->data_size,
1665  &off);
1666  if ((NULL == cname) ||
1667  (off != rd->data_size))
1668  {
1669  GNUNET_break_op (0); /* record not well-formed */
1670  GNUNET_free_non_null (cname);
1671  fail_resolution (rh);
1672  return;
1673  }
1675  cname);
1676  GNUNET_free (cname);
1677 }
1678 
1679 
1686 static void
1688  const struct GNUNET_GNSRECORD_Data *rd)
1689 {
1690  struct AuthorityChain *ac;
1691 
1692  /* delegation to another zone */
1693  if (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) !=
1694  rd->data_size)
1695  {
1696  GNUNET_break_op (0);
1697  fail_resolution (rh);
1698  return;
1699  }
1700  /* expand authority chain */
1701  ac = GNUNET_new (struct AuthorityChain);
1702  ac->rh = rh;
1703  ac->gns_authority = GNUNET_YES;
1705  rd->data,
1706  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
1708  /* add AC to tail */
1710  rh->ac_tail,
1711  ac);
1712  /* recurse */
1714  rh);
1715 }
1716 
1717 
1728 static int
1730  unsigned int rd_count,
1731  const struct GNUNET_GNSRECORD_Data *rd)
1732 {
1733  struct AuthorityChain *ac;
1734  const char *tld;
1735  char *ns;
1736 
1737  ns = NULL;
1738  /* expand authority chain */
1739  ac = GNUNET_new (struct AuthorityChain);
1740  ac->rh = rh;
1741  ac->authority_info.dns_authority.dns_handle = GNUNET_DNSSTUB_start (4);
1742 
1743  for (unsigned int i = 0; i < rd_count; i++)
1744  {
1745  char *ip;
1746  char *n;
1747  size_t off;
1748  struct Gns2DnsPending *gp;
1749  struct GNUNET_CRYPTO_EcdsaPublicKey zone;
1750  struct sockaddr_in v4;
1751  struct sockaddr_in6 v6;
1752 
1753  if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1754  continue;
1755  off = 0;
1756  n = GNUNET_DNSPARSER_parse_name (rd[i].data,
1757  rd[i].data_size,
1758  &off);
1759  ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1760  off += strlen (ip) + 1;
1761 
1762  if ((NULL == n) ||
1763  (NULL == ip) ||
1764  (off != rd[i].data_size))
1765  {
1766  GNUNET_break_op (0);
1768  GNUNET_free_non_null (ip);
1769  continue;
1770  }
1771  /* resolve 'ip' to determine the IP(s) of the DNS
1772  resolver to use for lookup of 'ns' */
1773  if (NULL != ns)
1774  {
1775  if (0 != strcasecmp (ns,
1776  n))
1777  {
1778  /* NS values must all be the same for all GNS2DNS records,
1779  anything else leads to insanity */
1780  GNUNET_break_op (0);
1781  GNUNET_free (n);
1782  GNUNET_free (ip);
1783  continue;
1784  }
1785  GNUNET_free (n);
1786  }
1787  else
1788  {
1789  ns = n;
1790  }
1791 
1792  /* check if 'ip' is already an IPv4/IPv6 address */
1793  if ((1 == inet_pton (AF_INET,
1794  ip,
1795  &v4)) ||
1796  (1 == inet_pton (AF_INET6,
1797  ip,
1798  &v6)))
1799  {
1802  ac->authority_info.dns_authority.dns_handle,
1803  ip));
1805  GNUNET_free (ip);
1806  continue;
1807  }
1808  tld = GNS_get_tld (ip);
1809  if ((0 != strcmp (tld, "+")) &&
1810  (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1811  {
1812  /* 'ip' is a DNS name */
1813  gp = GNUNET_new (struct Gns2DnsPending);
1814  gp->ac = ac;
1816  ac->authority_info.dns_authority.gp_tail,
1817  gp);
1818  gp->dns_rh = GNUNET_RESOLVER_ip_get (ip,
1819  AF_UNSPEC,
1822  gp);
1823  GNUNET_free (ip);
1824  continue;
1825  }
1826  /* 'ip' should be a GNS name */
1827  gp = GNUNET_new (struct Gns2DnsPending);
1828  gp->ac = ac;
1830  ac->authority_info.dns_authority.gp_tail,
1831  gp);
1832  gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1833  if (0 == strcmp (tld, "+"))
1834  {
1835  ip = translate_dot_plus (rh,
1836  ip);
1837  tld = GNS_get_tld (ip);
1838  if (GNUNET_OK !=
1840  &zone))
1841  {
1842  GNUNET_break_op (0);
1843  GNUNET_free (ip);
1844  continue;
1845  }
1846  }
1847  gp->rh->authority_zone = zone;
1849  "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1850  ip,
1851  ns);
1852  gp->rh->name = ip;
1853  gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1854  gp->rh->proc = &handle_gns2dns_result;
1855  gp->rh->proc_cls = gp;
1858  gp->rh->loop_limiter = rh->loop_limiter + 1;
1859  gp->rh->loop_threshold = rh->loop_threshold;
1860  gp->rh->task_id
1862  gp->rh);
1863  } /* end 'for all records' */
1864 
1865  if (NULL == ns)
1866  {
1867  /* not a single GNS2DNS record found */
1868  GNUNET_free (ac);
1869  return GNUNET_SYSERR;
1870  }
1872  strcpy (ac->authority_info.dns_authority.name,
1873  ns);
1874  /* for DNS recursion, the label is the full DNS name,
1875  created from the remainder of the GNS name and the
1876  name in the NS record */
1877  GNUNET_asprintf (&ac->label,
1878  "%.*s%s%s",
1879  (int) rh->name_resolution_pos,
1880  rh->name,
1881  (0 != rh->name_resolution_pos) ? "." : "",
1882  ns);
1883  GNUNET_free (ns);
1884 
1885  {
1886  /* the GNS name is UTF-8 and may include multibyte chars.
1887  * We have to convert the combined name to a DNS-compatible IDNA.
1888  */
1889  char *tmp = ac->label;
1890 
1891  if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1892  &ac->label,
1893  IDNA_ALLOW_UNASSIGNED))
1894  {
1896  _ ("Name `%s' cannot be converted to IDNA."),
1897  tmp);
1898  return GNUNET_SYSERR;
1899  }
1900  GNUNET_free (tmp);
1901  }
1902 
1904  rh->ac_tail,
1905  ac);
1906  if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1907  {
1909  _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1910  ac->label);
1911  return GNUNET_SYSERR;
1912  }
1913  continue_with_gns2dns (ac);
1914  return GNUNET_OK;
1915 }
1916 
1917 
1925 static void
1927  unsigned int rd_count,
1928  const struct GNUNET_GNSRECORD_Data *rd)
1929 {
1930  struct GNS_ResolverHandle *rh = cls;
1931  char *cname;
1932  struct VpnContext *vpn_ctx;
1933  const struct GNUNET_TUN_GnsVpnRecord *vpn;
1934  const char *vname;
1935  struct GNUNET_HashCode vhash;
1936  int af;
1937  char scratch[UINT16_MAX];
1938  size_t scratch_off;
1939  size_t scratch_start;
1940  size_t off;
1941  struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1942  unsigned int rd_off;
1943 
1945  "Resolution succeeded for `%s' in zone %s, got %u records\n",
1946  rh->ac_tail->label,
1948  rd_count);
1949  if (0 == rd_count)
1950  {
1952  _ ("GNS lookup failed (zero records found for `%s')\n"),
1953  rh->name);
1954  fail_resolution (rh);
1955  return;
1956  }
1957 
1958  if (0 == rh->name_resolution_pos)
1959  {
1960  /* top-level match, are we done yet? */
1961  if ((rd_count > 0) &&
1964  {
1965  off = 0;
1966  cname = GNUNET_DNSPARSER_parse_name (rd[0].data,
1967  rd[0].data_size,
1968  &off);
1969  if ((NULL == cname) ||
1970  (off != rd[0].data_size))
1971  {
1972  GNUNET_break_op (0);
1973  GNUNET_free_non_null (cname);
1974  fail_resolution (rh);
1975  return;
1976  }
1978  cname);
1979  GNUNET_free (cname);
1980  return;
1981  }
1982  /* If A/AAAA was requested, but we got a VPN
1983  record, we convert it to A/AAAA using GNUnet VPN */
1984  if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
1986  {
1987  for (unsigned int i = 0; i < rd_count; i++)
1988  {
1989  switch (rd[i].record_type)
1990  {
1992  {
1993  af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET :
1994  AF_INET6;
1995  if (sizeof(struct GNUNET_TUN_GnsVpnRecord) >
1996  rd[i].data_size)
1997  {
1998  GNUNET_break_op (0);
1999  fail_resolution (rh);
2000  return;
2001  }
2002  vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
2003  vname = (const char *) &vpn[1];
2004  if ('\0' != vname[rd[i].data_size - 1 - sizeof(struct
2006  ])
2007  {
2008  GNUNET_break_op (0);
2009  fail_resolution (rh);
2010  return;
2011  }
2013  &vhash);
2015  "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n",
2016  GNUNET_i2s (&vpn->peer),
2017  vname,
2018  (int) af,
2019  (int) ntohs (vpn->proto));
2020  vpn_ctx = GNUNET_new (struct VpnContext);
2021  rh->vpn_ctx = vpn_ctx;
2022  vpn_ctx->rh = rh;
2023  vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
2024  rd);
2025  if (vpn_ctx->rd_data_size < 0)
2026  {
2027  GNUNET_break_op (0);
2028  GNUNET_free (vpn_ctx);
2029  fail_resolution (rh);
2030  return;
2031  }
2032  vpn_ctx->rd_data = GNUNET_malloc ((size_t) vpn_ctx->rd_data_size);
2033  vpn_ctx->rd_count = rd_count;
2034  GNUNET_assert (vpn_ctx->rd_data_size ==
2036  rd,
2037  (size_t) vpn_ctx
2038  ->rd_data_size,
2039  vpn_ctx->rd_data));
2040  vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
2041  af,
2042  ntohs (
2043  vpn->proto),
2044  &vpn->peer,
2045  &vhash,
2047  VPN_TIMEOUT),
2048  &
2050  vpn_ctx);
2051  return;
2052  }
2053 
2055  {
2056  /* delegation to DNS */
2058  "Found GNS2DNS record, delegating to DNS!\n");
2059  if (GNUNET_OK ==
2061  rd_count,
2062  rd))
2063  return;
2064  else
2065  goto fail;
2066  }
2067 
2068  default:
2069  break;
2070  } /* end: switch */
2071  } /* end: for rd */
2072  } /* end: name_resolution_pos */
2073  /* convert relative names in record values to absolute names,
2074  using 'scratch' array for memory allocations */
2075  scratch_off = 0;
2076  rd_off = 0;
2077  for (unsigned int i = 0; i < rd_count; i++)
2078  {
2079  GNUNET_assert (rd_off <= i);
2080  if ((0 != rh->protocol) &&
2081  (0 != rh->service) &&
2083  continue; /* we _only_ care about boxed records */
2084 
2085  GNUNET_assert (rd_off < rd_count);
2086  rd_new[rd_off] = rd[i];
2087  /* Check if the embedded name(s) end in "+", and if so,
2088  replace the "+" with the zone at "ac_tail", changing the name
2089  to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2090  so we can free it afterwards. */
2091  switch (rd[i].record_type)
2092  {
2094  {
2095  char *cname;
2096 
2097  off = 0;
2098  cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
2099  rd[i].data_size,
2100  &off);
2101  if ((NULL == cname) ||
2102  (off != rd[i].data_size))
2103  {
2104  GNUNET_break_op (0); /* record not well-formed */
2105  }
2106  else
2107  {
2108  cname = translate_dot_plus (rh, cname);
2109  GNUNET_break (NULL != cname);
2110  scratch_start = scratch_off;
2111  if (GNUNET_OK !=
2113  sizeof(scratch),
2114  &scratch_off,
2115  cname))
2116  {
2117  GNUNET_break (0);
2118  }
2119  else
2120  {
2121  GNUNET_assert (rd_off < rd_count);
2122  rd_new[rd_off].data = &scratch[scratch_start];
2123  rd_new[rd_off].data_size = scratch_off - scratch_start;
2124  rd_off++;
2125  }
2126  }
2127  GNUNET_free_non_null (cname);
2128  }
2129  break;
2130 
2132  {
2133  struct GNUNET_DNSPARSER_SoaRecord *soa;
2134 
2135  off = 0;
2136  soa = GNUNET_DNSPARSER_parse_soa (rd[i].data,
2137  rd[i].data_size,
2138  &off);
2139  if ((NULL == soa) ||
2140  (off != rd[i].data_size))
2141  {
2142  GNUNET_break_op (0); /* record not well-formed */
2143  }
2144  else
2145  {
2146  soa->mname = translate_dot_plus (rh, soa->mname);
2147  soa->rname = translate_dot_plus (rh, soa->rname);
2148  scratch_start = scratch_off;
2149  if (GNUNET_OK !=
2151  sizeof(scratch),
2152  &scratch_off,
2153  soa))
2154  {
2155  GNUNET_break (0);
2156  }
2157  else
2158  {
2159  GNUNET_assert (rd_off < rd_count);
2160  rd_new[rd_off].data = &scratch[scratch_start];
2161  rd_new[rd_off].data_size = scratch_off - scratch_start;
2162  rd_off++;
2163  }
2164  }
2165  if (NULL != soa)
2167  }
2168  break;
2169 
2171  {
2172  struct GNUNET_DNSPARSER_MxRecord *mx;
2173 
2174  off = 0;
2175  mx = GNUNET_DNSPARSER_parse_mx (rd[i].data,
2176  rd[i].data_size,
2177  &off);
2178  if ((NULL == mx) ||
2179  (off != rd[i].data_size))
2180  {
2181  GNUNET_break_op (0); /* record not well-formed */
2182  }
2183  else
2184  {
2185  mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2186  scratch_start = scratch_off;
2187  if (GNUNET_OK !=
2189  sizeof(scratch),
2190  &scratch_off,
2191  mx))
2192  {
2193  GNUNET_break (0);
2194  }
2195  else
2196  {
2197  GNUNET_assert (rd_off < rd_count);
2198  rd_new[rd_off].data = &scratch[scratch_start];
2199  rd_new[rd_off].data_size = scratch_off - scratch_start;
2200  rd_off++;
2201  }
2202  }
2203  if (NULL != mx)
2205  }
2206  break;
2207 
2209  {
2210  struct GNUNET_DNSPARSER_SrvRecord *srv;
2211 
2212  off = 0;
2213  srv = GNUNET_DNSPARSER_parse_srv (rd[i].data,
2214  rd[i].data_size,
2215  &off);
2216  if ((NULL == srv) ||
2217  (off != rd[i].data_size))
2218  {
2219  GNUNET_break_op (0); /* record not well-formed */
2220  }
2221  else
2222  {
2223  srv->target = translate_dot_plus (rh, srv->target);
2224  scratch_start = scratch_off;
2225  if (GNUNET_OK !=
2227  sizeof(scratch),
2228  &scratch_off,
2229  srv))
2230  {
2231  GNUNET_break (0);
2232  }
2233  else
2234  {
2235  GNUNET_assert (rd_off < rd_count);
2236  rd_new[rd_off].data = &scratch[scratch_start];
2237  rd_new[rd_off].data_size = scratch_off - scratch_start;
2238  rd_off++;
2239  }
2240  }
2241  if (NULL != srv)
2243  }
2244  break;
2245 
2247  {
2248  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
2249 
2250  if (rd[i].data_size != sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))
2251  {
2252  GNUNET_break_op (0);
2253  break;
2254  }
2255  GNUNET_memcpy (&pub,
2256  rd[i].data,
2257  rd[i].data_size);
2258  rd_off++;
2260  {
2261  /* try to resolve "@" */
2262  struct AuthorityChain *ac;
2263 
2264  ac = GNUNET_new (struct AuthorityChain);
2265  ac->rh = rh;
2266  ac->gns_authority = GNUNET_YES;
2270  rh->ac_tail,
2271  ac);
2273  rh);
2274  return;
2275  }
2276  }
2277  break;
2278 
2280  {
2281  /* delegation to DNS */
2283  {
2284  rd_off++;
2285  break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2286  }
2288  "Found GNS2DNS record, delegating to DNS!\n");
2289  if (GNUNET_OK ==
2291  rd_count,
2292  rd))
2293  return;
2294  else
2295  goto fail;
2296  }
2297 
2299  {
2300  /* unbox SRV/TLSA records if a specific one was requested */
2301  if ((0 != rh->protocol) &&
2302  (0 != rh->service) &&
2303  (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2304  {
2305  const struct GNUNET_GNSRECORD_BoxRecord *box;
2306 
2307  box = rd[i].data;
2308  if ((ntohs (box->protocol) == rh->protocol) &&
2309  (ntohs (box->service) == rh->service))
2310  {
2311  /* Box matches, unbox! */
2312  GNUNET_assert (rd_off < rd_count);
2313  rd_new[rd_off].record_type = ntohl (box->record_type);
2314  rd_new[rd_off].data_size -= sizeof(struct
2316  rd_new[rd_off].data = &box[1];
2317  rd_off++;
2318  }
2319  }
2320  else
2321  {
2322  /* no specific protocol/service specified, preserve all BOX
2323  records (for modern, GNS-enabled applications) */
2324  rd_off++;
2325  }
2326  break;
2327  }
2328 
2329  default:
2330  rd_off++;
2331  break;
2332  } /* end: switch */
2333  } /* end: for rd_count */
2334 
2335  /* yes, we are done, return result */
2337  "Returning GNS response for `%s' with %u answers\n",
2338  rh->ac_tail->label,
2339  rd_off);
2340  rh->proc (rh->proc_cls,
2341  rd_off,
2342  rd_new);
2344  rh);
2345  return;
2346  }
2347 
2348  switch (rd[0].record_type)
2349  {
2351  GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2353  &rd[0]);
2354  return;
2355 
2357  GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2359  &rd[0]);
2360  return;
2361 
2362  default:
2363  if (GNUNET_OK ==
2365  rd_count,
2366  rd))
2367  return;
2368  break;
2369  }
2370 fail:
2372  _ ("GNS lookup recursion failed (no delegation record found)\n"));
2373  fail_resolution (rh);
2374 }
2375 
2376 
2385 static void
2387  int32_t success,
2388  const char *emsg)
2389 {
2390  struct CacheOps *co = cls;
2391 
2392  co->namecache_qe_cache = NULL;
2393  if (GNUNET_OK != success)
2395  _ ("Failed to cache GNS resolution: %s\n"),
2396  emsg);
2397  GNUNET_CONTAINER_DLL_remove (co_head,
2398  co_tail,
2399  co);
2400  GNUNET_free (co);
2401 }
2402 
2403 
2421 static void
2423  struct GNUNET_TIME_Absolute exp,
2424  const struct GNUNET_HashCode *key,
2425  const struct GNUNET_PeerIdentity *get_path,
2426  unsigned int get_path_length,
2427  const struct GNUNET_PeerIdentity *put_path,
2428  unsigned int put_path_length,
2429  enum GNUNET_BLOCK_Type type,
2430  size_t size,
2431  const void *data)
2432 {
2433  struct GNS_ResolverHandle *rh = cls;
2434  struct AuthorityChain *ac = rh->ac_tail;
2435  const struct GNUNET_GNSRECORD_Block *block;
2436  struct CacheOps *co;
2437 
2438  (void) exp;
2439  (void) key;
2440  (void) get_path;
2441  (void) get_path_length;
2442  (void) put_path;
2443  (void) put_path_length;
2444  (void) type;
2446  rh->get_handle = NULL;
2448  rh->dht_heap_node = NULL;
2450  "Handling response from the DHT\n");
2451  if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2452  {
2453  /* how did this pass DHT block validation!? */
2454  GNUNET_break (0);
2455  fail_resolution (rh);
2456  return;
2457  }
2458  block = data;
2459  if (size !=
2460  ntohl (block->purpose.size)
2461  + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)
2462  + sizeof(struct GNUNET_CRYPTO_EcdsaSignature))
2463  {
2464  /* how did this pass DHT block validation!? */
2465  GNUNET_break (0);
2466  fail_resolution (rh);
2467  return;
2468  }
2470  "Decrypting DHT block of size %u for `%s', expires %s\n",
2471  ntohl (block->purpose.size),
2472  rh->name,
2474  if (GNUNET_OK !=
2477  ac->label,
2479  rh))
2480  {
2481  GNUNET_break_op (0); /* block was ill-formed */
2482  fail_resolution (rh);
2483  return;
2484  }
2486  block->expiration_time)).
2487  rel_value_us)
2488  {
2490  "Received expired block from the DHT, will not cache it.\n");
2491  return;
2492  }
2493  if (GNUNET_YES == disable_cache)
2494  return;
2495  /* Cache well-formed blocks */
2497  "Caching response from the DHT in namecache\n");
2498  co = GNUNET_new (struct CacheOps);
2499  co->namecache_qe_cache = GNUNET_NAMECACHE_block_cache (namecache_handle,
2500  block,
2501  &
2503  co);
2504  GNUNET_CONTAINER_DLL_insert (co_head,
2505  co_tail,
2506  co);
2507 }
2508 
2509 
2516 static void
2518  const struct GNUNET_HashCode *query)
2519 {
2520  struct GNS_ResolverHandle *rx;
2521 
2522  GNUNET_assert (NULL == rh->get_handle);
2523  rh->get_handle = GNUNET_DHT_get_start (dht_handle,
2525  query,
2528  NULL, 0,
2529  &handle_dht_response, rh);
2530  rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
2531  rh,
2533  abs_value_us);
2534  if (GNUNET_CONTAINER_heap_get_size (dht_lookup_heap) >
2536  {
2537  /* fail longest-standing DHT request */
2538  rx = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
2539  rx->dht_heap_node = NULL;
2540  GNUNET_assert (NULL != rx);
2541  fail_resolution (rx);
2542  }
2543 }
2544 
2545 
2554 static void
2556  unsigned int rd_count,
2557  const struct GNUNET_GNSRECORD_Data *rd)
2558 {
2559  struct GNS_ResolverHandle *rh = cls;
2560 
2561  if (0 == rd_count)
2563  _ ("GNS namecache returned empty result for `%s'\n"),
2564  rh->name);
2566  rd_count,
2567  rd);
2568 }
2569 
2570 
2577 static void
2579  const struct GNUNET_GNSRECORD_Block *block)
2580 {
2581  struct GNS_ResolverHandle *rh = cls;
2582  struct AuthorityChain *ac = rh->ac_tail;
2583  const char *label = ac->label;
2584  const struct GNUNET_CRYPTO_EcdsaPublicKey *auth =
2586  struct GNUNET_HashCode query;
2587 
2588  GNUNET_assert (NULL != rh->namecache_qe);
2589  rh->namecache_qe = NULL;
2590  if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2591  ((GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2592  (ac != rh->ac_head))) &&
2593  ((NULL == block) ||
2595  block->expiration_time)).
2596  rel_value_us)))
2597  {
2598  /* namecache knows nothing; try DHT lookup */
2600  label,
2601  &query);
2603  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2604  ac->label,
2606  GNUNET_h2s (&query));
2607  start_dht_request (rh, &query);
2608  return;
2609  }
2610 
2611  if ((NULL == block) ||
2613  block->expiration_time)).
2614  rel_value_us))
2615  {
2616  /* DHT not permitted and no local result, fail */
2618  "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2619  ac->label,
2621  fail_resolution (rh);
2622  return;
2623  }
2625  "Received result from namecache for label `%s'\n",
2626  ac->label);
2627 
2628  if (GNUNET_OK !=
2630  auth,
2631  label,
2633  rh))
2634  {
2635  GNUNET_break_op (0); /* block was ill-formed */
2636  /* try DHT instead */
2638  label,
2639  &query);
2641  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2642  ac->label,
2644  GNUNET_h2s (&query));
2645  start_dht_request (rh, &query);
2646  return;
2647  }
2648 }
2649 
2650 
2656 static void
2658 {
2659  struct AuthorityChain *ac = rh->ac_tail;
2660  struct GNUNET_HashCode query;
2661 
2663  "Starting GNS resolution for `%s' in zone %s\n",
2664  ac->label,
2667  ac->label,
2668  &query);
2669  if (GNUNET_YES != disable_cache)
2670  {
2671  rh->namecache_qe
2672  = GNUNET_NAMECACHE_lookup_block (namecache_handle,
2673  &query,
2675  rh);
2676  GNUNET_assert (NULL != rh->namecache_qe);
2677  }
2678  else
2679  {
2680  start_dht_request (rh,
2681  &query);
2682  }
2683 }
2684 
2685 
2692 static void
2694  int is_valid)
2695 {
2696  struct GNS_ResolverHandle *rh = cls;
2697  struct AuthorityChain *ac = rh->ac_tail;
2698 
2699  rh->rev_check = NULL;
2700  if (GNUNET_YES != is_valid)
2701  {
2703  _ ("Zone %s was revoked, resolution fails\n"),
2705  fail_resolution (rh);
2706  return;
2707  }
2709 }
2710 
2711 
2717 static void
2719 {
2720  struct AuthorityChain *ac = rh->ac_tail;
2721 
2723  "Starting revocation check for zone %s\n",
2728  rh);
2729  GNUNET_assert (NULL != rh->rev_check);
2730 }
2731 
2732 
2738 static void
2740 {
2741  struct GNS_ResolverHandle *rh = cls;
2742 
2743  rh->task_id = NULL;
2744  if (rh->loop_threshold < rh->loop_limiter++)
2745  {
2747  "Encountered unbounded recursion resolving `%s'\n",
2748  rh->name);
2749  fail_resolution (rh);
2750  return;
2751  }
2752  if (GNUNET_YES == rh->ac_tail->gns_authority)
2754  else
2756 }
2757 
2758 
2765 static void
2767 {
2768  struct GNS_ResolverHandle *rh = cls;
2769  struct AuthorityChain *ac;
2770  struct in_addr v4;
2771  struct in6_addr v6;
2772 
2773  rh->task_id = NULL;
2774  if (1 == inet_pton (AF_INET,
2775  rh->name,
2776  &v4))
2777  {
2778  /* name is IPv4 address, pretend it's an A record */
2779  struct GNUNET_GNSRECORD_Data rd;
2780 
2781  rd.data = &v4;
2782  rd.data_size = sizeof(v4);
2783  rd.expiration_time = UINT64_MAX;
2785  rd.flags = 0;
2786  rh->proc (rh->proc_cls,
2787  1,
2788  &rd);
2789  GNUNET_assert (NULL == rh->task_id);
2791  rh);
2792  return;
2793  }
2794  if (1 == inet_pton (AF_INET6,
2795  rh->name,
2796  &v6))
2797  {
2798  /* name is IPv6 address, pretend it's an AAAA record */
2799  struct GNUNET_GNSRECORD_Data rd;
2800 
2801  rd.data = &v6;
2802  rd.data_size = sizeof(v6);
2803  rd.expiration_time = UINT64_MAX;
2805  rd.flags = 0;
2806  rh->proc (rh->proc_cls,
2807  1,
2808  &rd);
2809  GNUNET_assert (NULL == rh->task_id);
2811  rh);
2812  return;
2813  }
2814 
2815  ac = GNUNET_new (struct AuthorityChain);
2816  ac->rh = rh;
2818  if (NULL == ac->label)
2819  /* name was just the "TLD", so we default to label
2820  #GNUNET_GNS_EMPTY_LABEL_AT */
2822  ac->gns_authority = GNUNET_YES;
2825  rh->ac_tail,
2826  ac);
2828  rh);
2829 }
2830 
2831 
2846 struct GNS_ResolverHandle *
2848  uint32_t record_type,
2849  const char *name,
2851  uint16_t recursion_depth_limit,
2853  void *proc_cls)
2854 {
2855  struct GNS_ResolverHandle *rh;
2856 
2858  "Starting lookup for `%s'\n",
2859  name);
2860  rh = GNUNET_new (struct GNS_ResolverHandle);
2861  GNUNET_CONTAINER_DLL_insert (rlh_head,
2862  rlh_tail,
2863  rh);
2864  rh->authority_zone = *zone;
2865  rh->proc = proc;
2866  rh->proc_cls = proc_cls;
2867  rh->options = options;
2868  rh->record_type = record_type;
2869  rh->name = GNUNET_strdup (name);
2870  rh->name_resolution_pos = strlen (name);
2871  rh->loop_threshold = recursion_depth_limit;
2873  rh);
2874  return rh;
2875 }
2876 
2877 
2883 void
2885 {
2886  struct DnsResult *dr;
2887  struct AuthorityChain *ac;
2888  struct VpnContext *vpn_ctx;
2889 
2890  GNUNET_CONTAINER_DLL_remove (rlh_head,
2891  rlh_tail,
2892  rh);
2893  if (NULL != rh->dns_request)
2894  {
2896  rh->dns_request = NULL;
2897  }
2898  while (NULL != (ac = rh->ac_head))
2899  {
2901  rh->ac_tail,
2902  ac);
2903  if (GNUNET_NO == ac->gns_authority)
2904  {
2905  struct Gns2DnsPending *gp;
2906 
2907  while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2908  {
2910  ac->authority_info.dns_authority.gp_tail,
2911  gp);
2912  if (NULL != gp->rh)
2913  {
2914  /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2915  using GNS_resolver_lookup_cancel here, we need to
2916  add it first... */
2917  GNUNET_CONTAINER_DLL_insert (rlh_head,
2918  rlh_tail,
2919  gp->rh);
2920  GNUNET_assert (NULL == gp->rh->task_id);
2923  gp->rh);
2924  gp->rh = NULL;
2925  }
2926  if (NULL != gp->dns_rh)
2927  {
2929  gp->dns_rh = NULL;
2930  }
2931  GNUNET_free (gp);
2932  }
2934  }
2935  GNUNET_free (ac->label);
2936  GNUNET_free (ac);
2937  }
2938  if (NULL != rh->task_id)
2939  {
2941  rh->task_id = NULL;
2942  }
2943  if (NULL != rh->get_handle)
2944  {
2946  rh->get_handle = NULL;
2947  }
2948  if (NULL != rh->dht_heap_node)
2949  {
2951  rh->dht_heap_node = NULL;
2952  }
2953  if (NULL != (vpn_ctx = rh->vpn_ctx))
2954  {
2956  GNUNET_free (vpn_ctx->rd_data);
2957  GNUNET_free (vpn_ctx);
2958  }
2959  if (NULL != rh->namecache_qe)
2960  {
2962  rh->namecache_qe = NULL;
2963  }
2964  if (NULL != rh->rev_check)
2965  {
2967  rh->rev_check = NULL;
2968  }
2969  if (NULL != rh->std_resolve)
2970  {
2972  "Canceling standard DNS resolution\n");
2974  rh->std_resolve = NULL;
2975  }
2976  while (NULL != (dr = rh->dns_result_head))
2977  {
2979  rh->dns_result_tail,
2980  dr);
2981  GNUNET_free (dr);
2982  }
2983  GNUNET_free_non_null (rh->leho);
2984  GNUNET_free (rh->name);
2985  GNUNET_free (rh);
2986 }
2987 
2988 
2989 /* ***************** Resolver initialization ********************* */
2990 
2991 
3000 void
3002  struct GNUNET_DHT_Handle *dht,
3003  const struct GNUNET_CONFIGURATION_Handle *c,
3004  unsigned long long max_bg_queries)
3005 {
3006  cfg = c;
3007  namecache_handle = nc;
3008  dht_handle = dht;
3009  dht_lookup_heap =
3011  max_allowed_background_queries = max_bg_queries;
3013  "namecache",
3014  "DISABLE");
3015  if (GNUNET_YES == disable_cache)
3017  "Namecache disabled\n");
3018  vpn_handle = GNUNET_VPN_connect (cfg);
3019 }
3020 
3021 
3025 void
3027 {
3028  struct GNS_ResolverHandle *rh;
3029  struct CacheOps *co;
3030 
3031  /* abort active resolutions */
3032  while (NULL != (rh = rlh_head))
3033  {
3034  rh->proc (rh->proc_cls,
3035  0,
3036  NULL);
3038  }
3039  while (NULL != (co = co_head))
3040  {
3041  GNUNET_CONTAINER_DLL_remove (co_head,
3042  co_tail,
3043  co);
3045  GNUNET_free (co);
3046  }
3047  GNUNET_CONTAINER_heap_destroy (dht_lookup_heap);
3048  dht_lookup_heap = NULL;
3049  GNUNET_VPN_disconnect (vpn_handle);
3050  vpn_handle = NULL;
3051  dht_handle = NULL;
3052  namecache_handle = NULL;
3053 }
3054 
3055 
3056 /* 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
unsigned int loop_threshold
Maximum value of loop_limiter allowed by client.
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:86
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:83
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).
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:180
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:1271
#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:1298
#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 name 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:84
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.
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:84
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...
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_CRYPTO_EcdsaPublicKey *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_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:85
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 expiration time of the record is a relative time (not an absolute time).
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:756
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:974