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;
773  if (0 == pos->expiration_time)
774  {
776  rd[i].expiration_time = 0;
777  }
778  else
779  {
781  rd[i].expiration_time = pos->expiration_time;
782  }
783  i++;
784  }
785  GNUNET_assert (i == n);
787  "Transmitting standard DNS result with %u records\n",
788  n);
789  rh->proc (rh->proc_cls,
790  n,
791  rd);
792  }
794 }
795 
796 
806 static void
808  uint64_t expiration_time,
809  uint32_t record_type,
810  size_t data_size,
811  const void *data)
812 {
813  struct DnsResult *res;
814 
815  res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
817  res->data_size = data_size;
818  res->record_type = record_type;
819  res->data = &res[1];
820  GNUNET_memcpy (&res[1],
821  data,
822  data_size);
824  rh->dns_result_tail,
825  res);
826 }
827 
828 
837 static void
838 handle_dns_result (void *cls,
839  const struct sockaddr *addr,
840  socklen_t addrlen)
841 {
842  struct GNS_ResolverHandle *rh = cls;
843  const struct sockaddr_in *sa4;
844  const struct sockaddr_in6 *sa6;
845 
846  if (NULL == addr)
847  {
848  rh->std_resolve = NULL;
850  return;
851  }
853  "Received %u bytes of DNS IP data\n",
854  addrlen);
855  switch (addr->sa_family)
856  {
857  case AF_INET:
858  sa4 = (const struct sockaddr_in *) addr;
859  add_dns_result (rh,
860  0 /* expiration time is unknown */,
862  sizeof(struct in_addr),
863  &sa4->sin_addr);
864  break;
865 
866  case AF_INET6:
867  sa6 = (const struct sockaddr_in6 *) addr;
868  add_dns_result (rh,
869  0 /* expiration time is unknown */,
871  sizeof(struct in6_addr),
872  &sa6->sin6_addr);
873  break;
874 
875  default:
876  GNUNET_break (0);
877  break;
878  }
879 }
880 
881 
888 static void
889 recursive_resolution (void *cls);
890 
891 
898 static void
899 start_resolver_lookup (void *cls);
900 
901 
910 static void
911 dns_result_parser (void *cls,
912  const struct GNUNET_TUN_DnsHeader *dns,
913  size_t dns_len)
914 {
915  struct GNS_ResolverHandle *rh = cls;
916  struct GNUNET_DNSPARSER_Packet *p;
917  const struct GNUNET_DNSPARSER_Record *rec;
918  unsigned int rd_count;
919 
920  if (NULL == dns)
921  {
922  rh->dns_request = NULL;
924  rh->task_id = NULL;
925  fail_resolution (rh);
926  return;
927  }
928  if (rh->original_dns_id != dns->id)
929  {
930  /* DNS answer, but for another query */
931  return;
932  }
933  p = GNUNET_DNSPARSER_parse ((const char *) dns,
934  dns_len);
935  if (NULL == p)
936  {
938  _ ("Failed to parse DNS response\n"));
939  return;
940  }
941 
942  /* We got a result from DNS */
944  "Received DNS response for `%s' with %u answers\n",
945  rh->ac_tail->label,
946  (unsigned int) p->num_answers);
947  if ((p->num_answers > 0) &&
950  {
951  int af;
952 
954  "Got CNAME `%s' from DNS for `%s'\n",
955  p->answers[0].data.hostname,
956  rh->name);
957  if (NULL != rh->std_resolve)
958  {
960  "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
961  rh->name);
963  }
964  GNUNET_free (rh->name);
965  rh->name = GNUNET_strdup (p->answers[0].data.hostname);
966  rh->name_resolution_pos = strlen (rh->name);
967  switch (rh->record_type)
968  {
970  af = AF_INET;
971  break;
972 
974  af = AF_INET6;
975  break;
976 
977  default:
978  af = AF_UNSPEC;
979  break;
980  }
981  if (NULL != rh->leho)
982  add_dns_result (rh,
983  GNUNET_TIME_UNIT_HOURS.rel_value_us,
985  strlen (rh->leho),
986  rh->leho);
988  af,
991  rh);
994  rh->dns_request = NULL;
995  return;
996  }
997 
998  /* convert from (parsed) DNS to (binary) GNS format! */
999  rd_count = p->num_answers + p->num_authority_records
1001  {
1002  struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
1003  int skip;
1004  char buf[UINT16_MAX];
1005  size_t buf_off;
1006  size_t buf_start;
1007 
1008  buf_off = 0;
1009  skip = 0;
1010  memset (rd,
1011  0,
1012  sizeof(rd));
1013  for (unsigned int i = 0; i < rd_count; i++)
1014  {
1015  if (i < p->num_answers)
1016  rec = &p->answers[i];
1017  else if (i < p->num_answers + p->num_authority_records)
1018  rec = &p->authority_records[i - p->num_answers];
1019  else
1020  rec = &p->additional_records[i - p->num_answers
1021  - p->num_authority_records];
1022  /* As we copied the full DNS name to 'rh->ac_tail->label', this
1023  should be the correct check to see if this record is actually
1024  a record for our label... */
1025  if (0 != strcmp (rec->name,
1026  rh->ac_tail->label))
1027  {
1029  "Dropping record `%s', does not match desired name `%s'\n",
1030  rec->name,
1031  rh->ac_tail->label);
1032  skip++;
1033  continue;
1034  }
1035  rd[i - skip].record_type = rec->type;
1036  rd[i - skip].expiration_time = rec->expiration_time.abs_value_us;
1037  switch (rec->type)
1038  {
1040  if (rec->data.raw.data_len != sizeof(struct in_addr))
1041  {
1042  GNUNET_break_op (0);
1043  skip++;
1044  continue;
1045  }
1046  rd[i - skip].data_size = rec->data.raw.data_len;
1047  rd[i - skip].data = rec->data.raw.data;
1048  break;
1049 
1051  if (rec->data.raw.data_len != sizeof(struct in6_addr))
1052  {
1053  GNUNET_break_op (0);
1054  skip++;
1055  continue;
1056  }
1057  rd[i - skip].data_size = rec->data.raw.data_len;
1058  rd[i - skip].data = rec->data.raw.data;
1059  break;
1060 
1064  buf_start = buf_off;
1065  if (GNUNET_OK !=
1067  sizeof(buf),
1068  &buf_off,
1069  rec->data.hostname))
1070  {
1071  GNUNET_break (0);
1072  skip++;
1073  continue;
1074  }
1075  rd[i - skip].data_size = buf_off - buf_start;
1076  rd[i - skip].data = &buf[buf_start];
1077  break;
1078 
1080  buf_start = buf_off;
1081  if (GNUNET_OK !=
1083  sizeof(buf),
1084  &buf_off,
1085  rec->data.soa))
1086  {
1087  GNUNET_break (0);
1088  skip++;
1089  continue;
1090  }
1091  rd[i - skip].data_size = buf_off - buf_start;
1092  rd[i - skip].data = &buf[buf_start];
1093  break;
1094 
1096  buf_start = buf_off;
1097  if (GNUNET_OK !=
1099  sizeof(buf),
1100  &buf_off,
1101  rec->data.mx))
1102  {
1103  GNUNET_break (0);
1104  skip++;
1105  continue;
1106  }
1107  rd[i - skip].data_size = buf_off - buf_start;
1108  rd[i - skip].data = &buf[buf_start];
1109  break;
1110 
1112  buf_start = buf_off;
1113  if (GNUNET_OK !=
1115  sizeof(buf),
1116  &buf_off,
1117  rec->data.srv))
1118  {
1119  GNUNET_break (0);
1120  skip++;
1121  continue;
1122  }
1123  rd[i - skip].data_size = buf_off - buf_start;
1124  rd[i - skip].data = &buf[buf_start];
1125  break;
1126 
1127  default:
1129  _ ("Skipping record of unsupported type %d\n"),
1130  rec->type);
1131  skip++;
1132  continue;
1133  }
1134  } /* end of for all records in answer */
1135  if (NULL != rh->leho)
1136  {
1137  rd[rd_count - skip].record_type = GNUNET_GNSRECORD_TYPE_LEHO;
1138  rd[rd_count - skip].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1139  rd[rd_count - skip].flags |= GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
1140  rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1141  rd[rd_count - skip].data = rh->leho;
1142  rd[rd_count - skip].data_size = strlen (rh->leho);
1143  skip--; /* skip one LESS */
1145  "Adding LEHO %s\n",
1146  rh->leho);
1147  }
1149  "Returning DNS response for `%s' with %u answers\n",
1150  rh->ac_tail->label,
1151  (unsigned int) (rd_count - skip));
1152  rh->proc (rh->proc_cls,
1153  rd_count - skip,
1154  rd);
1156  rh->dns_request = NULL;
1157  }
1159  if (NULL != rh->task_id)
1160  GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1162  rh);
1163 }
1164 
1165 
1174 static void
1176 {
1177  struct AuthorityChain *ac;
1178  struct GNUNET_DNSPARSER_Query *query;
1179  struct GNUNET_DNSPARSER_Packet *p;
1180  char *dns_request;
1181  size_t dns_request_length;
1182  int ret;
1183 
1184  ac = rh->ac_tail;
1185  GNUNET_assert (NULL != ac);
1187  "Starting DNS lookup for `%s'\n",
1188  ac->label);
1190  query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1191  query->name = GNUNET_strdup (ac->label);
1192  query->type = rh->record_type;
1194  p = GNUNET_new (struct GNUNET_DNSPARSER_Packet);
1195  p->queries = query;
1196  p->num_queries = 1;
1198  UINT16_MAX);
1200  p->flags.recursion_desired = 1;
1201  ret = GNUNET_DNSPARSER_pack (p,
1202  1024,
1203  &dns_request,
1204  &dns_request_length);
1205  if (GNUNET_OK != ret)
1206  {
1207  GNUNET_break (0);
1208  rh->proc (rh->proc_cls,
1209  0,
1210  NULL);
1211  GNUNET_assert (NULL == rh->task_id);
1213  rh);
1214  }
1215  else
1216  {
1217  rh->original_dns_id = p->id;
1218  GNUNET_assert (NULL != ac->authority_info.dns_authority.dns_handle);
1219  GNUNET_assert (NULL == rh->dns_request);
1220  rh->leho = GNUNET_strdup (ac->label);
1222  ac->authority_info.dns_authority.dns_handle,
1223  dns_request,
1224  dns_request_length,
1226  rh);
1229  rh);
1230  }
1231  if (GNUNET_SYSERR != ret)
1232  GNUNET_free (dns_request);
1234 }
1235 
1236 
1245 static void
1247  const char *cname)
1248 {
1249  size_t nlen;
1250  char *res;
1251  const char *tld;
1252  struct AuthorityChain *ac;
1253  int af;
1254  struct GNUNET_CRYPTO_EcdsaPublicKey zone;
1255 
1256  nlen = strlen (cname);
1257  tld = GNS_get_tld (cname);
1258  if (0 == strcmp ("+", tld))
1259  {
1260  /* CNAME resolution continues relative to current domain */
1261  if (0 == rh->name_resolution_pos)
1262  {
1263  res = GNUNET_strndup (cname, nlen - 2);
1264  rh->name_resolution_pos = nlen - 2;
1265  }
1266  else
1267  {
1268  GNUNET_asprintf (&res,
1269  "%.*s.%.*s",
1270  (int) rh->name_resolution_pos,
1271  rh->name,
1272  (int) (nlen - 2),
1273  cname);
1274  rh->name_resolution_pos = strlen (res);
1275  }
1276  GNUNET_free (rh->name);
1277  rh->name = res;
1278  ac = GNUNET_new (struct AuthorityChain);
1279  ac->rh = rh;
1280  ac->gns_authority = GNUNET_YES;
1284  /* add AC to tail */
1286  rh->ac_tail,
1287  ac);
1289  rh);
1290  return;
1291  }
1292  if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1293  {
1294  /* CNAME resolution continues relative to current domain */
1295  if (0 == rh->name_resolution_pos)
1296  {
1297  GNUNET_asprintf (&res,
1298  "%.*s",
1299  strlen (cname) - (strlen (tld) + 1),
1300  cname);
1301  }
1302  else
1303  {
1304  GNUNET_asprintf (&res,
1305  "%.*s.%.*s",
1306  (int) rh->name_resolution_pos,
1307  rh->name,
1308  (int) strlen (cname) - (strlen (tld) + 1),
1309  cname);
1310  }
1311  rh->name_resolution_pos = strlen (res);
1312  GNUNET_free (rh->name);
1313  rh->name = res;
1314  ac = GNUNET_new (struct AuthorityChain);
1315  ac->rh = rh;
1316  ac->gns_authority = GNUNET_YES;
1319  /* add AC to tail */
1321  rh->ac_tail,
1322  ac);
1324  rh);
1325  return;
1326  }
1327 
1329  "Got CNAME `%s' from GNS for `%s'\n",
1330  cname,
1331  rh->name);
1332  if (NULL != rh->std_resolve)
1333  {
1335  "Multiple CNAME results from GNS resolving `%s'! Not really allowed...\n",
1336  rh->name);
1338  }
1339  /* name is absolute, go to DNS */
1340  GNUNET_free (rh->name);
1341  rh->name = GNUNET_strdup (cname);
1342  rh->name_resolution_pos = strlen (rh->name);
1343  switch (rh->record_type)
1344  {
1346  af = AF_INET;
1347  break;
1348 
1350  af = AF_INET6;
1351  break;
1352 
1353  default:
1354  af = AF_UNSPEC;
1355  break;
1356  }
1358  "Doing standard DNS lookup for `%s'\n",
1359  rh->name);
1360 
1362  af,
1365  rh);
1366 }
1367 
1368 
1376 static void
1377 handle_gns_resolution_result (void *cls,
1378  unsigned int rd_count,
1379  const struct GNUNET_GNSRECORD_Data *rd);
1380 
1381 
1396 static void
1398  int af,
1399  const void *address)
1400 {
1401  struct VpnContext *vpn_ctx = cls;
1402  struct GNS_ResolverHandle *rh = vpn_ctx->rh;
1403  struct GNUNET_GNSRECORD_Data rd[vpn_ctx->rd_count];
1404  unsigned int i;
1405 
1406  vpn_ctx->vpn_request = NULL;
1407  rh->vpn_ctx = NULL;
1410  (size_t) vpn_ctx->rd_data_size,
1411  vpn_ctx->rd_data,
1412  vpn_ctx->rd_count,
1413  rd));
1414  for (i = 0; i < vpn_ctx->rd_count; i++)
1415  {
1417  {
1418  switch (af)
1419  {
1420  case AF_INET:
1422  rd[i].data_size = sizeof(struct in_addr);
1425  rd[i].flags = 0;
1426  rd[i].data = address;
1427  break;
1428 
1429  case AF_INET6:
1433  rd[i].flags = 0;
1434  rd[i].data = address;
1435  rd[i].data_size = sizeof(struct in6_addr);
1436  break;
1437 
1438  default:
1439  GNUNET_assert (0);
1440  }
1441  break;
1442  }
1443  }
1444  GNUNET_assert (i < vpn_ctx->rd_count);
1445  if (0 == vpn_ctx->rd_count)
1447  _ ("VPN returned empty result for `%s'\n"),
1448  rh->name);
1450  vpn_ctx->rd_count,
1451  rd);
1452  GNUNET_free (vpn_ctx->rd_data);
1453  GNUNET_free (vpn_ctx);
1454 }
1455 
1456 
1464 static void
1466 {
1467  struct GNS_ResolverHandle *rh = ac->rh;
1468 
1469  if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1470  (GNUNET_NO == ac->authority_info.dns_authority.found))
1471  return; /* more pending and none found yet */
1472  if (GNUNET_NO == ac->authority_info.dns_authority.found)
1473  {
1475  "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1476  ac->authority_info.dns_authority.name);
1477  fail_resolution (rh);
1478  return;
1479  }
1480  if (GNUNET_NO != ac->authority_info.dns_authority.launched)
1481  return; /* already running, do not launch again! */
1482  /* recurse */
1483  ac->authority_info.dns_authority.launched = GNUNET_YES;
1485  "Will continue resolution using DNS to resolve `%s'\n",
1486  ac->label);
1487  GNUNET_assert (NULL == rh->task_id);
1489  rh);
1490 }
1491 
1492 
1501 static void
1503  unsigned int rd_count,
1504  const struct GNUNET_GNSRECORD_Data *rd)
1505 {
1506  struct Gns2DnsPending *gp = cls;
1507  struct AuthorityChain *ac = gp->ac;
1508 
1510  ac->authority_info.dns_authority.gp_tail,
1511  gp);
1512  /* enable cleanup of 'rh' handle that automatically comes after we return,
1513  and which expects 'rh' to be in the #rlh_head DLL. */
1514  if (NULL != gp->rh)
1515  {
1516  GNUNET_CONTAINER_DLL_insert (rlh_head,
1517  rlh_tail,
1518  gp->rh);
1519  gp->rh = NULL;
1520  }
1521  GNUNET_free (gp);
1523  "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1524  rd_count);
1525  /* find suitable A/AAAA record */
1526  for (unsigned int j = 0; j < rd_count; j++)
1527  {
1528  switch (rd[j].record_type)
1529  {
1531  {
1532  struct sockaddr_in v4;
1533 
1534  if (sizeof(struct in_addr) != rd[j].data_size)
1535  {
1536  GNUNET_break_op (0);
1537  continue;
1538  }
1539  memset (&v4,
1540  0,
1541  sizeof(v4));
1542  v4.sin_family = AF_INET;
1543  v4.sin_port = htons (53);
1544 #if HAVE_SOCKADDR_IN_SIN_LEN
1545  v4.sin_len = (u_char) sizeof(v4);
1546 #endif
1547  GNUNET_memcpy (&v4.sin_addr,
1548  rd[j].data,
1549  sizeof(struct in_addr));
1550  if (GNUNET_OK ==
1552  ac->authority_info.dns_authority.dns_handle,
1553  (const struct sockaddr *) &v4))
1555  break;
1556  }
1557 
1559  {
1560  struct sockaddr_in6 v6;
1561 
1562  if (sizeof(struct in6_addr) != rd[j].data_size)
1563  {
1564  GNUNET_break_op (0);
1565  continue;
1566  }
1567  /* FIXME: might want to check if we support IPv6 here,
1568  and otherwise skip this one and hope we find another */
1569  memset (&v6,
1570  0,
1571  sizeof(v6));
1572  v6.sin6_family = AF_INET6;
1573  v6.sin6_port = htons (53);
1574 #if HAVE_SOCKADDR_IN_SIN_LEN
1575  v6.sin6_len = (u_char) sizeof(v6);
1576 #endif
1577  GNUNET_memcpy (&v6.sin6_addr,
1578  rd[j].data,
1579  sizeof(struct in6_addr));
1580  if (GNUNET_OK ==
1582  ac->authority_info.dns_authority.dns_handle,
1583  (const struct sockaddr *) &v6))
1585  break;
1586  }
1587 
1588  default:
1589  break;
1590  }
1591  }
1592  continue_with_gns2dns (ac);
1593 }
1594 
1595 
1603 static void
1605  const struct sockaddr *addr,
1606  socklen_t addrlen)
1607 {
1608  struct Gns2DnsPending *gp = cls;
1609  struct AuthorityChain *ac = gp->ac;
1610  struct sockaddr_storage ss;
1611  struct sockaddr_in *v4;
1612  struct sockaddr_in6 *v6;
1613 
1614  if (NULL == addr)
1615  {
1616  /* DNS resolution finished */
1617  if (0 == gp->num_results)
1619  "Failed to use DNS to resolve name of DNS resolver\n");
1621  ac->authority_info.dns_authority.gp_tail,
1622  gp);
1623  GNUNET_free (gp);
1624  continue_with_gns2dns (ac);
1625  return;
1626  }
1627  GNUNET_memcpy (&ss,
1628  addr,
1629  addrlen);
1630  switch (ss.ss_family)
1631  {
1632  case AF_INET:
1633  v4 = (struct sockaddr_in *) &ss;
1634  v4->sin_port = htons (53);
1635  gp->num_results++;
1636  break;
1637 
1638  case AF_INET6:
1639  v6 = (struct sockaddr_in6 *) &ss;
1640  v6->sin6_port = htons (53);
1641  gp->num_results++;
1642  break;
1643 
1644  default:
1646  "Unsupported AF %d\n",
1647  ss.ss_family);
1648  return;
1649  }
1650  if (GNUNET_OK ==
1652  (struct sockaddr *) &ss))
1654 }
1655 
1656 
1663 static void
1665  const struct GNUNET_GNSRECORD_Data *rd)
1666 {
1667  char *cname;
1668  size_t off;
1669 
1670  off = 0;
1671  cname = GNUNET_DNSPARSER_parse_name (rd->data,
1672  rd->data_size,
1673  &off);
1674  if ((NULL == cname) ||
1675  (off != rd->data_size))
1676  {
1677  GNUNET_break_op (0); /* record not well-formed */
1678  GNUNET_free (cname);
1679  fail_resolution (rh);
1680  return;
1681  }
1683  cname);
1684  GNUNET_free (cname);
1685 }
1686 
1687 
1694 static void
1696  const struct GNUNET_GNSRECORD_Data *rd)
1697 {
1698  struct AuthorityChain *ac;
1699 
1700  /* delegation to another zone */
1701  if (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) !=
1702  rd->data_size)
1703  {
1704  GNUNET_break_op (0);
1705  fail_resolution (rh);
1706  return;
1707  }
1708  /* expand authority chain */
1709  ac = GNUNET_new (struct AuthorityChain);
1710  ac->rh = rh;
1711  ac->gns_authority = GNUNET_YES;
1713  rd->data,
1714  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
1716  /* add AC to tail */
1718  rh->ac_tail,
1719  ac);
1720  /* recurse */
1722  rh);
1723 }
1724 
1725 
1736 static int
1738  unsigned int rd_count,
1739  const struct GNUNET_GNSRECORD_Data *rd)
1740 {
1741  struct AuthorityChain *ac;
1742  const char *tld;
1743  char *ns;
1744 
1745  ns = NULL;
1746  /* expand authority chain */
1747  ac = GNUNET_new (struct AuthorityChain);
1748  ac->rh = rh;
1749  ac->authority_info.dns_authority.dns_handle = GNUNET_DNSSTUB_start (4);
1750 
1751  for (unsigned int i = 0; i < rd_count; i++)
1752  {
1753  char *ip;
1754  char *n;
1755  size_t off;
1756  struct Gns2DnsPending *gp;
1757  struct GNUNET_CRYPTO_EcdsaPublicKey zone;
1758  struct sockaddr_in v4;
1759  struct sockaddr_in6 v6;
1760 
1761  if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1762  {
1766  return GNUNET_SYSERR;
1767  }
1768  off = 0;
1769  n = GNUNET_DNSPARSER_parse_name (rd[i].data,
1770  rd[i].data_size,
1771  &off);
1772  ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1773  off += strlen (ip) + 1;
1774 
1775  if ((NULL == n) ||
1776  (NULL == ip) ||
1777  (off != rd[i].data_size))
1778  {
1779  GNUNET_break_op (0);
1780  GNUNET_free (n);
1781  GNUNET_free (ip);
1782  continue;
1783  }
1784  /* resolve 'ip' to determine the IP(s) of the DNS
1785  resolver to use for lookup of 'ns' */
1786  if (NULL != ns)
1787  {
1788  if (0 != strcasecmp (ns,
1789  n))
1790  {
1791  /* NS values must all be the same for all GNS2DNS records,
1792  anything else leads to insanity */
1793  GNUNET_break_op (0);
1794  GNUNET_free (n);
1795  GNUNET_free (ip);
1796  continue;
1797  }
1798  GNUNET_free (n);
1799  }
1800  else
1801  {
1802  ns = n;
1803  }
1804 
1805  /* check if 'ip' is already an IPv4/IPv6 address */
1806  if ((1 == inet_pton (AF_INET,
1807  ip,
1808  &v4)) ||
1809  (1 == inet_pton (AF_INET6,
1810  ip,
1811  &v6)))
1812  {
1815  ac->authority_info.dns_authority.dns_handle,
1816  ip));
1818  GNUNET_free (ip);
1819  continue;
1820  }
1821  tld = GNS_get_tld (ip);
1822  if ((0 != strcmp (tld, "+")) &&
1823  (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1824  {
1825  /* 'ip' is a DNS name */
1826  gp = GNUNET_new (struct Gns2DnsPending);
1827  gp->ac = ac;
1829  ac->authority_info.dns_authority.gp_tail,
1830  gp);
1831  gp->dns_rh = GNUNET_RESOLVER_ip_get (ip,
1832  AF_UNSPEC,
1835  gp);
1836  GNUNET_free (ip);
1837  continue;
1838  }
1839  /* 'ip' should be a GNS name */
1840  gp = GNUNET_new (struct Gns2DnsPending);
1841  gp->ac = ac;
1843  ac->authority_info.dns_authority.gp_tail,
1844  gp);
1845  gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1846  if (0 == strcmp (tld, "+"))
1847  {
1848  ip = translate_dot_plus (rh,
1849  ip);
1850  tld = GNS_get_tld (ip);
1851  if (GNUNET_OK !=
1853  &zone))
1854  {
1855  GNUNET_break_op (0);
1856  GNUNET_free (ip);
1857  continue;
1858  }
1859  }
1860  gp->rh->authority_zone = zone;
1862  "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1863  ip,
1864  ns);
1865  gp->rh->name = ip;
1866  gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1867  gp->rh->proc = &handle_gns2dns_result;
1868  gp->rh->proc_cls = gp;
1871  gp->rh->loop_limiter = rh->loop_limiter + 1;
1872  gp->rh->loop_threshold = rh->loop_threshold;
1873  gp->rh->task_id
1875  gp->rh);
1876  } /* end 'for all records' */
1877 
1878  if (NULL == ns)
1879  {
1880  /* not a single GNS2DNS record found */
1881  GNUNET_free (ac);
1882  return GNUNET_SYSERR;
1883  }
1885  strcpy (ac->authority_info.dns_authority.name,
1886  ns);
1887  /* for DNS recursion, the label is the full DNS name,
1888  created from the remainder of the GNS name and the
1889  name in the NS record */
1890  GNUNET_asprintf (&ac->label,
1891  "%.*s%s%s",
1892  (int) rh->name_resolution_pos,
1893  rh->name,
1894  (0 != rh->name_resolution_pos) ? "." : "",
1895  ns);
1896  GNUNET_free (ns);
1897 
1898  {
1899  /* the GNS name is UTF-8 and may include multibyte chars.
1900  * We have to convert the combined name to a DNS-compatible IDNA.
1901  */
1902  char *tmp = ac->label;
1903 
1904  if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1905  &ac->label,
1906  IDNA_ALLOW_UNASSIGNED))
1907  {
1909  _ ("Name `%s' cannot be converted to IDNA."),
1910  tmp);
1911  return GNUNET_SYSERR;
1912  }
1913  GNUNET_free (tmp);
1914  }
1915 
1917  rh->ac_tail,
1918  ac);
1919  if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1920  {
1922  _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1923  ac->label);
1924  return GNUNET_SYSERR;
1925  }
1926  continue_with_gns2dns (ac);
1927  return GNUNET_OK;
1928 }
1929 
1930 
1938 static void
1940  unsigned int rd_count,
1941  const struct GNUNET_GNSRECORD_Data *rd)
1942 {
1943  struct GNS_ResolverHandle *rh = cls;
1944  char *cname;
1945  struct VpnContext *vpn_ctx;
1946  const struct GNUNET_TUN_GnsVpnRecord *vpn;
1947  const char *vname;
1948  struct GNUNET_HashCode vhash;
1949  int af;
1950  char scratch[UINT16_MAX];
1951  size_t scratch_off;
1952  size_t scratch_start;
1953  size_t off;
1954  struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1955  unsigned int rd_off;
1956 
1958  "Resolution succeeded for `%s' in zone %s, got %u records\n",
1959  rh->ac_tail->label,
1961  rd_count);
1962  if (0 == rd_count)
1963  {
1965  _ ("GNS lookup failed (zero records found for `%s')\n"),
1966  rh->name);
1967  fail_resolution (rh);
1968  return;
1969  }
1970 
1971  if (0 == rh->name_resolution_pos)
1972  {
1973  /* top-level match, are we done yet? */
1974  if ((rd_count > 0) &&
1977  {
1978  off = 0;
1979  cname = GNUNET_DNSPARSER_parse_name (rd[0].data,
1980  rd[0].data_size,
1981  &off);
1982  if ((NULL == cname) ||
1983  (off != rd[0].data_size))
1984  {
1985  GNUNET_break_op (0);
1986  GNUNET_free (cname);
1987  fail_resolution (rh);
1988  return;
1989  }
1991  cname);
1992  GNUNET_free (cname);
1993  return;
1994  }
1995  /* If A/AAAA was requested, but we got a VPN
1996  record, we convert it to A/AAAA using GNUnet VPN */
1997  if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
1999  {
2000  for (unsigned int i = 0; i < rd_count; i++)
2001  {
2002  switch (rd[i].record_type)
2003  {
2005  {
2006  af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET :
2007  AF_INET6;
2008  if (sizeof(struct GNUNET_TUN_GnsVpnRecord) >
2009  rd[i].data_size)
2010  {
2011  GNUNET_break_op (0);
2012  fail_resolution (rh);
2013  return;
2014  }
2015  vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
2016  vname = (const char *) &vpn[1];
2017  if ('\0' != vname[rd[i].data_size - 1 - sizeof(struct
2019  ])
2020  {
2021  GNUNET_break_op (0);
2022  fail_resolution (rh);
2023  return;
2024  }
2026  &vhash);
2028  "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n",
2029  GNUNET_i2s (&vpn->peer),
2030  vname,
2031  (int) af,
2032  (int) ntohs (vpn->proto));
2033  vpn_ctx = GNUNET_new (struct VpnContext);
2034  rh->vpn_ctx = vpn_ctx;
2035  vpn_ctx->rh = rh;
2036  vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
2037  rd);
2038  if (vpn_ctx->rd_data_size < 0)
2039  {
2040  GNUNET_break_op (0);
2041  GNUNET_free (vpn_ctx);
2042  fail_resolution (rh);
2043  return;
2044  }
2045  vpn_ctx->rd_data = GNUNET_malloc ((size_t) vpn_ctx->rd_data_size);
2046  vpn_ctx->rd_count = rd_count;
2047  GNUNET_assert (vpn_ctx->rd_data_size ==
2049  rd,
2050  (size_t) vpn_ctx
2051  ->rd_data_size,
2052  vpn_ctx->rd_data));
2053  vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
2054  af,
2055  ntohs (
2056  vpn->proto),
2057  &vpn->peer,
2058  &vhash,
2060  VPN_TIMEOUT),
2061  &
2063  vpn_ctx);
2064  return;
2065  }
2066 
2068  {
2069  /* delegation to DNS */
2071  "Found GNS2DNS record, delegating to DNS!\n");
2072  if (GNUNET_OK ==
2074  rd_count,
2075  rd))
2076  return;
2077  else
2078  goto fail;
2079  }
2080 
2081  default:
2082  break;
2083  } /* end: switch */
2084  } /* end: for rd */
2085  } /* end: name_resolution_pos */
2086  /* convert relative names in record values to absolute names,
2087  using 'scratch' array for memory allocations */
2088  scratch_off = 0;
2089  rd_off = 0;
2090  for (unsigned int i = 0; i < rd_count; i++)
2091  {
2092  GNUNET_assert (rd_off <= i);
2093  if ((0 != rh->protocol) &&
2094  (0 != rh->service) &&
2096  continue; /* we _only_ care about boxed records */
2097 
2098  GNUNET_assert (rd_off < rd_count);
2099  rd_new[rd_off] = rd[i];
2100  /* Check if the embedded name(s) end in "+", and if so,
2101  replace the "+" with the zone at "ac_tail", changing the name
2102  to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2103  so we can free it afterwards. */
2104  switch (rd[i].record_type)
2105  {
2107  {
2108  char *cname;
2109 
2110  off = 0;
2111  cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
2112  rd[i].data_size,
2113  &off);
2114  if ((NULL == cname) ||
2115  (off != rd[i].data_size))
2116  {
2117  GNUNET_break_op (0); /* record not well-formed */
2118  }
2119  else
2120  {
2121  cname = translate_dot_plus (rh, cname);
2122  GNUNET_break (NULL != cname);
2123  scratch_start = scratch_off;
2124  if (GNUNET_OK !=
2126  sizeof(scratch),
2127  &scratch_off,
2128  cname))
2129  {
2130  GNUNET_break (0);
2131  }
2132  else
2133  {
2134  GNUNET_assert (rd_off < rd_count);
2135  rd_new[rd_off].data = &scratch[scratch_start];
2136  rd_new[rd_off].data_size = scratch_off - scratch_start;
2137  rd_off++;
2138  }
2139  }
2140  GNUNET_free (cname);
2141  }
2142  break;
2143 
2145  {
2146  struct GNUNET_DNSPARSER_SoaRecord *soa;
2147 
2148  off = 0;
2149  soa = GNUNET_DNSPARSER_parse_soa (rd[i].data,
2150  rd[i].data_size,
2151  &off);
2152  if ((NULL == soa) ||
2153  (off != rd[i].data_size))
2154  {
2155  GNUNET_break_op (0); /* record not well-formed */
2156  }
2157  else
2158  {
2159  soa->mname = translate_dot_plus (rh, soa->mname);
2160  soa->rname = translate_dot_plus (rh, soa->rname);
2161  scratch_start = scratch_off;
2162  if (GNUNET_OK !=
2164  sizeof(scratch),
2165  &scratch_off,
2166  soa))
2167  {
2168  GNUNET_break (0);
2169  }
2170  else
2171  {
2172  GNUNET_assert (rd_off < rd_count);
2173  rd_new[rd_off].data = &scratch[scratch_start];
2174  rd_new[rd_off].data_size = scratch_off - scratch_start;
2175  rd_off++;
2176  }
2177  }
2178  if (NULL != soa)
2180  }
2181  break;
2182 
2184  {
2185  struct GNUNET_DNSPARSER_MxRecord *mx;
2186 
2187  off = 0;
2188  mx = GNUNET_DNSPARSER_parse_mx (rd[i].data,
2189  rd[i].data_size,
2190  &off);
2191  if ((NULL == mx) ||
2192  (off != rd[i].data_size))
2193  {
2194  GNUNET_break_op (0); /* record not well-formed */
2195  }
2196  else
2197  {
2198  mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2199  scratch_start = scratch_off;
2200  if (GNUNET_OK !=
2202  sizeof(scratch),
2203  &scratch_off,
2204  mx))
2205  {
2206  GNUNET_break (0);
2207  }
2208  else
2209  {
2210  GNUNET_assert (rd_off < rd_count);
2211  rd_new[rd_off].data = &scratch[scratch_start];
2212  rd_new[rd_off].data_size = scratch_off - scratch_start;
2213  rd_off++;
2214  }
2215  }
2216  if (NULL != mx)
2218  }
2219  break;
2220 
2222  {
2223  struct GNUNET_DNSPARSER_SrvRecord *srv;
2224 
2225  off = 0;
2226  srv = GNUNET_DNSPARSER_parse_srv (rd[i].data,
2227  rd[i].data_size,
2228  &off);
2229  if ((NULL == srv) ||
2230  (off != rd[i].data_size))
2231  {
2232  GNUNET_break_op (0); /* record not well-formed */
2233  }
2234  else
2235  {
2236  srv->target = translate_dot_plus (rh, srv->target);
2237  scratch_start = scratch_off;
2238  if (GNUNET_OK !=
2240  sizeof(scratch),
2241  &scratch_off,
2242  srv))
2243  {
2244  GNUNET_break (0);
2245  }
2246  else
2247  {
2248  GNUNET_assert (rd_off < rd_count);
2249  rd_new[rd_off].data = &scratch[scratch_start];
2250  rd_new[rd_off].data_size = scratch_off - scratch_start;
2251  rd_off++;
2252  }
2253  }
2254  if (NULL != srv)
2256  }
2257  break;
2258 
2260  {
2261  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
2262 
2263  if (rd[i].data_size != sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))
2264  {
2265  GNUNET_break_op (0);
2266  break;
2267  }
2268  GNUNET_memcpy (&pub,
2269  rd[i].data,
2270  rd[i].data_size);
2271  rd_off++;
2273  {
2274  /* try to resolve "@" */
2275  struct AuthorityChain *ac;
2276 
2277  ac = GNUNET_new (struct AuthorityChain);
2278  ac->rh = rh;
2279  ac->gns_authority = GNUNET_YES;
2283  rh->ac_tail,
2284  ac);
2286  rh);
2287  return;
2288  }
2289  }
2290  break;
2291 
2293  {
2294  /* delegation to DNS */
2296  {
2297  rd_off++;
2298  break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2299  }
2301  "Found GNS2DNS record, delegating to DNS!\n");
2302  if (GNUNET_OK ==
2304  rd_count,
2305  rd))
2306  return;
2307  else
2308  goto fail;
2309  }
2310 
2312  {
2313  /* unbox SRV/TLSA records if a specific one was requested */
2314  if ((0 != rh->protocol) &&
2315  (0 != rh->service) &&
2316  (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2317  {
2318  const struct GNUNET_GNSRECORD_BoxRecord *box;
2319 
2320  box = rd[i].data;
2321  if ((ntohs (box->protocol) == rh->protocol) &&
2322  (ntohs (box->service) == rh->service))
2323  {
2324  /* Box matches, unbox! */
2325  GNUNET_assert (rd_off < rd_count);
2326  rd_new[rd_off].record_type = ntohl (box->record_type);
2327  rd_new[rd_off].data_size -= sizeof(struct
2329  rd_new[rd_off].data = &box[1];
2330  rd_off++;
2331  }
2332  }
2333  else
2334  {
2335  /* no specific protocol/service specified, preserve all BOX
2336  records (for modern, GNS-enabled applications) */
2337  rd_off++;
2338  }
2339  break;
2340  }
2341 
2342  default:
2343  rd_off++;
2344  break;
2345  } /* end: switch */
2346  } /* end: for rd_count */
2347 
2348  /* yes, we are done, return result */
2350  "Returning GNS response for `%s' with %u answers\n",
2351  rh->ac_tail->label,
2352  rd_off);
2353  rh->proc (rh->proc_cls,
2354  rd_off,
2355  rd_new);
2357  rh);
2358  return;
2359  }
2360 
2361  switch (rd[0].record_type)
2362  {
2364  GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2366  &rd[0]);
2367  return;
2368 
2370  GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2372  &rd[0]);
2373  return;
2374 
2375  default:
2376  if (GNUNET_OK ==
2378  rd_count,
2379  rd))
2380  return;
2381  break;
2382  }
2383 fail:
2385  _ ("GNS lookup recursion failed (no delegation record found)\n"));
2386  fail_resolution (rh);
2387 }
2388 
2389 
2398 static void
2400  int32_t success,
2401  const char *emsg)
2402 {
2403  struct CacheOps *co = cls;
2404 
2405  co->namecache_qe_cache = NULL;
2406  if (GNUNET_OK != success)
2408  _ ("Failed to cache GNS resolution: %s\n"),
2409  emsg);
2410  GNUNET_CONTAINER_DLL_remove (co_head,
2411  co_tail,
2412  co);
2413  GNUNET_free (co);
2414 }
2415 
2416 
2434 static void
2436  struct GNUNET_TIME_Absolute exp,
2437  const struct GNUNET_HashCode *key,
2438  const struct GNUNET_PeerIdentity *get_path,
2439  unsigned int get_path_length,
2440  const struct GNUNET_PeerIdentity *put_path,
2441  unsigned int put_path_length,
2442  enum GNUNET_BLOCK_Type type,
2443  size_t size,
2444  const void *data)
2445 {
2446  struct GNS_ResolverHandle *rh = cls;
2447  struct AuthorityChain *ac = rh->ac_tail;
2448  const struct GNUNET_GNSRECORD_Block *block;
2449  struct CacheOps *co;
2450 
2451  (void) exp;
2452  (void) key;
2453  (void) get_path;
2454  (void) get_path_length;
2455  (void) put_path;
2456  (void) put_path_length;
2457  (void) type;
2459  rh->get_handle = NULL;
2461  rh->dht_heap_node = NULL;
2463  "Handling response from the DHT\n");
2464  if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2465  {
2466  /* how did this pass DHT block validation!? */
2467  GNUNET_break (0);
2468  fail_resolution (rh);
2469  return;
2470  }
2471  block = data;
2472  if (size !=
2473  ntohl (block->purpose.size)
2474  + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)
2475  + sizeof(struct GNUNET_CRYPTO_EcdsaSignature))
2476  {
2477  /* how did this pass DHT block validation!? */
2478  GNUNET_break (0);
2479  fail_resolution (rh);
2480  return;
2481  }
2483  "Decrypting DHT block of size %u for `%s', expires %s\n",
2484  ntohl (block->purpose.size),
2485  rh->name,
2487  if (GNUNET_OK !=
2490  ac->label,
2492  rh))
2493  {
2494  GNUNET_break_op (0); /* block was ill-formed */
2495  fail_resolution (rh);
2496  return;
2497  }
2499  block->expiration_time)).
2500  rel_value_us)
2501  {
2503  "Received expired block from the DHT, will not cache it.\n");
2504  return;
2505  }
2506  if (GNUNET_YES == disable_cache)
2507  return;
2508  /* Cache well-formed blocks */
2510  "Caching response from the DHT in namecache\n");
2511  co = GNUNET_new (struct CacheOps);
2512  co->namecache_qe_cache = GNUNET_NAMECACHE_block_cache (namecache_handle,
2513  block,
2514  &
2516  co);
2517  GNUNET_CONTAINER_DLL_insert (co_head,
2518  co_tail,
2519  co);
2520 }
2521 
2522 
2529 static void
2531  const struct GNUNET_HashCode *query)
2532 {
2533  struct GNS_ResolverHandle *rx;
2534 
2535  GNUNET_assert (NULL == rh->get_handle);
2536  rh->get_handle = GNUNET_DHT_get_start (dht_handle,
2538  query,
2541  NULL, 0,
2542  &handle_dht_response, rh);
2543  rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
2544  rh,
2546  abs_value_us);
2547  if (GNUNET_CONTAINER_heap_get_size (dht_lookup_heap) >
2549  {
2550  /* fail longest-standing DHT request */
2551  rx = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
2552  rx->dht_heap_node = NULL;
2553  GNUNET_assert (NULL != rx);
2554  fail_resolution (rx);
2555  }
2556 }
2557 
2558 
2567 static void
2569  unsigned int rd_count,
2570  const struct GNUNET_GNSRECORD_Data *rd)
2571 {
2572  struct GNS_ResolverHandle *rh = cls;
2573 
2574  if (0 == rd_count)
2576  _ ("GNS namecache returned empty result for `%s'\n"),
2577  rh->name);
2579  rd_count,
2580  rd);
2581 }
2582 
2583 
2590 static void
2592  const struct GNUNET_GNSRECORD_Block *block)
2593 {
2594  struct GNS_ResolverHandle *rh = cls;
2595  struct AuthorityChain *ac = rh->ac_tail;
2596  const char *label = ac->label;
2597  const struct GNUNET_CRYPTO_EcdsaPublicKey *auth =
2599  struct GNUNET_HashCode query;
2600 
2601  GNUNET_assert (NULL != rh->namecache_qe);
2602  rh->namecache_qe = NULL;
2603  if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2604  ((GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2605  (ac != rh->ac_head))) &&
2606  ((NULL == block) ||
2608  block->expiration_time)).
2609  rel_value_us)))
2610  {
2611  /* namecache knows nothing; try DHT lookup */
2613  label,
2614  &query);
2616  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2617  ac->label,
2619  GNUNET_h2s (&query));
2620  start_dht_request (rh, &query);
2621  return;
2622  }
2623 
2624  if ((NULL == block) ||
2626  block->expiration_time)).
2627  rel_value_us))
2628  {
2629  /* DHT not permitted and no local result, fail */
2631  "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2632  ac->label,
2634  fail_resolution (rh);
2635  return;
2636  }
2638  "Received result from namecache for label `%s'\n",
2639  ac->label);
2640 
2641  if (GNUNET_OK !=
2643  auth,
2644  label,
2646  rh))
2647  {
2648  GNUNET_break_op (0); /* block was ill-formed */
2649  /* try DHT instead */
2651  label,
2652  &query);
2654  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2655  ac->label,
2657  GNUNET_h2s (&query));
2658  start_dht_request (rh, &query);
2659  return;
2660  }
2661 }
2662 
2663 
2669 static void
2671 {
2672  struct AuthorityChain *ac = rh->ac_tail;
2673  struct GNUNET_HashCode query;
2674 
2676  "Starting GNS resolution for `%s' in zone %s\n",
2677  ac->label,
2680  ac->label,
2681  &query);
2682  if (GNUNET_YES != disable_cache)
2683  {
2684  rh->namecache_qe
2685  = GNUNET_NAMECACHE_lookup_block (namecache_handle,
2686  &query,
2688  rh);
2689  GNUNET_assert (NULL != rh->namecache_qe);
2690  }
2691  else
2692  {
2693  start_dht_request (rh,
2694  &query);
2695  }
2696 }
2697 
2698 
2705 static void
2707  int is_valid)
2708 {
2709  struct GNS_ResolverHandle *rh = cls;
2710  struct AuthorityChain *ac = rh->ac_tail;
2711 
2712  rh->rev_check = NULL;
2713  if (GNUNET_YES != is_valid)
2714  {
2716  _ ("Zone %s was revoked, resolution fails\n"),
2718  fail_resolution (rh);
2719  return;
2720  }
2722 }
2723 
2724 
2730 static void
2732 {
2733  struct AuthorityChain *ac = rh->ac_tail;
2734 
2736  "Starting revocation check for zone %s\n",
2741  rh);
2742  GNUNET_assert (NULL != rh->rev_check);
2743 }
2744 
2745 
2751 static void
2753 {
2754  struct GNS_ResolverHandle *rh = cls;
2755 
2756  rh->task_id = NULL;
2757  if (rh->loop_threshold < rh->loop_limiter++)
2758  {
2760  "Encountered unbounded recursion resolving `%s'\n",
2761  rh->name);
2762  fail_resolution (rh);
2763  return;
2764  }
2765  if (GNUNET_YES == rh->ac_tail->gns_authority)
2767  else
2769 }
2770 
2771 
2778 static void
2780 {
2781  struct GNS_ResolverHandle *rh = cls;
2782  struct AuthorityChain *ac;
2783  struct in_addr v4;
2784  struct in6_addr v6;
2785 
2786  rh->task_id = NULL;
2787  if (1 == inet_pton (AF_INET,
2788  rh->name,
2789  &v4))
2790  {
2791  /* name is IPv4 address, pretend it's an A record */
2792  struct GNUNET_GNSRECORD_Data rd;
2793 
2794  rd.data = &v4;
2795  rd.data_size = sizeof(v4);
2796  rd.expiration_time = UINT64_MAX;
2798  rd.flags = 0;
2799  rh->proc (rh->proc_cls,
2800  1,
2801  &rd);
2802  GNUNET_assert (NULL == rh->task_id);
2804  rh);
2805  return;
2806  }
2807  if (1 == inet_pton (AF_INET6,
2808  rh->name,
2809  &v6))
2810  {
2811  /* name is IPv6 address, pretend it's an AAAA record */
2812  struct GNUNET_GNSRECORD_Data rd;
2813 
2814  rd.data = &v6;
2815  rd.data_size = sizeof(v6);
2816  rd.expiration_time = UINT64_MAX;
2818  rd.flags = 0;
2819  rh->proc (rh->proc_cls,
2820  1,
2821  &rd);
2822  GNUNET_assert (NULL == rh->task_id);
2824  rh);
2825  return;
2826  }
2827 
2828  ac = GNUNET_new (struct AuthorityChain);
2829  ac->rh = rh;
2831  if (NULL == ac->label)
2832  /* name was just the "TLD", so we default to label
2833  #GNUNET_GNS_EMPTY_LABEL_AT */
2835  ac->gns_authority = GNUNET_YES;
2838  rh->ac_tail,
2839  ac);
2841  rh);
2842 }
2843 
2844 
2859 struct GNS_ResolverHandle *
2861  uint32_t record_type,
2862  const char *name,
2864  uint16_t recursion_depth_limit,
2866  void *proc_cls)
2867 {
2868  struct GNS_ResolverHandle *rh;
2869 
2871  "Starting lookup for `%s'\n",
2872  name);
2873  rh = GNUNET_new (struct GNS_ResolverHandle);
2874  GNUNET_CONTAINER_DLL_insert (rlh_head,
2875  rlh_tail,
2876  rh);
2877  rh->authority_zone = *zone;
2878  rh->proc = proc;
2879  rh->proc_cls = proc_cls;
2880  rh->options = options;
2881  rh->record_type = record_type;
2882  rh->name = GNUNET_strdup (name);
2883  rh->name_resolution_pos = strlen (name);
2884  rh->loop_threshold = recursion_depth_limit;
2886  rh);
2887  return rh;
2888 }
2889 
2890 
2896 void
2898 {
2899  struct DnsResult *dr;
2900  struct AuthorityChain *ac;
2901  struct VpnContext *vpn_ctx;
2902 
2903  GNUNET_CONTAINER_DLL_remove (rlh_head,
2904  rlh_tail,
2905  rh);
2906  if (NULL != rh->dns_request)
2907  {
2909  rh->dns_request = NULL;
2910  }
2911  while (NULL != (ac = rh->ac_head))
2912  {
2914  rh->ac_tail,
2915  ac);
2916  if (GNUNET_NO == ac->gns_authority)
2917  {
2918  struct Gns2DnsPending *gp;
2919 
2920  while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2921  {
2923  ac->authority_info.dns_authority.gp_tail,
2924  gp);
2925  if (NULL != gp->rh)
2926  {
2927  /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2928  using GNS_resolver_lookup_cancel here, we need to
2929  add it first... */
2930  GNUNET_CONTAINER_DLL_insert (rlh_head,
2931  rlh_tail,
2932  gp->rh);
2933  GNUNET_assert (NULL == gp->rh->task_id);
2936  gp->rh);
2937  gp->rh = NULL;
2938  }
2939  if (NULL != gp->dns_rh)
2940  {
2942  gp->dns_rh = NULL;
2943  }
2944  GNUNET_free (gp);
2945  }
2947  }
2948  GNUNET_free (ac->label);
2949  GNUNET_free (ac);
2950  }
2951  if (NULL != rh->task_id)
2952  {
2954  rh->task_id = NULL;
2955  }
2956  if (NULL != rh->get_handle)
2957  {
2959  rh->get_handle = NULL;
2960  }
2961  if (NULL != rh->dht_heap_node)
2962  {
2964  rh->dht_heap_node = NULL;
2965  }
2966  if (NULL != (vpn_ctx = rh->vpn_ctx))
2967  {
2969  GNUNET_free (vpn_ctx->rd_data);
2970  GNUNET_free (vpn_ctx);
2971  }
2972  if (NULL != rh->namecache_qe)
2973  {
2975  rh->namecache_qe = NULL;
2976  }
2977  if (NULL != rh->rev_check)
2978  {
2980  rh->rev_check = NULL;
2981  }
2982  if (NULL != rh->std_resolve)
2983  {
2985  "Canceling standard DNS resolution\n");
2987  rh->std_resolve = NULL;
2988  }
2989  while (NULL != (dr = rh->dns_result_head))
2990  {
2992  rh->dns_result_tail,
2993  dr);
2994  GNUNET_free (dr);
2995  }
2996  GNUNET_free (rh->leho);
2997  GNUNET_free (rh->name);
2998  GNUNET_free (rh);
2999 }
3000 
3001 
3002 /* ***************** Resolver initialization ********************* */
3003 
3004 
3013 void
3015  struct GNUNET_DHT_Handle *dht,
3016  const struct GNUNET_CONFIGURATION_Handle *c,
3017  unsigned long long max_bg_queries)
3018 {
3019  cfg = c;
3020  namecache_handle = nc;
3021  dht_handle = dht;
3022  dht_lookup_heap =
3024  max_allowed_background_queries = max_bg_queries;
3026  "namecache",
3027  "DISABLE");
3028  if (GNUNET_YES == disable_cache)
3030  "Namecache disabled\n");
3031  vpn_handle = GNUNET_VPN_connect (cfg);
3032 }
3033 
3034 
3038 void
3040 {
3041  struct GNS_ResolverHandle *rh;
3042  struct CacheOps *co;
3043 
3044  /* abort active resolutions */
3045  while (NULL != (rh = rlh_head))
3046  {
3047  rh->proc (rh->proc_cls,
3048  0,
3049  NULL);
3051  }
3052  while (NULL != (co = co_head))
3053  {
3054  GNUNET_CONTAINER_DLL_remove (co_head,
3055  co_tail,
3056  co);
3058  GNUNET_free (co);
3059  }
3060  GNUNET_CONTAINER_heap_destroy (dht_lookup_heap);
3061  dht_lookup_heap = NULL;
3062  GNUNET_VPN_disconnect (vpn_handle);
3063  vpn_handle = NULL;
3064  dht_handle = NULL;
3065  namecache_handle = NULL;
3066 }
3067 
3068 
3069 /* 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.
This is a supplemental record.
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).
size_t data_size
Number of bytes in data.
#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:184
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:1269
#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:1296
#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.
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.
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:972