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_IDENTITY_PublicKey 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_IDENTITY_PublicKey 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;
774  if (0 == pos->expiration_time)
775  {
777  rd[i].expiration_time = 0;
778  }
779  else
780  {
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_IDENTITY_PublicKey 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  (int) (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  struct GNUNET_IDENTITY_PublicKey auth;
1700 
1701  /* delegation to another zone */
1703  rd->data_size,
1704  rd->record_type,
1705  &auth))
1706  {
1707  GNUNET_break_op (0);
1708  fail_resolution (rh);
1709  return;
1710  }
1711  /* expand authority chain */
1712  ac = GNUNET_new (struct AuthorityChain);
1713  ac->rh = rh;
1714  ac->gns_authority = GNUNET_YES;
1715  ac->authority_info.gns_authority = auth;
1717  /* add AC to tail */
1719  rh->ac_tail,
1720  ac);
1721  /* recurse */
1723  rh);
1724 }
1725 
1726 
1737 static int
1739  unsigned int rd_count,
1740  const struct GNUNET_GNSRECORD_Data *rd)
1741 {
1742  struct AuthorityChain *ac;
1743  const char *tld;
1744  char *ns;
1745 
1746  ns = NULL;
1747  /* expand authority chain */
1748  ac = GNUNET_new (struct AuthorityChain);
1749  ac->rh = rh;
1750  ac->authority_info.dns_authority.dns_handle = GNUNET_DNSSTUB_start (4);
1751 
1752  for (unsigned int i = 0; i < rd_count; i++)
1753  {
1754  char *ip;
1755  char *n;
1756  size_t off;
1757  struct Gns2DnsPending *gp;
1758  struct GNUNET_IDENTITY_PublicKey zone;
1759  struct sockaddr_in v4;
1760  struct sockaddr_in6 v6;
1761 
1762  if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1763  {
1767  GNUNET_free (ns);
1768  GNUNET_free (ac);
1769  return GNUNET_SYSERR;
1770  }
1771  off = 0;
1772  n = GNUNET_DNSPARSER_parse_name (rd[i].data,
1773  rd[i].data_size,
1774  &off);
1775  ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1776  if ((NULL == n) ||
1777  (NULL == ip))
1778  {
1779  GNUNET_break_op (0);
1780  GNUNET_free (n);
1781  GNUNET_free (ip);
1782  continue;
1783  }
1784 
1785  off += strlen (ip) + 1;
1786 
1787  if (off != rd[i].data_size)
1788  {
1789  GNUNET_break_op (0);
1790  GNUNET_free (n);
1791  GNUNET_free (ip);
1792  continue;
1793  }
1794  /* resolve 'ip' to determine the IP(s) of the DNS
1795  resolver to use for lookup of 'ns' */
1796  if (NULL != ns)
1797  {
1798  if (0 != strcasecmp (ns,
1799  n))
1800  {
1801  /* NS values must all be the same for all GNS2DNS records,
1802  anything else leads to insanity */
1803  GNUNET_break_op (0);
1804  GNUNET_free (n);
1805  GNUNET_free (ip);
1806  continue;
1807  }
1808  GNUNET_free (n);
1809  }
1810  else
1811  {
1812  ns = n;
1813  }
1814 
1815  /* check if 'ip' is already an IPv4/IPv6 address */
1816  if ((1 == inet_pton (AF_INET,
1817  ip,
1818  &v4)) ||
1819  (1 == inet_pton (AF_INET6,
1820  ip,
1821  &v6)))
1822  {
1825  ac->authority_info.dns_authority.dns_handle,
1826  ip));
1828  GNUNET_free (ip);
1829  continue;
1830  }
1831  tld = GNS_get_tld (ip);
1832  if ((0 != strcmp (tld, "+")) &&
1833  (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1834  {
1835  /* 'ip' is a DNS name */
1836  gp = GNUNET_new (struct Gns2DnsPending);
1837  gp->ac = ac;
1839  ac->authority_info.dns_authority.gp_tail,
1840  gp);
1841  gp->dns_rh = GNUNET_RESOLVER_ip_get (ip,
1842  AF_UNSPEC,
1845  gp);
1846  GNUNET_free (ip);
1847  continue;
1848  }
1849  /* 'ip' should be a GNS name */
1850  gp = GNUNET_new (struct Gns2DnsPending);
1851  gp->ac = ac;
1853  ac->authority_info.dns_authority.gp_tail,
1854  gp);
1855  gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1856  if (0 == strcmp (tld, "+"))
1857  {
1858  ip = translate_dot_plus (rh,
1859  ip);
1860  tld = GNS_get_tld (ip);
1861  if (GNUNET_OK !=
1863  &zone))
1864  {
1865  GNUNET_break_op (0);
1866  GNUNET_free (ip);
1867  continue;
1868  }
1869  }
1870  gp->rh->authority_zone = zone;
1872  "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1873  ip,
1874  ns);
1875  gp->rh->name = ip;
1876  gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1877  gp->rh->proc = &handle_gns2dns_result;
1878  gp->rh->proc_cls = gp;
1881  gp->rh->loop_limiter = rh->loop_limiter + 1;
1882  gp->rh->loop_threshold = rh->loop_threshold;
1883  gp->rh->task_id
1885  gp->rh);
1886  } /* end 'for all records' */
1887 
1888  if (NULL == ns)
1889  {
1890  /* not a single GNS2DNS record found */
1891  GNUNET_free (ac);
1892  return GNUNET_SYSERR;
1893  }
1895  strcpy (ac->authority_info.dns_authority.name,
1896  ns);
1897  /* for DNS recursion, the label is the full DNS name,
1898  created from the remainder of the GNS name and the
1899  name in the NS record */
1900  GNUNET_asprintf (&ac->label,
1901  "%.*s%s%s",
1902  (int) rh->name_resolution_pos,
1903  rh->name,
1904  (0 != rh->name_resolution_pos) ? "." : "",
1905  ns);
1906  GNUNET_free (ns);
1907 
1908  {
1909  /* the GNS name is UTF-8 and may include multibyte chars.
1910  * We have to convert the combined name to a DNS-compatible IDNA.
1911  */
1912  char *tmp = ac->label;
1913 
1914  if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1915  &ac->label,
1916  IDNA_ALLOW_UNASSIGNED))
1917  {
1919  _ ("Name `%s' cannot be converted to IDNA."),
1920  tmp);
1921  GNUNET_free (tmp);
1922  GNUNET_free (ac);
1923  return GNUNET_SYSERR;
1924  }
1925  GNUNET_free (tmp);
1926  }
1927 
1929  rh->ac_tail,
1930  ac);
1931  if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1932  {
1934  _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1935  ac->label);
1936  GNUNET_free (ac->label);
1937  GNUNET_free (ac);
1938  return GNUNET_SYSERR;
1939  }
1940  continue_with_gns2dns (ac);
1941  return GNUNET_OK;
1942 }
1943 
1944 
1952 static void
1954  unsigned int rd_count,
1955  const struct GNUNET_GNSRECORD_Data *rd)
1956 {
1957  struct GNS_ResolverHandle *rh = cls;
1958  char *cname;
1959  struct VpnContext *vpn_ctx;
1960  const struct GNUNET_TUN_GnsVpnRecord *vpn;
1961  const char *vname;
1962  struct GNUNET_HashCode vhash;
1963  int af;
1964  char scratch[UINT16_MAX];
1965  size_t scratch_off;
1966  size_t scratch_start;
1967  size_t off;
1968  struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1969  unsigned int rd_off;
1970 
1972  "Resolution succeeded for `%s' in zone %s, got %u records\n",
1973  rh->ac_tail->label,
1975  rd_count);
1976  if (0 == rd_count)
1977  {
1979  _ ("GNS lookup failed (zero records found for `%s')\n"),
1980  rh->name);
1981  fail_resolution (rh);
1982  return;
1983  }
1984 
1985  if (0 == rh->name_resolution_pos)
1986  {
1987  /* top-level match, are we done yet? */
1988  if ((rd_count > 0) &&
1991  {
1992  off = 0;
1993  cname = GNUNET_DNSPARSER_parse_name (rd[0].data,
1994  rd[0].data_size,
1995  &off);
1996  if ((NULL == cname) ||
1997  (off != rd[0].data_size))
1998  {
1999  GNUNET_break_op (0);
2000  GNUNET_free (cname);
2001  fail_resolution (rh);
2002  return;
2003  }
2005  cname);
2006  GNUNET_free (cname);
2007  return;
2008  }
2009  /* If A/AAAA was requested, but we got a VPN
2010  record, we convert it to A/AAAA using GNUnet VPN */
2011  if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2013  {
2014  for (unsigned int i = 0; i < rd_count; i++)
2015  {
2016  switch (rd[i].record_type)
2017  {
2019  {
2020  af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET :
2021  AF_INET6;
2022  if (sizeof(struct GNUNET_TUN_GnsVpnRecord) >
2023  rd[i].data_size)
2024  {
2025  GNUNET_break_op (0);
2026  fail_resolution (rh);
2027  return;
2028  }
2029  vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
2030  vname = (const char *) &vpn[1];
2031  if ('\0' != vname[rd[i].data_size - 1 - sizeof(struct
2033  ])
2034  {
2035  GNUNET_break_op (0);
2036  fail_resolution (rh);
2037  return;
2038  }
2040  &vhash);
2042  "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n",
2043  GNUNET_i2s (&vpn->peer),
2044  vname,
2045  (int) af,
2046  (int) ntohs (vpn->proto));
2047  vpn_ctx = GNUNET_new (struct VpnContext);
2048  rh->vpn_ctx = vpn_ctx;
2049  vpn_ctx->rh = rh;
2050  vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
2051  rd);
2052  if (vpn_ctx->rd_data_size < 0)
2053  {
2054  GNUNET_break_op (0);
2055  GNUNET_free (vpn_ctx);
2056  fail_resolution (rh);
2057  return;
2058  }
2059  vpn_ctx->rd_data = GNUNET_malloc ((size_t) vpn_ctx->rd_data_size);
2060  vpn_ctx->rd_count = rd_count;
2061  GNUNET_assert (vpn_ctx->rd_data_size ==
2063  rd,
2064  (size_t) vpn_ctx
2065  ->rd_data_size,
2066  vpn_ctx->rd_data));
2067  vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
2068  af,
2069  ntohs (
2070  vpn->proto),
2071  &vpn->peer,
2072  &vhash,
2074  VPN_TIMEOUT),
2075  &
2077  vpn_ctx);
2078  return;
2079  }
2080 
2082  {
2083  /* delegation to DNS */
2085  "Found GNS2DNS record, delegating to DNS!\n");
2086  if (GNUNET_OK ==
2088  rd_count,
2089  rd))
2090  return;
2091  else
2092  goto fail;
2093  }
2094 
2095  default:
2096  break;
2097  } /* end: switch */
2098  } /* end: for rd */
2099  } /* end: name_resolution_pos */
2100  /* convert relative names in record values to absolute names,
2101  using 'scratch' array for memory allocations */
2102  scratch_off = 0;
2103  rd_off = 0;
2104  for (unsigned int i = 0; i < rd_count; i++)
2105  {
2106  GNUNET_assert (rd_off <= i);
2107  if ((0 != rh->protocol) &&
2108  (0 != rh->service) &&
2110  continue; /* we _only_ care about boxed records */
2111 
2112  GNUNET_assert (rd_off < rd_count);
2113  rd_new[rd_off] = rd[i];
2114  /* Check if the embedded name(s) end in "+", and if so,
2115  replace the "+" with the zone at "ac_tail", changing the name
2116  to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2117  so we can free it afterwards. */
2118  switch (rd[i].record_type)
2119  {
2121  {
2122  char *cname;
2123 
2124  off = 0;
2125  cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
2126  rd[i].data_size,
2127  &off);
2128  if ((NULL == cname) ||
2129  (off != rd[i].data_size))
2130  {
2131  GNUNET_break_op (0); /* record not well-formed */
2132  }
2133  else
2134  {
2135  cname = translate_dot_plus (rh, cname);
2136  GNUNET_break (NULL != cname);
2137  scratch_start = scratch_off;
2138  if (GNUNET_OK !=
2140  sizeof(scratch),
2141  &scratch_off,
2142  cname))
2143  {
2144  GNUNET_break (0);
2145  }
2146  else
2147  {
2148  GNUNET_assert (rd_off < rd_count);
2149  rd_new[rd_off].data = &scratch[scratch_start];
2150  rd_new[rd_off].data_size = scratch_off - scratch_start;
2151  rd_off++;
2152  }
2153  }
2154  GNUNET_free (cname);
2155  }
2156  break;
2157 
2159  {
2160  struct GNUNET_DNSPARSER_SoaRecord *soa;
2161 
2162  off = 0;
2163  soa = GNUNET_DNSPARSER_parse_soa (rd[i].data,
2164  rd[i].data_size,
2165  &off);
2166  if ((NULL == soa) ||
2167  (off != rd[i].data_size))
2168  {
2169  GNUNET_break_op (0); /* record not well-formed */
2170  }
2171  else
2172  {
2173  soa->mname = translate_dot_plus (rh, soa->mname);
2174  soa->rname = translate_dot_plus (rh, soa->rname);
2175  scratch_start = scratch_off;
2176  if (GNUNET_OK !=
2178  sizeof(scratch),
2179  &scratch_off,
2180  soa))
2181  {
2182  GNUNET_break (0);
2183  }
2184  else
2185  {
2186  GNUNET_assert (rd_off < rd_count);
2187  rd_new[rd_off].data = &scratch[scratch_start];
2188  rd_new[rd_off].data_size = scratch_off - scratch_start;
2189  rd_off++;
2190  }
2191  }
2192  if (NULL != soa)
2194  }
2195  break;
2196 
2198  {
2199  struct GNUNET_DNSPARSER_MxRecord *mx;
2200 
2201  off = 0;
2202  mx = GNUNET_DNSPARSER_parse_mx (rd[i].data,
2203  rd[i].data_size,
2204  &off);
2205  if ((NULL == mx) ||
2206  (off != rd[i].data_size))
2207  {
2208  GNUNET_break_op (0); /* record not well-formed */
2209  }
2210  else
2211  {
2212  mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2213  scratch_start = scratch_off;
2214  if (GNUNET_OK !=
2216  sizeof(scratch),
2217  &scratch_off,
2218  mx))
2219  {
2220  GNUNET_break (0);
2221  }
2222  else
2223  {
2224  GNUNET_assert (rd_off < rd_count);
2225  rd_new[rd_off].data = &scratch[scratch_start];
2226  rd_new[rd_off].data_size = scratch_off - scratch_start;
2227  rd_off++;
2228  }
2229  }
2230  if (NULL != mx)
2232  }
2233  break;
2234 
2236  {
2237  struct GNUNET_DNSPARSER_SrvRecord *srv;
2238 
2239  off = 0;
2240  srv = GNUNET_DNSPARSER_parse_srv (rd[i].data,
2241  rd[i].data_size,
2242  &off);
2243  if ((NULL == srv) ||
2244  (off != rd[i].data_size))
2245  {
2246  GNUNET_break_op (0); /* record not well-formed */
2247  }
2248  else
2249  {
2250  srv->target = translate_dot_plus (rh, srv->target);
2251  scratch_start = scratch_off;
2252  if (GNUNET_OK !=
2254  sizeof(scratch),
2255  &scratch_off,
2256  srv))
2257  {
2258  GNUNET_break (0);
2259  }
2260  else
2261  {
2262  GNUNET_assert (rd_off < rd_count);
2263  rd_new[rd_off].data = &scratch[scratch_start];
2264  rd_new[rd_off].data_size = scratch_off - scratch_start;
2265  rd_off++;
2266  }
2267  }
2268  if (NULL != srv)
2270  }
2271  break;
2272 
2275  {
2276  struct GNUNET_IDENTITY_PublicKey pubkey;
2277  if (rd[i].data_size < sizeof(uint32_t))
2278  {
2279  GNUNET_break_op (0);
2280  break;
2281  }
2282  if (GNUNET_OK !=
2284  rd[i].data_size,
2285  rd[i].record_type,
2286  &pubkey))
2287  {
2288  GNUNET_break_op (0);
2289  break;
2290  }
2291  rd_off++;
2292  if (rd[i].record_type != rh->record_type)
2293  {
2294  /* try to resolve "@" */
2295  struct AuthorityChain *ac;
2296 
2297  ac = GNUNET_new (struct AuthorityChain);
2298  ac->rh = rh;
2299  ac->gns_authority = GNUNET_YES;
2303  rh->ac_tail,
2304  ac);
2306  rh);
2307  return;
2308  }
2309  }
2310  break;
2311 
2313  {
2314  /* delegation to DNS */
2316  {
2317  rd_off++;
2318  break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2319  }
2321  "Found GNS2DNS record, delegating to DNS!\n");
2322  if (GNUNET_OK ==
2324  rd_count,
2325  rd))
2326  return;
2327  else
2328  goto fail;
2329  }
2330 
2332  {
2333  /* unbox SRV/TLSA records if a specific one was requested */
2334  if ((0 != rh->protocol) &&
2335  (0 != rh->service) &&
2336  (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2337  {
2338  const struct GNUNET_GNSRECORD_BoxRecord *box;
2339 
2340  box = rd[i].data;
2341  if ((ntohs (box->protocol) == rh->protocol) &&
2342  (ntohs (box->service) == rh->service))
2343  {
2344  /* Box matches, unbox! */
2345  GNUNET_assert (rd_off < rd_count);
2346  rd_new[rd_off].record_type = ntohl (box->record_type);
2347  rd_new[rd_off].data_size -= sizeof(struct
2349  rd_new[rd_off].data = &box[1];
2350  rd_off++;
2351  }
2352  }
2353  else
2354  {
2355  /* no specific protocol/service specified, preserve all BOX
2356  records (for modern, GNS-enabled applications) */
2357  rd_off++;
2358  }
2359  break;
2360  }
2361 
2362  default:
2363  rd_off++;
2364  break;
2365  } /* end: switch */
2366  } /* end: for rd_count */
2367 
2368  /* yes, we are done, return result */
2370  "Returning GNS response for `%s' with %u answers\n",
2371  rh->ac_tail->label,
2372  rd_off);
2373  rh->proc (rh->proc_cls,
2374  rd_off,
2375  rd_new);
2377  rh);
2378  return;
2379  }
2380 
2381  switch (rd[0].record_type)
2382  {
2384  GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2386  &rd[0]);
2387  return;
2388 
2391  GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2393  &rd[0]);
2394  return;
2395 
2396  default:
2397  if (GNUNET_OK ==
2399  rd_count,
2400  rd))
2401  return;
2402  break;
2403  }
2404 fail:
2406  _ ("GNS lookup recursion failed (no delegation record found)\n"));
2407  fail_resolution (rh);
2408 }
2409 
2410 
2419 static void
2421  int32_t success,
2422  const char *emsg)
2423 {
2424  struct CacheOps *co = cls;
2425 
2426  co->namecache_qe_cache = NULL;
2427  if (GNUNET_OK != success)
2429  _ ("Failed to cache GNS resolution: %s\n"),
2430  emsg);
2431  GNUNET_CONTAINER_DLL_remove (co_head,
2432  co_tail,
2433  co);
2434  GNUNET_free (co);
2435 }
2436 
2437 
2455 static void
2457  struct GNUNET_TIME_Absolute exp,
2458  const struct GNUNET_HashCode *key,
2459  const struct GNUNET_PeerIdentity *get_path,
2460  unsigned int get_path_length,
2461  const struct GNUNET_PeerIdentity *put_path,
2462  unsigned int put_path_length,
2463  enum GNUNET_BLOCK_Type type,
2464  size_t size,
2465  const void *data)
2466 {
2467  struct GNS_ResolverHandle *rh = cls;
2468  struct AuthorityChain *ac = rh->ac_tail;
2469  const struct GNUNET_GNSRECORD_Block *block;
2470  struct CacheOps *co;
2471 
2472  (void) exp;
2473  (void) key;
2474  (void) get_path;
2475  (void) get_path_length;
2476  (void) put_path;
2477  (void) put_path_length;
2478  (void) type;
2480  rh->get_handle = NULL;
2482  rh->dht_heap_node = NULL;
2484  "Handling response from the DHT\n");
2485  if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2486  {
2487  /* how did this pass DHT block validation!? */
2488  GNUNET_break (0);
2489  fail_resolution (rh);
2490  return;
2491  }
2492  block = data;
2493  if (size != GNUNET_GNSRECORD_block_get_size (block))
2494  {
2495  /* how did this pass DHT block validation!? */
2496  GNUNET_break (0);
2497  fail_resolution (rh);
2498  return;
2499  }
2501  "Decrypting DHT block of size %lu for `%s', expires %s\n",
2503  rh->name,
2505  if (GNUNET_OK !=
2508  ac->label,
2510  rh))
2511  {
2512  GNUNET_break_op (0); /* block was ill-formed */
2513  fail_resolution (rh);
2514  return;
2515  }
2518  rel_value_us)
2519  {
2521  "Received expired block from the DHT, will not cache it.\n");
2522  return;
2523  }
2524  if (GNUNET_YES == disable_cache)
2525  return;
2526  /* Cache well-formed blocks */
2528  "Caching response from the DHT in namecache\n");
2529  co = GNUNET_new (struct CacheOps);
2530  co->namecache_qe_cache = GNUNET_NAMECACHE_block_cache (namecache_handle,
2531  block,
2532  &
2534  co);
2535  GNUNET_CONTAINER_DLL_insert (co_head,
2536  co_tail,
2537  co);
2538 }
2539 
2540 
2547 static void
2549  const struct GNUNET_HashCode *query)
2550 {
2551  struct GNS_ResolverHandle *rx;
2552 
2553  GNUNET_assert (NULL == rh->get_handle);
2554  rh->get_handle = GNUNET_DHT_get_start (dht_handle,
2556  query,
2559  NULL, 0,
2560  &handle_dht_response, rh);
2561  rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
2562  rh,
2564  abs_value_us);
2565  if (GNUNET_CONTAINER_heap_get_size (dht_lookup_heap) >
2567  {
2568  /* fail longest-standing DHT request */
2569  rx = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
2570  rx->dht_heap_node = NULL;
2571  GNUNET_assert (NULL != rx);
2572  fail_resolution (rx);
2573  }
2574 }
2575 
2576 
2585 static void
2587  unsigned int rd_count,
2588  const struct GNUNET_GNSRECORD_Data *rd)
2589 {
2590  struct GNS_ResolverHandle *rh = cls;
2591 
2592  if (0 == rd_count)
2594  _ ("GNS namecache returned empty result for `%s'\n"),
2595  rh->name);
2597  rd_count,
2598  rd);
2599 }
2600 
2601 
2608 static void
2610  const struct GNUNET_GNSRECORD_Block *block)
2611 {
2612  struct GNS_ResolverHandle *rh = cls;
2613  struct AuthorityChain *ac = rh->ac_tail;
2614  const char *label = ac->label;
2615  const struct GNUNET_IDENTITY_PublicKey *auth =
2617  struct GNUNET_HashCode query;
2618 
2619  GNUNET_assert (NULL != rh->namecache_qe);
2620  rh->namecache_qe = NULL;
2621  if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2622  ((GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2623  (ac != rh->ac_head))) &&
2624  ((NULL == block) ||
2627  rel_value_us)))
2628  {
2629  /* namecache knows nothing; try DHT lookup */
2631  label,
2632  &query);
2634  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2635  ac->label,
2637  GNUNET_h2s (&query));
2638  start_dht_request (rh, &query);
2639  return;
2640  }
2641 
2642  if ((NULL == block) ||
2645  rel_value_us))
2646  {
2647  /* DHT not permitted and no local result, fail */
2649  "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2650  ac->label,
2652  fail_resolution (rh);
2653  return;
2654  }
2656  "Received result from namecache for label `%s'\n",
2657  ac->label);
2658 
2659  if (GNUNET_OK !=
2661  auth,
2662  label,
2664  rh))
2665  {
2666  GNUNET_break_op (0); /* block was ill-formed */
2667  /* try DHT instead */
2669  label,
2670  &query);
2672  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2673  ac->label,
2675  GNUNET_h2s (&query));
2676  start_dht_request (rh, &query);
2677  return;
2678  }
2679 }
2680 
2681 
2687 static void
2689 {
2690  struct AuthorityChain *ac = rh->ac_tail;
2691  struct GNUNET_HashCode query;
2692 
2694  "Starting GNS resolution for `%s' in zone %s\n",
2695  ac->label,
2698  ac->label,
2699  &query);
2700  if (GNUNET_YES != disable_cache)
2701  {
2702  rh->namecache_qe
2703  = GNUNET_NAMECACHE_lookup_block (namecache_handle,
2704  &query,
2706  rh);
2707  GNUNET_assert (NULL != rh->namecache_qe);
2708  }
2709  else
2710  {
2711  start_dht_request (rh,
2712  &query);
2713  }
2714 }
2715 
2716 
2723 static void
2725  int is_valid)
2726 {
2727  struct GNS_ResolverHandle *rh = cls;
2728  struct AuthorityChain *ac = rh->ac_tail;
2729 
2730  rh->rev_check = NULL;
2731  if (GNUNET_YES != is_valid)
2732  {
2734  _ ("Zone %s was revoked, resolution fails\n"),
2736  fail_resolution (rh);
2737  return;
2738  }
2740 }
2741 
2742 
2748 static void
2750 {
2751  struct AuthorityChain *ac = rh->ac_tail;
2752 
2754  "Starting revocation check for zone %s\n",
2759  rh);
2760  GNUNET_assert (NULL != rh->rev_check);
2761 }
2762 
2763 
2769 static void
2771 {
2772  struct GNS_ResolverHandle *rh = cls;
2773 
2774  rh->task_id = NULL;
2775  if (rh->loop_threshold < rh->loop_limiter++)
2776  {
2778  "Encountered unbounded recursion resolving `%s'\n",
2779  rh->name);
2780  fail_resolution (rh);
2781  return;
2782  }
2783  if (GNUNET_YES == rh->ac_tail->gns_authority)
2785  else
2787 }
2788 
2789 
2796 static void
2798 {
2799  struct GNS_ResolverHandle *rh = cls;
2800  struct AuthorityChain *ac;
2801  struct in_addr v4;
2802  struct in6_addr v6;
2803 
2804  rh->task_id = NULL;
2805  if (1 == inet_pton (AF_INET,
2806  rh->name,
2807  &v4))
2808  {
2809  /* name is IPv4 address, pretend it's an A record */
2810  struct GNUNET_GNSRECORD_Data rd;
2811 
2812  rd.data = &v4;
2813  rd.data_size = sizeof(v4);
2814  rd.expiration_time = UINT64_MAX;
2816  rd.flags = 0;
2817  rh->proc (rh->proc_cls,
2818  1,
2819  &rd);
2820  GNUNET_assert (NULL == rh->task_id);
2822  rh);
2823  return;
2824  }
2825  if (1 == inet_pton (AF_INET6,
2826  rh->name,
2827  &v6))
2828  {
2829  /* name is IPv6 address, pretend it's an AAAA record */
2830  struct GNUNET_GNSRECORD_Data rd;
2831 
2832  rd.data = &v6;
2833  rd.data_size = sizeof(v6);
2834  rd.expiration_time = UINT64_MAX;
2836  rd.flags = 0;
2837  rh->proc (rh->proc_cls,
2838  1,
2839  &rd);
2840  GNUNET_assert (NULL == rh->task_id);
2842  rh);
2843  return;
2844  }
2845 
2846  ac = GNUNET_new (struct AuthorityChain);
2847  ac->rh = rh;
2849  if (NULL == ac->label)
2850  /* name was just the "TLD", so we default to label
2851  #GNUNET_GNS_EMPTY_LABEL_AT */
2853  ac->gns_authority = GNUNET_YES;
2856  rh->ac_tail,
2857  ac);
2859  rh);
2860 }
2861 
2862 
2877 struct GNS_ResolverHandle *
2879  uint32_t record_type,
2880  const char *name,
2882  uint16_t recursion_depth_limit,
2884  void *proc_cls)
2885 {
2886  struct GNS_ResolverHandle *rh;
2887 
2889  "Starting lookup for `%s'\n",
2890  name);
2891  rh = GNUNET_new (struct GNS_ResolverHandle);
2892  GNUNET_CONTAINER_DLL_insert (rlh_head,
2893  rlh_tail,
2894  rh);
2895  rh->authority_zone = *zone;
2896  rh->proc = proc;
2897  rh->proc_cls = proc_cls;
2898  rh->options = options;
2899  rh->record_type = record_type;
2900  rh->name = GNUNET_strdup (name);
2901  rh->name_resolution_pos = strlen (name);
2902  rh->loop_threshold = recursion_depth_limit;
2904  rh);
2905  return rh;
2906 }
2907 
2908 
2914 void
2916 {
2917  struct DnsResult *dr;
2918  struct AuthorityChain *ac;
2919  struct VpnContext *vpn_ctx;
2920 
2921  GNUNET_CONTAINER_DLL_remove (rlh_head,
2922  rlh_tail,
2923  rh);
2924  if (NULL != rh->dns_request)
2925  {
2927  rh->dns_request = NULL;
2928  }
2929  while (NULL != (ac = rh->ac_head))
2930  {
2932  rh->ac_tail,
2933  ac);
2934  if (GNUNET_NO == ac->gns_authority)
2935  {
2936  struct Gns2DnsPending *gp;
2937 
2938  while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2939  {
2941  ac->authority_info.dns_authority.gp_tail,
2942  gp);
2943  if (NULL != gp->rh)
2944  {
2945  /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2946  using GNS_resolver_lookup_cancel here, we need to
2947  add it first... */
2948  GNUNET_CONTAINER_DLL_insert (rlh_head,
2949  rlh_tail,
2950  gp->rh);
2951  GNUNET_assert (NULL == gp->rh->task_id);
2954  gp->rh);
2955  gp->rh = NULL;
2956  }
2957  if (NULL != gp->dns_rh)
2958  {
2960  gp->dns_rh = NULL;
2961  }
2962  GNUNET_free (gp);
2963  }
2965  }
2966  GNUNET_free (ac->label);
2967  GNUNET_free (ac);
2968  }
2969  if (NULL != rh->task_id)
2970  {
2972  rh->task_id = NULL;
2973  }
2974  if (NULL != rh->get_handle)
2975  {
2977  rh->get_handle = NULL;
2978  }
2979  if (NULL != rh->dht_heap_node)
2980  {
2982  rh->dht_heap_node = NULL;
2983  }
2984  if (NULL != (vpn_ctx = rh->vpn_ctx))
2985  {
2987  GNUNET_free (vpn_ctx->rd_data);
2988  GNUNET_free (vpn_ctx);
2989  }
2990  if (NULL != rh->namecache_qe)
2991  {
2993  rh->namecache_qe = NULL;
2994  }
2995  if (NULL != rh->rev_check)
2996  {
2998  rh->rev_check = NULL;
2999  }
3000  if (NULL != rh->std_resolve)
3001  {
3003  "Canceling standard DNS resolution\n");
3005  rh->std_resolve = NULL;
3006  }
3007  while (NULL != (dr = rh->dns_result_head))
3008  {
3010  rh->dns_result_tail,
3011  dr);
3012  GNUNET_free (dr);
3013  }
3014  GNUNET_free (rh->leho);
3015  GNUNET_free (rh->name);
3016  GNUNET_free (rh);
3017 }
3018 
3019 
3020 /* ***************** Resolver initialization ********************* */
3021 
3022 
3031 void
3033  struct GNUNET_DHT_Handle *dht,
3034  const struct GNUNET_CONFIGURATION_Handle *c,
3035  unsigned long long max_bg_queries)
3036 {
3037  cfg = c;
3038  namecache_handle = nc;
3039  dht_handle = dht;
3040  dht_lookup_heap =
3042  max_allowed_background_queries = max_bg_queries;
3044  "namecache",
3045  "DISABLE");
3046  if (GNUNET_YES == disable_cache)
3048  "Namecache disabled\n");
3049  vpn_handle = GNUNET_VPN_connect (cfg);
3050 }
3051 
3052 
3056 void
3058 {
3059  struct GNS_ResolverHandle *rh;
3060  struct CacheOps *co;
3061 
3062  /* abort active resolutions */
3063  while (NULL != (rh = rlh_head))
3064  {
3065  rh->proc (rh->proc_cls,
3066  0,
3067  NULL);
3069  }
3070  while (NULL != (co = co_head))
3071  {
3072  GNUNET_CONTAINER_DLL_remove (co_head,
3073  co_tail,
3074  co);
3076  GNUNET_free (co);
3077  }
3078  GNUNET_CONTAINER_heap_destroy (dht_lookup_heap);
3079  dht_lookup_heap = NULL;
3080  GNUNET_VPN_disconnect (vpn_handle);
3081  vpn_handle = NULL;
3082  dht_handle = NULL;
3083  namecache_handle = NULL;
3084 }
3085 
3086 
3087 /* 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
#define GNUNET_GNSRECORD_TYPE_PKEY
WARNING: This header is generated! In order to add GNS record types, you must register them in GANA...
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.
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.
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.
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_IDENTITY_PublicKey *pkey)
Convert an absolute domain name to the respective public key.
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.
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Delegation to DNS.
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:181
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_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
#define GNUNET_GNSRECORD_TYPE_BOX
Boxed records (see TLSA/SRV handling in GNS)
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.
struct GNUNET_DNSPARSER_Record * additional_records
Array of all additional answers in the packet, must contain "num_additional_records" entries...
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 currently 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.
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:178
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 being managed.
#define GNUNET_GNSRECORD_TYPE_LEHO
legacy hostnames
int found
Did we succeed in getting an IP address for any of the DNS servers listed? Once we do...
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.
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_IDENTITY_PublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.
#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
size_t GNUNET_GNSRECORD_block_get_size(const struct GNUNET_GNSRECORD_Block *block)
Returns the length of this block in bytes.
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
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 ...
#define GNUNET_GNSRECORD_TYPE_VPN
VPN resolution.
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
static struct GNUNET_IDENTITY_PublicKey pubkey
Public key of the zone to look in.
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.
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.
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
struct GNUNET_DNSPARSER_Query * queries
Array of all queries in the packet, must contain "num_queries" entries.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_IDENTITY_PublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
void GNUNET_DHT_get_stop(struct GNUNET_DHT_GetHandle *get_handle)
Stop async DHT-get.
Definition: dht_api.c:1155
void GNUNET_GNSRECORD_query_from_public_key(const struct GNUNET_IDENTITY_PublicKey *pub, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
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:86
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 cumulative result obtained to the callback and clean up the request.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
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.
struct DnsResult * prev
Kept in DLL.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_IDENTITY_PublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls)
Decrypt block.
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.
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.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_IDENTITY_PublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
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?
static void fail_resolution(struct GNS_ResolverHandle *rh)
Function called to asynchronously fail a resolution.
struct GNUNET_IDENTITY_PublicKey authority_zone
The top-level GNS authoritative zone to query.
#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).
An identity key as per LSD0001.
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
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
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.
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.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
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:232
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.
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.
#define GNUNET_GNSRECORD_TYPE_EDKEY
Record type for EDKEY zone delegations.
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:604
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
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...
struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_block_get_expiration(const struct GNUNET_GNSRECORD_Block *block)
Returns the expiration of a block.
#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.
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_IDENTITY_PublicKey *z)
Convert a zone key to a string (for printing debug messages).
struct AuthorityChain * next
This is a DLL.
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
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_IDENTITY_PublicKey *zone, uint32_t record_type, const char *name, enum GNUNET_GNS_LocalOptions options, uint16_t recursion_depth_limit, GNS_ResultProcessor proc, void *proc_cls)
Lookup of a record in a specific zone calls lookup result processor on result.
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