GNUnet  0.19.2
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_dht_service.h"
43 #include "gnunet_gnsrecord_lib.h"
45 #include "gnunet_dns_service.h"
48 #include "gnunet_gns_service.h"
49 #include "gns.h"
50 #include "gnunet-service-gns.h"
52 
53 
57 #define DHT_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
58  GNUNET_TIME_UNIT_SECONDS, 60)
59 
63 #define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \
64  GNUNET_TIME_UNIT_SECONDS, 15)
65 
69 #define DHT_GNS_REPLICATION_LEVEL 10
70 
71 
76 struct AuthorityChain;
77 
78 
85 {
90 
95 
99  struct AuthorityChain *ac;
100 
107 
112 
116  unsigned int num_results;
117 };
118 
119 
124 struct GNS_ResolverHandle;
125 
126 
132 {
137 
142 
147 
151  char *label;
152 
158 
162  union
163  {
168 
169  struct
170  {
177 
183 
189 
194 
199  int found;
200 
204  int launched;
207 };
208 
209 
213 struct DnsResult
214 {
218  struct DnsResult *next;
219 
223  struct DnsResult *prev;
224 
228  const void *data;
229 
234  uint64_t expiration_time;
235 
239  size_t data_size;
240 
244  uint32_t record_type;
245 };
246 
247 
253 {
258 
263 
268 
273 
277  void *proc_cls;
278 
283 
284 
289 
294 
299 
304 
310 
315 
320 
325 
329  char *name;
330 
335  char *leho;
336 
341 
346 
351 
356 
361  int protocol;
362 
367  int service;
368 
373 
379  unsigned int loop_limiter;
380 
384  unsigned int loop_threshold;
385 
389  uint16_t original_dns_id;
390 };
391 
392 
396 struct CacheOps
397 {
401  struct CacheOps *next;
402 
406  struct CacheOps *prev;
407 
412 };
413 
414 
419 
424 
429 
433 static unsigned long long max_allowed_background_queries;
434 
439 
444 
448 static struct CacheOps *co_head;
449 
453 static struct CacheOps *co_tail;
454 
458 static int disable_cache;
459 
463 static const struct GNUNET_CONFIGURATION_Handle *cfg;
464 
465 
481 /* dead, but keep for now */ int
482 is_canonical (const char *name)
483 {
484  const char *pos;
485  const char *dot;
486 
487  if (NULL == strchr (name,
488  (unsigned char) '.'))
489  return GNUNET_YES;
490  if ('_' != name[0])
491  return GNUNET_NO;
492  pos = &name[1];
493  while (NULL != (dot = strchr (pos,
494  (unsigned char) '.')))
495  if ('_' != dot[1])
496  return GNUNET_NO;
497  else
498  pos = dot + 1;
499  return GNUNET_YES;
500 }
501 
502 
503 /* ************************** Resolution **************************** */
504 
512 static char *
514  char *name)
515 {
516  char *ret;
517  size_t s_len = strlen (name);
518 
519  if (0 != strcmp (&name[s_len - 2],
520  ".+"))
521  return name; /* did not end in ".+" */
524  "%.*s.%s",
525  (int) (s_len - 2),
526  name,
529  GNUNET_free (name);
530  return ret;
531 }
532 
533 
540 static void
542 {
543  struct GNS_ResolverHandle *rh = cls;
544 
545  rh->task_id = NULL;
547 }
548 
549 
555 static void
557 {
558  rh->proc (rh->proc_cls,
559  0,
560  NULL);
561  GNUNET_assert (NULL == rh->task_id);
563  rh);
564 }
565 
566 
572 static void
574 {
575  struct GNS_ResolverHandle *rh = cls;
576 
577  rh->task_id = NULL;
578  fail_resolution (rh);
579 }
580 
581 
599 static char *
601 {
602  const char *rp;
603  const char *dot;
604  size_t len;
605  char *ret;
606  char *srv_name;
607  char *proto_name;
608  struct protoent *pe;
609  struct servent *se;
610 
611  if (0 == rh->name_resolution_pos)
612  return NULL;
613  dot = memrchr (rh->name,
614  (int) '.',
615  rh->name_resolution_pos);
616  if (NULL == dot)
617  {
618  /* done, this was the last one */
619  len = rh->name_resolution_pos;
620  rp = rh->name;
621  rh->name_resolution_pos = 0;
622  }
623  else if (('_' == dot[1]) &&
624  ('_' == rh->name[0]) &&
625  (dot == memchr (rh->name, (int) '.', rh->name_resolution_pos)))
626  {
634  len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
635  }
636  else
637  {
638  /* advance by one label */
639  len = rh->name_resolution_pos - (dot - rh->name) - 1;
640  rp = dot + 1;
641  rh->name_resolution_pos = dot - rh->name;
642  }
643  rh->protocol = 0;
644  rh->service = 0;
645  ret = GNUNET_strndup (rp, len);
646  /* If we have labels starting with underscore with label on
647  * the right (SRV/DANE/BOX case), determine port/protocol;
648  * The format of `rh->name` must be "_PORT._PROTOCOL".
649  */
650  if (('_' == rh->name[0]) &&
651  (NULL != (dot = memrchr (rh->name,
652  (int) '.',
653  rh->name_resolution_pos))) &&
654  ('_' == dot[1]) &&
655  (NULL == memrchr (rh->name,
656  (int) '.',
657  dot - rh->name)))
658  {
659  srv_name = GNUNET_strndup (&rh->name[1],
660  (dot - rh->name) - 1);
661  proto_name = GNUNET_strndup (&dot[2],
662  rh->name_resolution_pos - (dot - rh->name)
663  - 2);
664  rh->name_resolution_pos = 0;
665  pe = getprotobyname (proto_name);
666  if (NULL == pe)
667  {
669  _ ("Protocol `%s' unknown, skipping labels.\n"),
670  proto_name);
671  GNUNET_free (proto_name);
672  GNUNET_free (srv_name);
673  return ret;
674  }
675  se = getservbyname (srv_name,
676  proto_name);
677  if (NULL == se)
678  {
680  _ (
681  "Service `%s' unknown for protocol `%s', trying as number.\n"),
682  srv_name,
683  proto_name);
684  if (1 != sscanf (srv_name, "%u", &rh->service))
685  {
687  _ ("Service `%s' not a port, skipping service labels.\n"),
688  srv_name);
689  GNUNET_free (proto_name);
690  GNUNET_free (srv_name);
691  return ret;
692  }
693  }
694  else
695  {
696  rh->service = ntohs (se->s_port);
697  }
698  rh->protocol = pe->p_proto;
699  GNUNET_free (proto_name);
700  GNUNET_free (srv_name);
701  }
702  return ret;
703 }
704 
705 
711 static void
713 {
714  struct DnsResult *pos;
715  unsigned int n;
716  unsigned int i;
717 
718  n = 0;
719  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
720  n++;
721  {
722  struct GNUNET_GNSRECORD_Data rd[n];
723 
724  i = 0;
725  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
726  {
727  rd[i].data = pos->data;
728  rd[i].data_size = pos->data_size;
729  rd[i].record_type = pos->record_type;
737  if (0 == pos->expiration_time)
738  {
740  rd[i].expiration_time = 0;
741  }
742  else
743  {
745  }
746  i++;
747  }
748  GNUNET_assert (i == n);
750  "Transmitting standard DNS result with %u records\n",
751  n);
752  rh->proc (rh->proc_cls,
753  n,
754  rd);
755  }
757 }
758 
759 
769 static void
771  uint64_t expiration_time,
772  uint32_t record_type,
773  size_t data_size,
774  const void *data)
775 {
776  struct DnsResult *res;
777 
778  res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
779  res->expiration_time = expiration_time;
780  res->data_size = data_size;
781  res->record_type = record_type;
782  res->data = &res[1];
783  GNUNET_memcpy (&res[1],
784  data,
785  data_size);
787  rh->dns_result_tail,
788  res);
789 }
790 
791 
800 static void
801 handle_dns_result (void *cls,
802  const struct sockaddr *addr,
803  socklen_t addrlen)
804 {
805  struct GNS_ResolverHandle *rh = cls;
806  const struct sockaddr_in *sa4;
807  const struct sockaddr_in6 *sa6;
808 
809  if (NULL == addr)
810  {
811  rh->std_resolve = NULL;
813  return;
814  }
816  "Received %u bytes of DNS IP data\n",
817  addrlen);
818  switch (addr->sa_family)
819  {
820  case AF_INET:
821  sa4 = (const struct sockaddr_in *) addr;
822  add_dns_result (rh,
823  0 /* expiration time is unknown */,
825  sizeof(struct in_addr),
826  &sa4->sin_addr);
827  break;
828 
829  case AF_INET6:
830  sa6 = (const struct sockaddr_in6 *) addr;
831  add_dns_result (rh,
832  0 /* expiration time is unknown */,
834  sizeof(struct in6_addr),
835  &sa6->sin6_addr);
836  break;
837 
838  default:
839  GNUNET_break (0);
840  break;
841  }
842 }
843 
844 
850 static void
851 recursive_resolution (void *cls);
852 
853 
860 static void
861 start_resolver_lookup (void *cls);
862 
863 
872 static void
873 dns_result_parser (void *cls,
874  const struct GNUNET_TUN_DnsHeader *dns,
875  size_t dns_len)
876 {
877  struct GNS_ResolverHandle *rh = cls;
878  struct GNUNET_DNSPARSER_Packet *p;
879  const struct GNUNET_DNSPARSER_Record *rec;
880  unsigned int rd_count;
881 
882  if (NULL == dns)
883  {
884  rh->dns_request = NULL;
886  rh->task_id = NULL;
887  fail_resolution (rh);
888  return;
889  }
890  if (rh->original_dns_id != dns->id)
891  {
892  /* DNS answer, but for another query */
893  return;
894  }
895  p = GNUNET_DNSPARSER_parse ((const char *) dns,
896  dns_len);
897  if (NULL == p)
898  {
900  _ ("Failed to parse DNS response\n"));
901  return;
902  }
903 
904  /* We got a result from DNS */
906  "Received DNS response for `%s' with %u answers\n",
907  rh->ac_tail->label,
908  (unsigned int) p->num_answers);
909  if ((p->num_answers > 0) &&
910  (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
912  {
913  int af;
914 
916  "Got CNAME `%s' from DNS for `%s'\n",
917  p->answers[0].data.hostname,
918  rh->name);
919  if (NULL != rh->std_resolve)
920  {
922  "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
923  rh->name);
925  }
926  GNUNET_free (rh->name);
927  rh->name = GNUNET_strdup (p->answers[0].data.hostname);
928  rh->name_resolution_pos = strlen (rh->name);
929  switch (rh->record_type)
930  {
932  af = AF_INET;
933  break;
934 
936  af = AF_INET6;
937  break;
938 
939  default:
940  af = AF_UNSPEC;
941  break;
942  }
943  if (NULL != rh->leho)
944  add_dns_result (rh,
945  GNUNET_TIME_UNIT_HOURS.rel_value_us,
947  strlen (rh->leho),
948  rh->leho);
950  af,
953  rh);
956  rh->dns_request = NULL;
957  return;
958  }
959 
960  /* convert from (parsed) DNS to (binary) GNS format! */
961  rd_count = p->num_answers + p->num_authority_records
962  + p->num_additional_records;
963  {
964  struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
965  int skip;
966  char buf[UINT16_MAX];
967  size_t buf_off;
968  size_t buf_start;
969 
970  buf_off = 0;
971  skip = 0;
972  memset (rd,
973  0,
974  sizeof(rd));
975  for (unsigned int i = 0; i < rd_count; i++)
976  {
977  if (i < p->num_answers)
978  rec = &p->answers[i];
979  else if (i < p->num_answers + p->num_authority_records)
980  rec = &p->authority_records[i - p->num_answers];
981  else
982  rec = &p->additional_records[i - p->num_answers
983  - p->num_authority_records];
984  /* As we copied the full DNS name to 'rh->ac_tail->label', this
985  should be the correct check to see if this record is actually
986  a record for our label... */
987  if (0 != strcmp (rec->name,
988  rh->ac_tail->label))
989  {
991  "Dropping record `%s', does not match desired name `%s'\n",
992  rec->name,
993  rh->ac_tail->label);
994  skip++;
995  continue;
996  }
997  rd[i - skip].record_type = rec->type;
999  switch (rec->type)
1000  {
1002  if (rec->data.raw.data_len != sizeof(struct in_addr))
1003  {
1004  GNUNET_break_op (0);
1005  skip++;
1006  continue;
1007  }
1008  rd[i - skip].data_size = rec->data.raw.data_len;
1009  rd[i - skip].data = rec->data.raw.data;
1010  break;
1011 
1013  if (rec->data.raw.data_len != sizeof(struct in6_addr))
1014  {
1015  GNUNET_break_op (0);
1016  skip++;
1017  continue;
1018  }
1019  rd[i - skip].data_size = rec->data.raw.data_len;
1020  rd[i - skip].data = rec->data.raw.data;
1021  break;
1022 
1026  buf_start = buf_off;
1027  if (GNUNET_OK !=
1029  sizeof(buf),
1030  &buf_off,
1031  rec->data.hostname))
1032  {
1033  GNUNET_break (0);
1034  skip++;
1035  continue;
1036  }
1037  rd[i - skip].data_size = buf_off - buf_start;
1038  rd[i - skip].data = &buf[buf_start];
1039  break;
1040 
1042  buf_start = buf_off;
1043  if (GNUNET_OK !=
1045  sizeof(buf),
1046  &buf_off,
1047  rec->data.soa))
1048  {
1049  GNUNET_break (0);
1050  skip++;
1051  continue;
1052  }
1053  rd[i - skip].data_size = buf_off - buf_start;
1054  rd[i - skip].data = &buf[buf_start];
1055  break;
1056 
1058  buf_start = buf_off;
1059  if (GNUNET_OK !=
1061  sizeof(buf),
1062  &buf_off,
1063  rec->data.mx))
1064  {
1065  GNUNET_break (0);
1066  skip++;
1067  continue;
1068  }
1069  rd[i - skip].data_size = buf_off - buf_start;
1070  rd[i - skip].data = &buf[buf_start];
1071  break;
1072 
1074  buf_start = buf_off;
1075  if (GNUNET_OK !=
1077  sizeof(buf),
1078  &buf_off,
1079  rec->data.srv))
1080  {
1081  GNUNET_break (0);
1082  skip++;
1083  continue;
1084  }
1085  rd[i - skip].data_size = buf_off - buf_start;
1086  rd[i - skip].data = &buf[buf_start];
1087  break;
1088 
1089  default:
1091  _ ("Skipping record of unsupported type %d\n"),
1092  rec->type);
1093  skip++;
1094  continue;
1095  }
1096  } /* end of for all records in answer */
1097  if (NULL != rh->leho)
1098  {
1102  rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1103  rd[rd_count - skip].data = rh->leho;
1104  rd[rd_count - skip].data_size = strlen (rh->leho);
1105  skip--; /* skip one LESS */
1107  "Adding LEHO %s\n",
1108  rh->leho);
1109  }
1111  "Returning DNS response for `%s' with %u answers\n",
1112  rh->ac_tail->label,
1113  (unsigned int) (rd_count - skip));
1114  rh->proc (rh->proc_cls,
1115  rd_count - skip,
1116  rd);
1118  rh->dns_request = NULL;
1119  }
1121  if (NULL != rh->task_id)
1122  GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1124  rh);
1125 }
1126 
1127 
1136 static void
1138 {
1139  struct AuthorityChain *ac;
1140  struct GNUNET_DNSPARSER_Query *query;
1141  struct GNUNET_DNSPARSER_Packet *p;
1142  char *dns_request;
1143  size_t dns_request_length;
1144  int ret;
1145 
1146  ac = rh->ac_tail;
1147  GNUNET_assert (NULL != ac);
1149  "Starting DNS lookup for `%s'\n",
1150  ac->label);
1151  GNUNET_assert (GNUNET_NO == ac->gns_authority);
1152  query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1153  query->name = GNUNET_strdup (ac->label);
1154  query->type = rh->record_type;
1157  p->queries = query;
1158  p->num_queries = 1;
1160  UINT16_MAX);
1161  p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1162  p->flags.recursion_desired = 1;
1164  1024,
1165  &dns_request,
1166  &dns_request_length);
1167  if (GNUNET_OK != ret)
1168  {
1169  GNUNET_break (0);
1170  rh->proc (rh->proc_cls,
1171  0,
1172  NULL);
1173  GNUNET_assert (NULL == rh->task_id);
1175  rh);
1176  }
1177  else
1178  {
1179  rh->original_dns_id = p->id;
1180  GNUNET_assert (NULL != ac->authority_info.dns_authority.dns_handle);
1181  GNUNET_assert (NULL == rh->dns_request);
1182  rh->leho = GNUNET_strdup (ac->label);
1184  ac->authority_info.dns_authority.dns_handle,
1185  dns_request,
1186  dns_request_length,
1188  rh);
1191  rh);
1192  }
1193  if (GNUNET_SYSERR != ret)
1194  GNUNET_free (dns_request);
1196 }
1197 
1198 
1207 static void
1209  const char *rname)
1210 {
1211  size_t nlen;
1212  char *res;
1213  const char *tld;
1214  struct AuthorityChain *ac;
1215  int af;
1217 
1219  "Handling GNS REDIRECT result `%s'\n",
1220  rname);
1221  nlen = strlen (rname);
1222  tld = GNS_get_tld (rname);
1223  if (0 == strcmp ("+", tld))
1224  {
1225  /* REDIRECT resolution continues relative to current domain */
1226  if (0 == rh->name_resolution_pos)
1227  {
1228  res = GNUNET_strndup (rname, nlen - 2);
1229  rh->name_resolution_pos = nlen - 2;
1230  }
1231  else
1232  {
1233  GNUNET_asprintf (&res,
1234  "%.*s.%.*s",
1235  (int) rh->name_resolution_pos,
1236  rh->name,
1237  (int) (nlen - 2),
1238  rname);
1239  rh->name_resolution_pos = strlen (res);
1240  }
1241  GNUNET_free (rh->name);
1242  rh->name = res;
1243  ac = GNUNET_new (struct AuthorityChain);
1244  ac->rh = rh;
1245  ac->gns_authority = GNUNET_YES;
1246  ac->authority_info.gns_authority =
1248  ac->label = resolver_lookup_get_next_label (rh);
1249  /* add AC to tail */
1251  rh->ac_tail,
1252  ac);
1254  rh);
1255  return;
1256  }
1258  {
1259  /* REDIRECT resolution continues relative to current domain */
1260  if (0 == rh->name_resolution_pos)
1261  {
1262  GNUNET_asprintf (&res,
1263  "%.*s",
1264  (int) (strlen (rname) - (strlen (tld) + 1)),
1265  rname);
1266  }
1267  else
1268  {
1269  GNUNET_asprintf (&res,
1270  "%.*s.%.*s",
1271  (int) rh->name_resolution_pos,
1272  rh->name,
1273  (int) (strlen (rname) - (strlen (tld) + 1)),
1274  rname);
1275  }
1276  rh->name_resolution_pos = strlen (res);
1277  GNUNET_free (rh->name);
1278  rh->name = res;
1279  ac = GNUNET_new (struct AuthorityChain);
1280  ac->rh = rh;
1281  ac->gns_authority = GNUNET_YES;
1282  ac->authority_info.gns_authority = zone;
1283  ac->label = resolver_lookup_get_next_label (rh);
1284  /* add AC to tail */
1286  rh->ac_tail,
1287  ac);
1289  rh);
1290  return;
1291  }
1292 
1294  "Got REDIRECT `%s' from GNS for `%s'\n",
1295  rname,
1296  rh->name);
1297  if (NULL != rh->std_resolve)
1298  {
1300  "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1301  rh->name);
1303  }
1304  /* name is absolute, go to DNS */
1305  GNUNET_free (rh->name);
1306  rh->name = GNUNET_strdup (rname);
1307  rh->name_resolution_pos = strlen (rh->name);
1308  switch (rh->record_type)
1309  {
1311  af = AF_INET;
1312  break;
1313 
1315  af = AF_INET6;
1316  break;
1317 
1318  default:
1319  af = AF_UNSPEC;
1320  break;
1321  }
1323  "Doing standard DNS lookup for `%s'\n",
1324  rh->name);
1325 
1327  af,
1330  rh);
1331 }
1332 
1333 
1342 static void
1344  const char *cname)
1345 {
1346  int af;
1347 
1348  GNUNET_free (rh->name);
1349  rh->name = GNUNET_strdup (cname);
1350  rh->name_resolution_pos = strlen (rh->name);
1351  switch (rh->record_type)
1352  {
1354  af = AF_INET;
1355  break;
1356 
1358  af = AF_INET6;
1359  break;
1360 
1361  default:
1362  af = AF_UNSPEC;
1363  break;
1364  }
1366  "Doing standard DNS lookup for `%s'\n",
1367  rh->name);
1368 
1370  af,
1373  rh);
1374 }
1375 
1376 
1384 static void
1385 handle_gns_resolution_result (void *cls,
1386  unsigned int rd_count,
1387  const struct GNUNET_GNSRECORD_Data *rd);
1388 
1389 
1397 static void
1399 {
1400  struct GNS_ResolverHandle *rh = ac->rh;
1401 
1402  if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1403  (GNUNET_NO == ac->authority_info.dns_authority.found))
1404  return; /* more pending and none found yet */
1405  if (GNUNET_NO == ac->authority_info.dns_authority.found)
1406  {
1408  "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1409  ac->authority_info.dns_authority.name);
1410  fail_resolution (rh);
1411  return;
1412  }
1413  if (GNUNET_NO != ac->authority_info.dns_authority.launched)
1414  return; /* already running, do not launch again! */
1415  /* recurse */
1416  ac->authority_info.dns_authority.launched = GNUNET_YES;
1418  "Will continue resolution using DNS to resolve `%s'\n",
1419  ac->label);
1420  GNUNET_assert (NULL == rh->task_id);
1422  rh);
1423 }
1424 
1425 
1434 static void
1436  unsigned int rd_count,
1437  const struct GNUNET_GNSRECORD_Data *rd)
1438 {
1439  struct Gns2DnsPending *gp = cls;
1440  struct AuthorityChain *ac = gp->ac;
1441 
1442  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
1443  ac->authority_info.dns_authority.gp_tail,
1444  gp);
1445  /* enable cleanup of 'rh' handle that automatically comes after we return,
1446  and which expects 'rh' to be in the #rlh_head DLL. */
1447  if (NULL != gp->rh)
1448  {
1450  rlh_tail,
1451  gp->rh);
1452  gp->rh = NULL;
1453  }
1454  GNUNET_free (gp);
1456  "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1457  rd_count);
1458  /* find suitable A/AAAA record */
1459  for (unsigned int j = 0; j < rd_count; j++)
1460  {
1461  switch (rd[j].record_type)
1462  {
1464  {
1465  struct sockaddr_in v4;
1466 
1467  if (sizeof(struct in_addr) != rd[j].data_size)
1468  {
1469  GNUNET_break_op (0);
1470  continue;
1471  }
1472  memset (&v4,
1473  0,
1474  sizeof(v4));
1475  v4.sin_family = AF_INET;
1476  v4.sin_port = htons (53);
1477 #if HAVE_SOCKADDR_IN_SIN_LEN
1478  v4.sin_len = (u_char) sizeof(v4);
1479 #endif
1480  GNUNET_memcpy (&v4.sin_addr,
1481  rd[j].data,
1482  sizeof(struct in_addr));
1483  if (GNUNET_OK ==
1485  ac->authority_info.dns_authority.dns_handle,
1486  (const struct sockaddr *) &v4))
1487  ac->authority_info.dns_authority.found = GNUNET_YES;
1488  break;
1489  }
1490 
1492  {
1493  struct sockaddr_in6 v6;
1494 
1495  if (sizeof(struct in6_addr) != rd[j].data_size)
1496  {
1497  GNUNET_break_op (0);
1498  continue;
1499  }
1500  /* FIXME: might want to check if we support IPv6 here,
1501  and otherwise skip this one and hope we find another */
1502  memset (&v6,
1503  0,
1504  sizeof(v6));
1505  v6.sin6_family = AF_INET6;
1506  v6.sin6_port = htons (53);
1507 #if HAVE_SOCKADDR_IN_SIN_LEN
1508  v6.sin6_len = (u_char) sizeof(v6);
1509 #endif
1510  GNUNET_memcpy (&v6.sin6_addr,
1511  rd[j].data,
1512  sizeof(struct in6_addr));
1513  if (GNUNET_OK ==
1515  ac->authority_info.dns_authority.dns_handle,
1516  (const struct sockaddr *) &v6))
1517  ac->authority_info.dns_authority.found = GNUNET_YES;
1518  break;
1519  }
1520 
1521  default:
1522  break;
1523  }
1524  }
1526 }
1527 
1528 
1536 static void
1538  const struct sockaddr *addr,
1539  socklen_t addrlen)
1540 {
1541  struct Gns2DnsPending *gp = cls;
1542  struct AuthorityChain *ac = gp->ac;
1543  struct sockaddr_storage ss;
1544  struct sockaddr_in *v4;
1545  struct sockaddr_in6 *v6;
1546 
1547  if (NULL == addr)
1548  {
1549  /* DNS resolution finished */
1550  if (0 == gp->num_results)
1552  "Failed to use DNS to resolve name of DNS resolver\n");
1553  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
1554  ac->authority_info.dns_authority.gp_tail,
1555  gp);
1556  GNUNET_free (gp);
1558  return;
1559  }
1560  GNUNET_memcpy (&ss,
1561  addr,
1562  addrlen);
1563  switch (ss.ss_family)
1564  {
1565  case AF_INET:
1566  v4 = (struct sockaddr_in *) &ss;
1567  v4->sin_port = htons (53);
1568  gp->num_results++;
1569  break;
1570 
1571  case AF_INET6:
1572  v6 = (struct sockaddr_in6 *) &ss;
1573  v6->sin6_port = htons (53);
1574  gp->num_results++;
1575  break;
1576 
1577  default:
1579  "Unsupported AF %d\n",
1580  ss.ss_family);
1581  return;
1582  }
1583  if (GNUNET_OK ==
1584  GNUNET_DNSSTUB_add_dns_sa (ac->authority_info.dns_authority.dns_handle,
1585  (struct sockaddr *) &ss))
1586  ac->authority_info.dns_authority.found = GNUNET_YES;
1587 }
1588 
1589 
1596 static void
1598  const struct GNUNET_GNSRECORD_Data *rd)
1599 {
1601  rd->data);
1602 }
1603 
1604 
1611 static void
1613  const struct GNUNET_GNSRECORD_Data *rd)
1614 {
1615  char *cname;
1616  size_t off;
1617 
1618  off = 0;
1620  rd->data_size,
1621  &off);
1622  if ((NULL == cname) ||
1623  (off != rd->data_size))
1624  {
1625  GNUNET_break_op (0); /* record not well-formed */
1626  GNUNET_free (cname);
1627  fail_resolution (rh);
1628  return;
1629  }
1631  cname);
1632  GNUNET_free (cname);
1633 }
1634 
1635 
1642 static void
1644  const struct GNUNET_GNSRECORD_Data *rd)
1645 {
1646  struct AuthorityChain *ac;
1647  struct GNUNET_IDENTITY_PublicKey auth;
1648 
1649  /* delegation to another zone */
1651  rd->data_size,
1652  rd->record_type,
1653  &auth))
1654  {
1655  GNUNET_break_op (0);
1656  fail_resolution (rh);
1657  return;
1658  }
1659  /* expand authority chain */
1660  ac = GNUNET_new (struct AuthorityChain);
1661  ac->rh = rh;
1662  ac->gns_authority = GNUNET_YES;
1663  ac->authority_info.gns_authority = auth;
1664  ac->label = resolver_lookup_get_next_label (rh);
1665  /* add AC to tail */
1667  rh->ac_tail,
1668  ac);
1669  /* recurse */
1671  rh);
1672 }
1673 
1674 
1685 static int
1687  unsigned int rd_count,
1688  const struct GNUNET_GNSRECORD_Data *rd)
1689 {
1690  struct AuthorityChain *ac;
1691  const char *tld;
1692  char *ns;
1693 
1694  ns = NULL;
1695  /* expand authority chain */
1696  ac = GNUNET_new (struct AuthorityChain);
1697  ac->rh = rh;
1698  ac->authority_info.dns_authority.dns_handle = GNUNET_DNSSTUB_start (4);
1699 
1700  for (unsigned int i = 0; i < rd_count; i++)
1701  {
1702  char *ip;
1703  char *n;
1704  size_t off;
1705  struct Gns2DnsPending *gp;
1707  struct sockaddr_in v4;
1708  struct sockaddr_in6 v6;
1709 
1710  if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1711  {
1715  GNUNET_free (ns);
1716  GNUNET_free (ac);
1717  return GNUNET_SYSERR;
1718  }
1719  off = 0;
1721  rd[i].data_size,
1722  &off);
1723  ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1724  if ((NULL == n) ||
1725  (NULL == ip))
1726  {
1727  GNUNET_break_op (0);
1728  GNUNET_free (n);
1729  GNUNET_free (ip);
1730  continue;
1731  }
1732 
1733  off += strlen (ip) + 1;
1734 
1735  if (off != rd[i].data_size)
1736  {
1737  GNUNET_break_op (0);
1738  GNUNET_free (n);
1739  GNUNET_free (ip);
1740  continue;
1741  }
1742  /* resolve 'ip' to determine the IP(s) of the DNS
1743  resolver to use for lookup of 'ns' */
1744  if (NULL != ns)
1745  {
1746  if (0 != strcasecmp (ns,
1747  n))
1748  {
1749  /* NS values must all be the same for all GNS2DNS records,
1750  anything else leads to insanity */
1751  GNUNET_break_op (0);
1752  GNUNET_free (n);
1753  GNUNET_free (ip);
1754  continue;
1755  }
1756  GNUNET_free (n);
1757  }
1758  else
1759  {
1760  ns = n;
1761  }
1762 
1763  /* check if 'ip' is already an IPv4/IPv6 address */
1764  if ((1 == inet_pton (AF_INET,
1765  ip,
1766  &v4)) ||
1767  (1 == inet_pton (AF_INET6,
1768  ip,
1769  &v6)))
1770  {
1773  ac->authority_info.dns_authority.dns_handle,
1774  ip));
1775  ac->authority_info.dns_authority.found = GNUNET_YES;
1776  GNUNET_free (ip);
1777  continue;
1778  }
1779  tld = GNS_get_tld (ip);
1780  if ((0 != strcmp (tld, "+")) &&
1782  {
1783  /* 'ip' is a DNS name */
1784  gp = GNUNET_new (struct Gns2DnsPending);
1785  gp->ac = ac;
1786  GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
1787  ac->authority_info.dns_authority.gp_tail,
1788  gp);
1789  gp->dns_rh = GNUNET_RESOLVER_ip_get (ip,
1790  AF_UNSPEC,
1793  gp);
1794  GNUNET_free (ip);
1795  continue;
1796  }
1797  /* 'ip' should be a GNS name */
1798  gp = GNUNET_new (struct Gns2DnsPending);
1799  gp->ac = ac;
1800  GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
1801  ac->authority_info.dns_authority.gp_tail,
1802  gp);
1803  gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1804  if (0 == strcmp (tld, "+"))
1805  {
1806  ip = translate_dot_plus (rh,
1807  ip);
1808  tld = GNS_get_tld (ip);
1809  if (GNUNET_OK !=
1811  &zone))
1812  {
1813  GNUNET_break_op (0);
1814  GNUNET_free (ip);
1815  continue;
1816  }
1817  }
1818  gp->rh->authority_zone = zone;
1820  "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1821  ip,
1822  ns);
1823  gp->rh->name = ip;
1824  gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1825  gp->rh->proc = &handle_gns2dns_result;
1826  gp->rh->proc_cls = gp;
1829  gp->rh->loop_limiter = rh->loop_limiter + 1;
1830  gp->rh->loop_threshold = rh->loop_threshold;
1831  gp->rh->task_id
1833  gp->rh);
1834  } /* end 'for all records' */
1835 
1836  if (NULL == ns)
1837  {
1838  /* not a single GNS2DNS record found */
1839  GNUNET_free (ac);
1840  return GNUNET_SYSERR;
1841  }
1843  strcpy (ac->authority_info.dns_authority.name,
1844  ns);
1845  /* for DNS recursion, the label is the full DNS name,
1846  created from the remainder of the GNS name and the
1847  name in the NS record */
1848  GNUNET_asprintf (&ac->label,
1849  "%.*s%s%s",
1850  (int) rh->name_resolution_pos,
1851  rh->name,
1852  (0 != rh->name_resolution_pos) ? "." : "",
1853  ns);
1854  GNUNET_free (ns);
1855 
1856  {
1857  /* the GNS name is UTF-8 and may include multibyte chars.
1858  * We have to convert the combined name to a DNS-compatible IDNA.
1859  */
1860  char *tmp = ac->label;
1861 
1862  if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1863  &ac->label,
1864  IDNA_ALLOW_UNASSIGNED))
1865  {
1867  _ ("Name `%s' cannot be converted to IDNA."),
1868  tmp);
1869  GNUNET_free (tmp);
1870  GNUNET_free (ac);
1871  return GNUNET_SYSERR;
1872  }
1873  GNUNET_free (tmp);
1874  }
1875 
1877  rh->ac_tail,
1878  ac);
1879  if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1880  {
1882  _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1883  ac->label);
1884  GNUNET_free (ac->label);
1885  GNUNET_free (ac);
1886  return GNUNET_SYSERR;
1887  }
1889  return GNUNET_OK;
1890 }
1891 
1892 
1893 static void
1895  unsigned int rd_count,
1896  const struct GNUNET_GNSRECORD_Data *rd)
1897 {
1898  struct GNS_ResolverHandle *rh = cls;
1899  char *cname;
1900  char scratch[UINT16_MAX];
1901  size_t scratch_off;
1902  size_t scratch_start;
1903  size_t off;
1904  struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1905  unsigned int rd_off;
1906 
1908  "Resolution succeeded for `%s' in zone %s, got %u records\n",
1909  rh->ac_tail->label,
1911  rd_count);
1912  if (0 == rd_count)
1913  {
1915  _ ("GNS lookup failed (zero records found for `%s')\n"),
1916  rh->name);
1917  fail_resolution (rh);
1918  return;
1919  }
1920 
1921  if (0 == rh->name_resolution_pos)
1922  {
1923  /* top-level match, are we done yet? */
1924  if ((rd_count > 0) &&
1927  {
1928  off = 0;
1929  cname = GNUNET_DNSPARSER_parse_name (rd[0].data,
1930  rd[0].data_size,
1931  &off);
1932  if ((NULL == cname) ||
1933  (off != rd[0].data_size))
1934  {
1935  GNUNET_break_op (0);
1936  GNUNET_free (cname);
1937  fail_resolution (rh);
1938  return;
1939  }
1941  cname);
1942  GNUNET_free (cname);
1943  return;
1944  }
1945  if ((rd_count > 0) &&
1948  {
1950  rd[0].data);
1951  return;
1952  }
1953 
1954 
1955  /* If A/AAAA was requested,
1956  * but we got a GNS2DNS record */
1957  if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
1959  {
1960  for (unsigned int i = 0; i < rd_count; i++)
1961  {
1962  switch (rd[i].record_type)
1963  {
1965  {
1966  /* delegation to DNS */
1968  "Found GNS2DNS record, delegating to DNS!\n");
1969  if (GNUNET_OK ==
1971  rd_count,
1972  rd))
1973  return;
1974  else
1975  goto fail;
1976  }
1977 
1978  default:
1979  break;
1980  } /* end: switch */
1981  } /* end: for rd */
1982  } /* end: name_resolution_pos */
1983  /* convert relative names in record values to absolute names,
1984  using 'scratch' array for memory allocations */
1985  scratch_off = 0;
1986  rd_off = 0;
1987  for (unsigned int i = 0; i < rd_count; i++)
1988  {
1989  GNUNET_assert (rd_off <= i);
1990  if ((0 != rh->protocol) &&
1991  (0 != rh->service) &&
1993  continue; /* we _only_ care about boxed records */
1994 
1995  GNUNET_assert (rd_off < rd_count);
1996  rd_new[rd_off] = rd[i];
1997  /* Check if the embedded name(s) end in "+", and if so,
1998  replace the "+" with the zone at "ac_tail", changing the name
1999  to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2000  so we can free it afterwards. */
2001  switch (rd[i].record_type)
2002  {
2004  {
2005  char *rname;
2006  rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2007  rname = translate_dot_plus (rh, rname);
2008  GNUNET_break (NULL != rname);
2009  scratch_start = scratch_off;
2010  memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2011  scratch_off += strlen (rname) + 1;
2012  GNUNET_assert (rd_off < rd_count);
2013  rd_new[rd_off].data = &scratch[scratch_start];
2014  rd_new[rd_off].data_size = scratch_off - scratch_start;
2015  rd_off++;
2016  GNUNET_free (rname);
2017  }
2018  break;
2019 
2021  {
2022  char *cname;
2023 
2024  off = 0;
2025  cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
2026  rd[i].data_size,
2027  &off);
2028  if ((NULL == cname) ||
2029  (off != rd[i].data_size))
2030  {
2031  GNUNET_break_op (0); /* record not well-formed */
2032  }
2033  else
2034  {
2035  cname = translate_dot_plus (rh, cname);
2036  GNUNET_break (NULL != cname);
2037  scratch_start = scratch_off;
2038  if (GNUNET_OK !=
2040  sizeof(scratch),
2041  &scratch_off,
2042  cname))
2043  {
2044  GNUNET_break (0);
2045  }
2046  else
2047  {
2048  GNUNET_assert (rd_off < rd_count);
2049  rd_new[rd_off].data = &scratch[scratch_start];
2050  rd_new[rd_off].data_size = scratch_off - scratch_start;
2051  rd_off++;
2052  }
2053  }
2054  GNUNET_free (cname);
2055  }
2056  break;
2057 
2059  {
2060  struct GNUNET_DNSPARSER_SoaRecord *soa;
2061 
2062  off = 0;
2064  rd[i].data_size,
2065  &off);
2066  if ((NULL == soa) ||
2067  (off != rd[i].data_size))
2068  {
2069  GNUNET_break_op (0); /* record not well-formed */
2070  }
2071  else
2072  {
2073  soa->mname = translate_dot_plus (rh, soa->mname);
2074  soa->rname = translate_dot_plus (rh, soa->rname);
2075  scratch_start = scratch_off;
2076  if (GNUNET_OK !=
2078  sizeof(scratch),
2079  &scratch_off,
2080  soa))
2081  {
2082  GNUNET_break (0);
2083  }
2084  else
2085  {
2086  GNUNET_assert (rd_off < rd_count);
2087  rd_new[rd_off].data = &scratch[scratch_start];
2088  rd_new[rd_off].data_size = scratch_off - scratch_start;
2089  rd_off++;
2090  }
2091  }
2092  if (NULL != soa)
2094  }
2095  break;
2096 
2098  {
2099  struct GNUNET_DNSPARSER_MxRecord *mx;
2100 
2101  off = 0;
2103  rd[i].data_size,
2104  &off);
2105  if ((NULL == mx) ||
2106  (off != rd[i].data_size))
2107  {
2108  GNUNET_break_op (0); /* record not well-formed */
2109  }
2110  else
2111  {
2112  mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2113  scratch_start = scratch_off;
2114  if (GNUNET_OK !=
2116  sizeof(scratch),
2117  &scratch_off,
2118  mx))
2119  {
2120  GNUNET_break (0);
2121  }
2122  else
2123  {
2124  GNUNET_assert (rd_off < rd_count);
2125  rd_new[rd_off].data = &scratch[scratch_start];
2126  rd_new[rd_off].data_size = scratch_off - scratch_start;
2127  rd_off++;
2128  }
2129  }
2130  if (NULL != mx)
2132  }
2133  break;
2134 
2136  {
2137  struct GNUNET_DNSPARSER_SrvRecord *srv;
2138 
2139  off = 0;
2141  rd[i].data_size,
2142  &off);
2143  if ((NULL == srv) ||
2144  (off != rd[i].data_size))
2145  {
2146  GNUNET_break_op (0); /* record not well-formed */
2147  }
2148  else
2149  {
2150  srv->target = translate_dot_plus (rh, srv->target);
2151  scratch_start = scratch_off;
2152  if (GNUNET_OK !=
2154  sizeof(scratch),
2155  &scratch_off,
2156  srv))
2157  {
2158  GNUNET_break (0);
2159  }
2160  else
2161  {
2162  GNUNET_assert (rd_off < rd_count);
2163  rd_new[rd_off].data = &scratch[scratch_start];
2164  rd_new[rd_off].data_size = scratch_off - scratch_start;
2165  rd_off++;
2166  }
2167  }
2168  if (NULL != srv)
2170  }
2171  break;
2172 
2175  {
2177  if (rd[i].data_size < sizeof(uint32_t))
2178  {
2179  GNUNET_break_op (0);
2180  break;
2181  }
2182  if (GNUNET_OK !=
2184  rd[i].data_size,
2185  rd[i].record_type,
2186  &pubkey))
2187  {
2188  GNUNET_break_op (0);
2189  break;
2190  }
2191  rd_off++;
2192  if (rd[i].record_type != rh->record_type)
2193  {
2194  /* try to resolve "@" */
2195  struct AuthorityChain *ac;
2196 
2197  ac = GNUNET_new (struct AuthorityChain);
2198  ac->rh = rh;
2199  ac->gns_authority = GNUNET_YES;
2200  ac->authority_info.gns_authority = pubkey;
2203  rh->ac_tail,
2204  ac);
2206  rh);
2207  return;
2208  }
2209  }
2210  break;
2211 
2213  {
2214  /* delegation to DNS */
2216  {
2217  rd_off++;
2218  break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2219  }
2221  "Found GNS2DNS record, delegating to DNS!\n");
2222  if (GNUNET_OK ==
2224  rd_count,
2225  rd))
2226  return;
2227  else
2228  goto fail;
2229  }
2230 
2232  {
2233  /* unbox SRV/TLSA records if a specific one was requested */
2234  if ((0 != rh->protocol) &&
2235  (0 != rh->service) &&
2236  (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2237  {
2238  const struct GNUNET_GNSRECORD_BoxRecord *box;
2239 
2240  box = rd[i].data;
2242  "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2243  ntohs (box->protocol), ntohs (box->service),
2244  rh->protocol, rh->service);
2245  if ((ntohs (box->protocol) == rh->protocol) &&
2246  (ntohs (box->service) == rh->service))
2247  {
2248  /* Box matches, unbox! */
2249  GNUNET_assert (rd_off < rd_count);
2250  rd_new[rd_off].record_type = ntohl (box->record_type);
2251  rd_new[rd_off].data_size -= sizeof(struct
2253  rd_new[rd_off].data = &box[1];
2254  rd_off++;
2255  }
2256  }
2257  else
2258  {
2259  /* no specific protocol/service specified, preserve all BOX
2260  records (for modern, GNS-enabled applications) */
2261  rd_off++;
2262  }
2263  break;
2264  }
2265 
2266  default:
2267  rd_off++;
2268  break;
2269  } /* end: switch */
2270  } /* end: for rd_count */
2271 
2272  /* yes, we are done, return result */
2274  "Returning GNS response for `%s' with %u answers\n",
2275  rh->ac_tail->label,
2276  rd_off);
2277  rh->proc (rh->proc_cls,
2278  rd_off,
2279  rd_new);
2281  rh);
2282  return;
2283  }
2284 
2285  switch (rd[0].record_type)
2286  {
2288  GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2290  &rd[0]);
2291  return;
2292 
2294  GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2296  &rd[0]);
2297  return;
2298 
2301  GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2303  &rd[0]);
2304  return;
2305 
2307  if (GNUNET_OK ==
2309  rd_count,
2310  rd))
2311  return;
2312  break;
2313  default:
2315  return;
2317  _ ("Unable to process critical delegation record\n"));
2318  break;
2319  }
2320 fail:
2322  _ ("GNS lookup recursion failed (no delegation record found)\n"));
2323  fail_resolution (rh);
2324 }
2325 
2326 
2335 static void
2337  int32_t success,
2338  const char *emsg)
2339 {
2340  struct CacheOps *co = cls;
2341 
2342  co->namecache_qe_cache = NULL;
2343  if (GNUNET_OK != success)
2345  _ ("Failed to cache GNS resolution: %s\n"),
2346  emsg);
2348  co_tail,
2349  co);
2350  GNUNET_free (co);
2351 }
2352 
2353 
2372 static void
2374  struct GNUNET_TIME_Absolute exp,
2375  const struct GNUNET_HashCode *key,
2376  const struct GNUNET_PeerIdentity *trunc_peer,
2377  const struct GNUNET_DHT_PathElement *get_path,
2378  unsigned int get_path_length,
2379  const struct GNUNET_DHT_PathElement *put_path,
2380  unsigned int put_path_length,
2381  enum GNUNET_BLOCK_Type type,
2382  size_t size,
2383  const void *data)
2384 {
2385  struct GNS_ResolverHandle *rh = cls;
2386  struct AuthorityChain *ac = rh->ac_tail;
2387  const struct GNUNET_GNSRECORD_Block *block;
2388  struct CacheOps *co;
2389 
2390  (void) exp;
2391  (void) key;
2392  (void) get_path;
2393  (void) get_path_length;
2394  (void) put_path;
2395  (void) put_path_length;
2396  (void) type;
2398  rh->get_handle = NULL;
2400  rh->dht_heap_node = NULL;
2402  "Handling response from the DHT\n");
2403  if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2404  {
2405  /* how did this pass DHT block validation!? */
2406  GNUNET_break (0);
2407  fail_resolution (rh);
2408  return;
2409  }
2410  block = data;
2411  if (size != GNUNET_GNSRECORD_block_get_size (block))
2412  {
2413  /* how did this pass DHT block validation!? */
2414  GNUNET_break (0);
2415  fail_resolution (rh);
2416  return;
2417  }
2419  "Decrypting DHT block of size %lu for `%s', expires %s\n",
2421  rh->name,
2423  if (GNUNET_OK !=
2425  &ac->authority_info.gns_authority,
2426  ac->label,
2428  rh))
2429  {
2430  GNUNET_break_op (0); /* block was ill-formed */
2431  fail_resolution (rh);
2432  return;
2433  }
2436  rel_value_us)
2437  {
2439  "Received expired block from the DHT, will not cache it.\n");
2440  return;
2441  }
2442  if (GNUNET_YES == disable_cache)
2443  return;
2444  /* Cache well-formed blocks */
2446  "Caching response from the DHT in namecache\n");
2447  co = GNUNET_new (struct CacheOps);
2449  block,
2450  &
2452  co);
2454  co_tail,
2455  co);
2456 }
2457 
2458 
2465 static void
2467  const struct GNUNET_HashCode *query)
2468 {
2469  struct GNS_ResolverHandle *rx;
2470 
2471  GNUNET_assert (NULL == rh->get_handle);
2474  query,
2477  NULL, 0,
2478  &handle_dht_response, rh);
2480  rh,
2482  abs_value_us);
2485  {
2486  /* fail longest-standing DHT request */
2488  rx->dht_heap_node = NULL;
2489  GNUNET_assert (NULL != rx);
2490  fail_resolution (rx);
2491  }
2492 }
2493 
2494 
2503 static void
2505  unsigned int rd_count,
2506  const struct GNUNET_GNSRECORD_Data *rd)
2507 {
2508  struct GNS_ResolverHandle *rh = cls;
2509 
2510  if (0 == rd_count)
2512  _ ("GNS namecache returned empty result for `%s'\n"),
2513  rh->name);
2515  rd_count,
2516  rd);
2517 }
2518 
2519 
2526 static void
2528  const struct GNUNET_GNSRECORD_Block *block)
2529 {
2530  struct GNS_ResolverHandle *rh = cls;
2531  struct AuthorityChain *ac = rh->ac_tail;
2532  const char *label = ac->label;
2533  const struct GNUNET_IDENTITY_PublicKey *auth =
2534  &ac->authority_info.gns_authority;
2535  struct GNUNET_HashCode query;
2536 
2537  GNUNET_assert (NULL != rh->namecache_qe);
2538  rh->namecache_qe = NULL;
2539  if (NULL == block)
2541  "No block found\n");
2542  else
2544  "Got block with expiration %s\n",
2547  if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2548  ((GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2549  (ac != rh->ac_head))) &&
2550  ((NULL == block) ||
2553  rel_value_us)))
2554  {
2555  /* namecache knows nothing; try DHT lookup */
2557  label,
2558  &query);
2560  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2561  ac->label,
2562  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority),
2563  GNUNET_h2s (&query));
2564  start_dht_request (rh, &query);
2565  return;
2566  }
2567 
2568  if ((NULL == block) ||
2571  rel_value_us))
2572  {
2573  /* DHT not permitted and no local result, fail */
2575  "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2576  ac->label,
2577  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2578  fail_resolution (rh);
2579  return;
2580  }
2582  "Received result from namecache for label `%s'\n",
2583  ac->label);
2584 
2585  if (GNUNET_OK !=
2587  auth,
2588  label,
2590  rh))
2591  {
2592  GNUNET_break_op (0); /* block was ill-formed */
2593  /* try DHT instead */
2595  label,
2596  &query);
2598  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2599  ac->label,
2600  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority),
2601  GNUNET_h2s (&query));
2602  start_dht_request (rh, &query);
2603  return;
2604  }
2605 }
2606 
2607 
2613 static void
2615 {
2616  struct AuthorityChain *ac = rh->ac_tail;
2617  struct GNUNET_HashCode query;
2618 
2620  "Starting GNS resolution for `%s' in zone %s\n",
2621  ac->label,
2622  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2623  GNUNET_GNSRECORD_query_from_public_key (&ac->authority_info.gns_authority,
2624  ac->label,
2625  &query);
2626  if (GNUNET_YES != disable_cache)
2627  {
2628  rh->namecache_qe
2630  &query,
2632  rh);
2633  GNUNET_assert (NULL != rh->namecache_qe);
2634  }
2635  else
2636  {
2637  start_dht_request (rh,
2638  &query);
2639  }
2640 }
2641 
2642 
2649 static void
2651  int is_valid)
2652 {
2653  struct GNS_ResolverHandle *rh = cls;
2654  struct AuthorityChain *ac = rh->ac_tail;
2655 
2656  rh->rev_check = NULL;
2657  if (GNUNET_YES != is_valid)
2658  {
2660  _ ("Zone %s was revoked, resolution fails\n"),
2661  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2662  fail_resolution (rh);
2663  return;
2664  }
2666 }
2667 
2668 
2674 static void
2676 {
2677  struct AuthorityChain *ac = rh->ac_tail;
2678 
2680  "Starting revocation check for zone %s\n",
2681  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2683  &ac->authority_info.gns_authority,
2685  rh);
2686  GNUNET_assert (NULL != rh->rev_check);
2687 }
2688 
2689 
2690 static void
2692 {
2693  struct GNS_ResolverHandle *rh = cls;
2694 
2695  rh->task_id = NULL;
2696  if (rh->loop_threshold < rh->loop_limiter++)
2697  {
2699  "Encountered unbounded recursion resolving `%s'\n",
2700  rh->name);
2701  fail_resolution (rh);
2702  return;
2703  }
2704  if (GNUNET_YES == rh->ac_tail->gns_authority)
2706  else
2708 }
2709 
2710 
2711 static void
2713 {
2714  struct GNS_ResolverHandle *rh = cls;
2715  struct AuthorityChain *ac;
2716  struct in_addr v4;
2717  struct in6_addr v6;
2718 
2719  rh->task_id = NULL;
2720  if (1 == inet_pton (AF_INET,
2721  rh->name,
2722  &v4))
2723  {
2724  /* name is IPv4 address, pretend it's an A record */
2725  struct GNUNET_GNSRECORD_Data rd;
2726 
2727  rd.data = &v4;
2728  rd.data_size = sizeof(v4);
2729  rd.expiration_time = UINT64_MAX;
2731  rd.flags = 0;
2732  rh->proc (rh->proc_cls,
2733  1,
2734  &rd);
2735  GNUNET_assert (NULL == rh->task_id);
2737  rh);
2738  return;
2739  }
2740  if (1 == inet_pton (AF_INET6,
2741  rh->name,
2742  &v6))
2743  {
2744  /* name is IPv6 address, pretend it's an AAAA record */
2745  struct GNUNET_GNSRECORD_Data rd;
2746 
2747  rd.data = &v6;
2748  rd.data_size = sizeof(v6);
2749  rd.expiration_time = UINT64_MAX;
2751  rd.flags = 0;
2752  rh->proc (rh->proc_cls,
2753  1,
2754  &rd);
2755  GNUNET_assert (NULL == rh->task_id);
2757  rh);
2758  return;
2759  }
2760 
2761  ac = GNUNET_new (struct AuthorityChain);
2762  ac->rh = rh;
2763  ac->label = resolver_lookup_get_next_label (rh);
2764  if (NULL == ac->label)
2765  /* name was just the "TLD", so we default to label
2766  #GNUNET_GNS_EMPTY_LABEL_AT */
2768  ac->gns_authority = GNUNET_YES;
2769  ac->authority_info.gns_authority = rh->authority_zone;
2771  rh->ac_tail,
2772  ac);
2774  rh);
2775 }
2776 
2777 
2792 struct GNS_ResolverHandle *
2794  uint32_t record_type,
2795  const char *name,
2797  uint16_t recursion_depth_limit,
2799  void *proc_cls)
2800 {
2801  struct GNS_ResolverHandle *rh;
2802 
2804  "Starting lookup for `%s'\n",
2805  name);
2806  rh = GNUNET_new (struct GNS_ResolverHandle);
2808  rlh_tail,
2809  rh);
2810  rh->authority_zone = *zone;
2811  rh->proc = proc;
2812  rh->proc_cls = proc_cls;
2813  rh->options = options;
2814  rh->record_type = record_type;
2815  rh->name = GNUNET_strdup (name);
2816  rh->name_resolution_pos = strlen (name);
2817  rh->loop_threshold = recursion_depth_limit;
2819  rh);
2820  return rh;
2821 }
2822 
2823 
2829 void
2831 {
2832  struct DnsResult *dr;
2833  struct AuthorityChain *ac;
2834 
2836  rlh_tail,
2837  rh);
2838  if (NULL != rh->dns_request)
2839  {
2841  rh->dns_request = NULL;
2842  }
2843  while (NULL != (ac = rh->ac_head))
2844  {
2846  rh->ac_tail,
2847  ac);
2848  if (GNUNET_NO == ac->gns_authority)
2849  {
2850  struct Gns2DnsPending *gp;
2851 
2852  while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2853  {
2854  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
2855  ac->authority_info.dns_authority.gp_tail,
2856  gp);
2857  if (NULL != gp->rh)
2858  {
2859  /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2860  using GNS_resolver_lookup_cancel here, we need to
2861  add it first... */
2863  rlh_tail,
2864  gp->rh);
2865  GNUNET_assert (NULL == gp->rh->task_id);
2868  gp->rh);
2869  gp->rh = NULL;
2870  }
2871  if (NULL != gp->dns_rh)
2872  {
2874  gp->dns_rh = NULL;
2875  }
2876  GNUNET_free (gp);
2877  }
2878  GNUNET_DNSSTUB_stop (ac->authority_info.dns_authority.dns_handle);
2879  }
2880  GNUNET_free (ac->label);
2881  GNUNET_free (ac);
2882  }
2883  if (NULL != rh->task_id)
2884  {
2886  rh->task_id = NULL;
2887  }
2888  if (NULL != rh->get_handle)
2889  {
2891  rh->get_handle = NULL;
2892  }
2893  if (NULL != rh->dht_heap_node)
2894  {
2896  rh->dht_heap_node = NULL;
2897  }
2898  if (NULL != rh->namecache_qe)
2899  {
2901  rh->namecache_qe = NULL;
2902  }
2903  if (NULL != rh->rev_check)
2904  {
2906  rh->rev_check = NULL;
2907  }
2908  if (NULL != rh->std_resolve)
2909  {
2911  "Canceling standard DNS resolution\n");
2913  rh->std_resolve = NULL;
2914  }
2915  while (NULL != (dr = rh->dns_result_head))
2916  {
2919  dr);
2920  GNUNET_free (dr);
2921  }
2922  GNUNET_free (rh->leho);
2923  GNUNET_free (rh->name);
2924  GNUNET_free (rh);
2925 }
2926 
2927 
2928 /* ***************** Resolver initialization ********************* */
2929 
2930 
2939 void
2941  struct GNUNET_DHT_Handle *dht,
2942  const struct GNUNET_CONFIGURATION_Handle *c,
2943  unsigned long long max_bg_queries)
2944 {
2945  cfg = c;
2946  namecache_handle = nc;
2947  dht_handle = dht;
2948  dht_lookup_heap =
2950  max_allowed_background_queries = max_bg_queries;
2952  "namecache",
2953  "DISABLE");
2954  if (GNUNET_YES == disable_cache)
2956  "Namecache disabled\n");
2957 }
2958 
2959 
2963 void
2965 {
2966  struct GNS_ResolverHandle *rh;
2967  struct CacheOps *co;
2968 
2969  /* abort active resolutions */
2970  while (NULL != (rh = rlh_head))
2971  {
2972  rh->proc (rh->proc_cls,
2973  0,
2974  NULL);
2976  }
2977  while (NULL != (co = co_head))
2978  {
2980  co_tail,
2981  co);
2983  GNUNET_free (co);
2984  }
2986  dht_lookup_heap = NULL;
2987  dht_handle = NULL;
2988  namecache_handle = NULL;
2989 }
2990 
2991 
2992 /* end of gnunet-service-gns_resolver.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
#define memrchr(s, c, n)
Definition: compat.h:49
#define GNUNET_GNSRECORD_TYPE_BOX
Boxed records (see TLSA/SRV handling in GNS)
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Delegation to DNS.
#define GNUNET_GNSRECORD_TYPE_REDIRECT
Resolver redirects.
#define GNUNET_GNSRECORD_TYPE_LEHO
legacy hostnames
#define GNUNET_GNSRECORD_TYPE_PKEY
WARNING: This header is generated! In order to add GNS record types, you must register them in GANA,...
#define GNUNET_GNSRECORD_TYPE_EDKEY
Record type for EDKEY zone delegations.
GNUNET_BLOCK_Type
WARNING: This header is generated! In order to add DHT block types, you must register them in GANA,...
@ GNUNET_BLOCK_TYPE_GNS_NAMERECORD
Block for storing GNS record data.
IPC messages between GNS API and GNS service.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_NAMESTORE_Handle * ns
Handle to the namestore.
Definition: gnunet-abd.c:41
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static int res
static struct GNUNET_DHT_Handle * dht
Handle to the DHT.
struct GNUNET_HashCode key
The key used in the DHT.
uint32_t data
The data value.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static struct GNUNET_IDENTITY_PublicKey pubkey
Public key of the zone to look in.
static char * zone
Name of the zone being managed.
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
static char * rp
Relying party.
static struct GNUNET_PEERINFO_NotifyContext * nc
Iterator context.
const char * GNS_get_tld(const char *name)
Obtain the TLD of the given name.
GNU Name System (main service)
#define DNS_LOOKUP_TIMEOUT
Default timeout for DNS lookups.
static int disable_cache
Use namecache.
void GNS_resolver_init(struct GNUNET_NAMECACHE_Handle *nc, struct GNUNET_DHT_Handle *dht, const struct GNUNET_CONFIGURATION_Handle *c, unsigned long long max_bg_queries)
Initialize the resolver.
static unsigned long long max_allowed_background_queries
Maximum amount of parallel queries to the DHT.
static void start_dht_request(struct GNS_ResolverHandle *rh, const struct GNUNET_HashCode *query)
Initiate a DHT query for a set of GNS records.
static void handle_gns2dns_ip(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Function called by the resolver for each address obtained from DNS.
static void handle_revocation_result(void *cls, int is_valid)
Function called with the result from a revocation check.
int is_canonical(const char *name)
Determine if this name is canonical (is a legal name in a zone, without delegation); note that we do ...
static void recursive_pkey_resolution(struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
We found a PKEY record, perform recursive resolution on it.
static void recursive_resolution(void *cls)
Task scheduled to continue with the resolution process.
static void start_resolver_lookup(void *cls)
Begin the resolution process from 'name', starting with the identification of the zone specified by '...
static char * resolver_lookup_get_next_label(struct GNS_ResolverHandle *rh)
Get the next, rightmost label from the name that we are trying to resolve, and update the resolution ...
static struct GNS_ResolverHandle * rlh_tail
Tail of resolver lookup list.
static void transmit_lookup_dns_result(struct GNS_ResolverHandle *rh)
Gives the cumulative result obtained to the callback and clean up the request.
static void recursive_gns_resolution_namecache(struct GNS_ResolverHandle *rh)
Lookup tail of our authority chain in the namecache.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Global configuration.
static void fail_resolution(struct GNS_ResolverHandle *rh)
Function called to asynchronously fail a resolution.
static void handle_namecache_block_response(void *cls, const struct GNUNET_GNSRECORD_Block *block)
Process a record that was stored in the namecache.
static void recursive_cname_resolution(struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
We found a CNAME record, perform recursive resolution on it.
static void handle_gns_redirect_result(struct GNS_ResolverHandle *rh, const char *rname)
We encountered a REDIRECT record during our resolution.
static void add_dns_result(struct GNS_ResolverHandle *rh, uint64_t expiration_time, uint32_t record_type, size_t data_size, const void *data)
Add a result from DNS to the records to be returned to the application.
static void recursive_gns_resolution_revocation(struct GNS_ResolverHandle *rh)
Perform revocation check on tail of our authority chain.
static struct GNUNET_DHT_Handle * dht_handle
Resolver handle to the dht.
static char * translate_dot_plus(struct GNS_ResolverHandle *rh, char *name)
Expands a name ending in .
static struct GNS_ResolverHandle * rlh_head
Head of resolver lookup list.
void GNS_resolver_lookup_cancel(struct GNS_ResolverHandle *rh)
Cancel active resolution (i.e.
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_IDENTITY_PublicKey *zone, uint32_t record_type, const char *name, enum GNUNET_GNS_LocalOptions options, uint16_t recursion_depth_limit, GNS_ResultProcessor proc, void *proc_cls)
Lookup of a record in a specific zone calls lookup result processor on result.
static void handle_dns_result(void *cls, const struct sockaddr *addr, socklen_t addrlen)
We had to do a DNS lookup.
static struct CacheOps * co_head
Organized in a DLL.
static void handle_dht_response(void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *trunc_peer, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data)
Iterator called on each result obtained for a DHT operation that expects a reply.
static void dns_result_parser(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
Function called with the result of a DNS resolution.
static void recursive_redirect_resolution(struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
We found a REDIRECT record, perform recursive resolution on it.
static void namecache_cache_continuation(void *cls, int32_t success, const char *emsg)
Function called once the namestore has completed the request for caching a block.
static void handle_gns_cname_result(struct GNS_ResolverHandle *rh, const char *cname)
We encountered a CNAME record during our resolution.
#define DHT_GNS_REPLICATION_LEVEL
DHT replication level.
static void GNS_resolver_lookup_cancel_(void *cls)
Wrapper around GNS_resolver_lookup_cancel() as a task.
static void recursive_dns_resolution(struct GNS_ResolverHandle *rh)
Perform recursive DNS resolution.
static void timeout_resolution(void *cls)
Function called when a resolution times out.
static struct CacheOps * co_tail
Organized in a DLL.
static int recursive_gns2dns_resolution(struct GNS_ResolverHandle *rh, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
We found one or more GNS2DNS records, perform recursive resolution on it.
static void handle_gns_namecache_resolution_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process a records that were decrypted from a block that we got from the namecache.
static void handle_gns_resolution_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process records that were decrypted from a block.
static void handle_gns2dns_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
We've resolved the IP address for the DNS resolver to use after encountering a GNS2DNS record.
static void continue_with_gns2dns(struct AuthorityChain *ac)
We have resolved one or more of the nameservers for a GNS2DNS lookup.
void GNS_resolver_done()
Shutdown resolver.
static struct GNUNET_CONTAINER_Heap * dht_lookup_heap
Heap for limiting parallel DHT lookups.
static struct GNUNET_NAMECACHE_Handle * namecache_handle
Our handle to the namecache service.
void(* GNS_ResultProcessor)(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Function called with results for a GNS resolution.
static char buf[2048]
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
API to the DHT service.
API to access the DNS service.
API to the GNS service.
API that can be used to manipulate GNS record data.
API that can be used to store naming information on a GNUnet node.
Functions related to doing DNS lookups.
API to perform and access key revocations.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
void GNUNET_DHT_get_stop(struct GNUNET_DHT_GetHandle *get_handle)
Stop async DHT-get.
Definition: dht_api.c:1237
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:1164
@ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
Each peer along the way should process the request (otherwise only peers locally closest to the key w...
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
int GNUNET_DNSPARSER_builder_add_name(char *dst, size_t dst_len, size_t *off, const char *name)
Add a DNS name to the UDP packet at the given location, converting the name to IDNA notation as neces...
Definition: dnsparser.c:889
struct GNUNET_DNSPARSER_SoaRecord * GNUNET_DNSPARSER_parse_soa(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS SOA record.
Definition: dnsparser.c:391
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:854
#define GNUNET_DNSPARSER_TYPE_SRV
#define GNUNET_DNSPARSER_TYPE_SOA
#define GNUNET_DNSPARSER_TYPE_A
void GNUNET_DNSPARSER_free_srv(struct GNUNET_DNSPARSER_SrvRecord *srv)
Free SRV information record.
Definition: dnsparser.c:139
#define GNUNET_DNSPARSER_TYPE_PTR
struct GNUNET_DNSPARSER_Packet * GNUNET_DNSPARSER_parse(const char *udp_payload, size_t udp_payload_length)
Parse a UDP payload of a DNS packet in to a nice struct for further processing and manipulation.
Definition: dnsparser.c:656
struct GNUNET_DNSPARSER_MxRecord * GNUNET_DNSPARSER_parse_mx(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS MX record.
Definition: dnsparser.c:436
#define GNUNET_DNSPARSER_TYPE_NS
int GNUNET_DNSPARSER_builder_add_soa(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SoaRecord *soa)
Add an SOA record to the UDP packet at the given location.
Definition: dnsparser.c:1079
#define GNUNET_DNSPARSER_TYPE_CNAME
int GNUNET_DNSPARSER_builder_add_mx(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_MxRecord *mx)
Add an MX record to the UDP packet at the given location.
Definition: dnsparser.c:1003
void GNUNET_DNSPARSER_free_soa(struct GNUNET_DNSPARSER_SoaRecord *soa)
Free SOA information record.
Definition: dnsparser.c:108
int GNUNET_DNSPARSER_builder_add_srv(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SrvRecord *srv)
Add an SRV record to the UDP packet at the given location.
Definition: dnsparser.c:1120
struct GNUNET_DNSPARSER_SrvRecord * GNUNET_DNSPARSER_parse_srv(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS SRV record.
Definition: dnsparser.c:477
void GNUNET_DNSPARSER_free_mx(struct GNUNET_DNSPARSER_MxRecord *mx)
Free MX information record.
Definition: dnsparser.c:154
#define GNUNET_DNSPARSER_TYPE_AAAA
int GNUNET_DNSPARSER_pack(const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length)
Given a DNS packet p, generate the corresponding UDP payload.
Definition: dnsparser.c:1259
#define GNUNET_DNSPARSER_TYPE_MX
char * GNUNET_DNSPARSER_parse_name(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse name inside of a DNS query or record.
Definition: dnsparser.c:334
#define GNUNET_DNSPARSER_MAX_NAME_LENGTH
Maximum length of a name in DNS.
int GNUNET_DNSSTUB_add_dns_ip(struct GNUNET_DNSSTUB_Context *ctx, const char *dns_ip)
Add nameserver for use by the DNSSTUB.
Definition: dnsstub.c:613
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition: dnsstub.c:705
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition: dnsstub.c:586
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition: dnsstub.c:562
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:526
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:665
GNUNET_GNS_LocalOptions
Options for the GNS lookup.
@ GNUNET_GNS_LO_LOCAL_MASTER
For the rightmost label, only look in the cache (it is our local namestore), for the others,...
@ GNUNET_GNS_LO_DEFAULT
Defaults, look in cache, then in DHT.
@ GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION
This expiration time of the record is a relative time (not an absolute time).
@ GNUNET_GNSRECORD_RF_SUPPLEMENTAL
This is a supplemental record.
@ GNUNET_GNSRECORD_RF_NONE
Entry for no flags / cleared flags.
void GNUNET_GNSRECORD_query_from_public_key(const struct GNUNET_IDENTITY_PublicKey *pub, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_IDENTITY_PublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_IDENTITY_PublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls)
Decrypt block.
size_t GNUNET_GNSRECORD_block_get_size(const struct GNUNET_GNSRECORD_Block *block)
Returns the length of this block in bytes.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_is_critical(uint32_t type)
Check if this type is a critical record.
Definition: gnsrecord.c:247
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_IDENTITY_PublicKey *pkey)
Convert an absolute domain name to the respective public key.
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_IDENTITY_PublicKey *z)
Convert a zone to a string (for printing debug messages).
#define GNUNET_GNSRECORD_TYPE_ANY
Record type indicating any record/'*'.
struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_block_get_expiration(const struct GNUNET_GNSRECORD_Block *block)
Returns the expiration of a block.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_IDENTITY_PublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_NAMECACHE_cancel(struct GNUNET_NAMECACHE_QueueEntry *qe)
Cancel a namecache operation.
struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_lookup_block(struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_HashCode *derived_hash, GNUNET_NAMECACHE_BlockProcessor proc, void *proc_cls)
Get a result for a particular key from the namecache.
struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_block_cache(struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_GNSRECORD_Block *block, GNUNET_NAMECACHE_ContinuationWithStatus cont, void *cont_cls)
Store an item in the namecache.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get(const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
Convert a string to one or more IP addresses.
Definition: resolver_api.c:940
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_IDENTITY_PublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.
void GNUNET_REVOCATION_query_cancel(struct GNUNET_REVOCATION_Query *q)
Cancel key revocation check.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1268
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:944
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:1241
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_TIME_UNIT_HOURS
One hour.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:405
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:616
#define GNUNET_TUN_DNS_CLASS_INTERNET
A few common DNS classes (ok, only one is common, but I list a couple more to make it clear what we'r...
#define GNUNET_TUN_DNS_OPCODE_QUERY
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
const char * name
DLL to hold the authority chain we had to pass in the resolution process.
int found
Did we succeed in getting an IP address for any of the DNS servers listed? Once we do,...
char * label
label/name corresponding to the authority
struct AuthorityChain * next
This is a DLL.
int gns_authority
GNUNET_YES if the authority was a GNS authority, GNUNET_NO if the authority was a DNS authority.
struct GNUNET_DNSSTUB_Context * dns_handle
Handle to perform DNS lookups with this authority (in GNS2DNS handling).
char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH+1]
Domain of the DNS resolver that is the authority.
struct AuthorityChain::@19::@20 dns_authority
struct AuthorityChain * prev
This is a DLL.
struct GNS_ResolverHandle * rh
Resolver handle this entry in the chain belongs to.
int launched
Did we start the recursive resolution via DNS?
union AuthorityChain::@19 authority_info
Information about the resolver authority for this label.
struct Gns2DnsPending * gp_head
List of resolutions of the 'ip' of the name server that are still pending.
struct Gns2DnsPending * gp_tail
Tail of list of resolutions of the 'ip' of the name server that are still pending.
Active namestore caching operations.
struct CacheOps * prev
Organized in a DLL.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe_cache
Pending Namestore caching task.
struct CacheOps * next
Organized in a DLL.
A result we got from DNS.
struct DnsResult * next
Kept in DLL.
size_t data_size
Number of bytes in data.
uint32_t record_type
Type of the GNS/DNS record.
struct DnsResult * prev
Kept in DLL.
uint64_t expiration_time
Expiration time for the DNS record, 0 if we didn't get anything useful (i.e.
const void * data
Binary value stored in the DNS record (appended to this struct)
Handle to a currently pending resolution.
size_t name_resolution_pos
Current offset in name where we are resolving.
int service
For SRV and TLSA records, the number of the service specified in the name.
char * leho
Legacy Hostname to use if we encountered GNS2DNS record and thus can deduct the LEHO from that transi...
struct GNUNET_CONTAINER_HeapNode * dht_heap_node
Heap node associated with this lookup.
void * proc_cls
closure passed to proc
struct GNS_ResolverHandle * next
DLL.
struct GNUNET_DHT_GetHandle * get_handle
Handle for DHT lookups.
struct DnsResult * dns_result_tail
DLL of results we got from DNS.
struct GNUNET_REVOCATION_Query * rev_check
Pending revocation check.
unsigned int loop_limiter
We increment the loop limiter for each step in a recursive resolution.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe
Pending Namecache lookup task.
struct GNUNET_RESOLVER_RequestHandle * std_resolve
Handle for standard DNS resolution, NULL if none is active.
int record_type
Desired type for the resolution.
struct DnsResult * dns_result_head
DLL of results we got from DNS.
struct AuthorityChain * ac_head
DLL to store the authority chain.
struct AuthorityChain * ac_tail
DLL to store the authority chain.
unsigned int loop_threshold
Maximum value of loop_limiter allowed by client.
struct GNUNET_SCHEDULER_Task * task_id
ID of a task associated with the resolution process.
GNS_ResultProcessor proc
called when resolution phase finishes
uint16_t original_dns_id
16 bit random ID we used in the dns_request.
struct GNS_ResolverHandle * prev
DLL.
struct GNUNET_IDENTITY_PublicKey authority_zone
The top-level GNS authoritative zone to query.
char * name
The name to resolve.
int protocol
For SRV and TLSA records, the number of the protocol specified in the name.
enum GNUNET_GNS_LocalOptions options
Use only cache.
struct GNUNET_DNSSTUB_RequestSocket * dns_request
Socket for a DNS request, NULL if none is active.
Handle to a node in a heap.
Handle to a GET request.
Definition: dht_api.c:81
Connection to the DHT service.
Definition: dht_api.c:237
A (signed) path tracking a block's flow through the DHT is represented by an array of path elements,...
Information from MX records (RFC 1035).
char * mxhost
Name of the mail server.
Easy-to-process, parsed version of a DNS packet.
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
char * name
Name of the record that the query is for (0-terminated).
void * data
Binary record data.
size_t data_len
Number of bytes in data.
A DNS response record.
struct GNUNET_DNSPARSER_SoaRecord * soa
SOA data for SOA records.
struct GNUNET_DNSPARSER_SrvRecord * srv
SRV data for SRV records.
struct GNUNET_DNSPARSER_MxRecord * mx
MX data for MX records.
char * hostname
For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
struct GNUNET_TIME_Absolute expiration_time
When does the record expire?
union GNUNET_DNSPARSER_Record::@24 data
Payload of the record (which one of these is valid depends on the 'type').
char * name
Name of the record that the query is for (0-terminated).
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
Information from SOA records (RFC 1035).
char * mname
The domainname of the name server that was the original or primary source of data for this zone.
char * rname
A domainname which specifies the mailbox of the person responsible for this zone.
Information from SRV records (RFC 2782).
char * target
Hostname offering the service.
Handle to the stub resolver.
Definition: dnsstub.c:125
UDP socket we are using for sending DNS requests to the Internet.
Definition: dnsstub.c:46
Record type used to box up SRV and TLSA records.
uint32_t record_type
GNS record type of the boxed record.
uint16_t service
Service of the boxed record (aka port number), in NBO.
uint16_t protocol
Protocol of the boxed record (6 = TCP, 17 = UDP, etc.).
uint32_t record_type
Type of the GNS/DNS record.
const void * data
Binary value stored in the DNS record.
size_t data_size
Number of bytes in data.
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
uint64_t expiration_time
Expiration time for the DNS record.
A 512-bit hashcode.
An identity key as per LSD0001.
Connection to the NAMECACHE service.
Definition: namecache_api.c:93
An QueueEntry used to store information for a pending NAMECACHE record operation.
Definition: namecache_api.c:46
The identity of the host (wraps the signing key of the peer).
Handle to a request given to the resolver.
Definition: resolver_api.c:104
Handle for the key revocation query.
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
uint16_t id
Unique identifier for the request/response.
Element of a resolution process for looking up the responsible DNS server hostname in a GNS2DNS recur...
struct GNUNET_RESOLVER_RequestHandle * dns_rh
Handle for DNS resolution of the DNS nameserver.
struct Gns2DnsPending * next
Kept in a DLL.
struct Gns2DnsPending * prev
Kept in a DLL.
struct GNS_ResolverHandle * rh
Handle for the resolution of the IP part of the GNS2DNS record.
struct AuthorityChain * ac
Context this activity belongs with.
unsigned int num_results
How many results did we get?
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model