GNUnet  0.10.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 #include "gnunet_util_lib.h"
29 #include "gnunet_dnsstub_lib.h"
30 #include "gnunet_dht_service.h"
31 #include "gnunet_gnsrecord_lib.h"
33 #include "gnunet_dns_service.h"
36 #include "gnunet_dnsparser_lib.h"
37 #include "gnunet_tun_lib.h"
38 #include "gnunet_gns_service.h"
39 #include "gns.h"
40 #include "gnunet-service-gns.h"
42 #include "gnunet_vpn_service.h"
43 
44 
48 #define DHT_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
49 
53 #define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
54 
58 #define VPN_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
59 
63 #define DHT_GNS_REPLICATION_LEVEL 10
64 
68 #define MAX_RECURSION 256
69 
70 
75 struct AuthorityChain;
76 
77 
84 {
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  {
164 
168  struct GNUNET_CRYPTO_EcdsaPublicKey gns_authority;
169 
170  struct
171  {
178 
184 
190 
195 
200  int found;
201 
205  int launched;
206 
207  } dns_authority;
208 
209  } authority_info;
210 
211 };
212 
213 
217 struct DnsResult
218 {
219 
223  struct DnsResult *next;
224 
228  struct DnsResult *prev;
229 
233  const void *data;
234 
239  uint64_t expiration_time;
240 
244  size_t data_size;
245 
249  uint32_t record_type;
250 
251 };
252 
253 
258 {
259 
264 
269 
273  unsigned int rd_count;
274 
278  char *rd_data;
279 
283  ssize_t rd_data_size;
284 };
285 
286 
292 {
293 
298 
303 
307  struct GNUNET_CRYPTO_EcdsaPublicKey authority_zone;
308 
313 
317  void* proc_cls;
318 
323 
328 
333 
338 
343 
348 
354 
359 
364 
369 
373  char *name;
374 
379  char *leho;
380 
385 
390 
395 
400 
405  int protocol;
406 
411  int service;
412 
417 
423  unsigned int loop_limiter;
424 
428  uint16_t original_dns_id;
429 
430 };
431 
432 
436 struct CacheOps
437 {
438 
442  struct CacheOps *next;
443 
447  struct CacheOps *prev;
448 
453 
454 };
455 
456 
461 
466 
471 
476 
480 static unsigned long long max_allowed_background_queries;
481 
486 
491 
495 static struct CacheOps *co_head;
496 
500 static struct CacheOps *co_tail;
501 
505 static int disable_cache;
506 
510 static const struct GNUNET_CONFIGURATION_Handle *cfg;
511 
512 
528 /* dead, but keep for now */ int
529 is_canonical (const char *name)
530 {
531  const char *pos;
532  const char *dot;
533 
534  if (NULL == strchr (name,
535  (unsigned char) '.'))
536  return GNUNET_YES;
537  if ('_' != name[0])
538  return GNUNET_NO;
539  pos = &name[1];
540  while (NULL != (dot = strchr (pos,
541  (unsigned char) '.')))
542  if ('_' != dot[1])
543  return GNUNET_NO;
544  else
545  pos = dot + 1;
546  return GNUNET_YES;
547 }
548 
549 /* ************************** Resolution **************************** */
550 
558 static char *
560  char *name)
561 {
562  char *ret;
563  size_t s_len = strlen (name);
564 
565  if (0 != strcmp (&name[s_len - 2],
566  ".+"))
567  return name; /* did not end in ".+" */
569  GNUNET_asprintf (&ret,
570  "%.*s.%s",
571  (int) (s_len - 2),
572  name,
574  GNUNET_free (name);
575  return ret;
576 }
577 
578 
585 static void
587 {
588  struct GNS_ResolverHandle *rh = cls;
589 
590  rh->task_id = NULL;
592 }
593 
594 
600 static void
602 {
603  rh->proc (rh->proc_cls,
604  0,
605  NULL);
606  GNUNET_assert (NULL == rh->task_id);
608  rh);
609 }
610 
611 
617 static void
619 {
620  struct GNS_ResolverHandle *rh = cls;
621 
622  rh->task_id = NULL;
623  fail_resolution (rh);
624 }
625 
626 
644 static char *
646 {
647  const char *rp;
648  const char *dot;
649  size_t len;
650  char *ret;
651  char *srv_name;
652  char *proto_name;
653  struct protoent *pe;
654  struct servent *se;
655 
656  if (0 == rh->name_resolution_pos)
657  return NULL;
658  dot = memrchr (rh->name,
659  (int) '.',
660  rh->name_resolution_pos);
661  if (NULL == dot)
662  {
663  /* done, this was the last one */
664  len = rh->name_resolution_pos;
665  rp = rh->name;
666  rh->name_resolution_pos = 0;
667  }
668  else
669  {
670  /* advance by one label */
671  len = rh->name_resolution_pos - (dot - rh->name) - 1;
672  rp = dot + 1;
673  rh->name_resolution_pos = dot - rh->name;
674  }
675  rh->protocol = 0;
676  rh->service = 0;
677  ret = GNUNET_strndup (rp, len);
678  /* If we have labels starting with underscore with label on
679  * the right (SRV/DANE/BOX case), determine port/protocol;
680  * The format of `rh->name` must be "_PORT._PROTOCOL".
681  */
682  if ( ('_' == rh->name[0]) &&
683  (NULL != (dot = memrchr (rh->name,
684  (int) '.',
685  rh->name_resolution_pos))) &&
686  ('_' == dot[1]) &&
687  (NULL == memrchr (rh->name,
688  (int) '.',
689  dot - rh->name)) )
690  {
691  srv_name = GNUNET_strndup (&rh->name[1],
692  (dot - rh->name) - 1);
693  proto_name = GNUNET_strndup (&dot[2],
694  rh->name_resolution_pos - (dot - rh->name) - 1);
695  rh->name_resolution_pos = 0;
696  pe = getprotobyname (proto_name);
697  if (NULL == pe)
698  {
700  _("Protocol `%s' unknown, skipping labels.\n"),
701  proto_name);
702  GNUNET_free (proto_name);
703  GNUNET_free (srv_name);
704  return ret;
705  }
706  se = getservbyname (srv_name,
707  proto_name);
708  if (NULL == se)
709  {
711  _("Service `%s' unknown for protocol `%s', skipping labels.\n"),
712  srv_name,
713  proto_name);
714  GNUNET_free (proto_name);
715  GNUNET_free (srv_name);
716  return ret;
717  }
718  rh->protocol = pe->p_proto;
719  rh->service = se->s_port;
720  GNUNET_free (proto_name);
721  GNUNET_free (srv_name);
722  }
723  return ret;
724 }
725 
726 
732 static void
734 {
735  struct DnsResult *pos;
736  unsigned int n;
737  unsigned int i;
738 
739  n = 0;
740  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
741  n++;
742  {
743  struct GNUNET_GNSRECORD_Data rd[n];
744 
745  i = 0;
746  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
747  {
748  rd[i].data = pos->data;
749  rd[i].data_size = pos->data_size;
750  rd[i].record_type = pos->record_type;
751  if (0 == pos->expiration_time)
752  {
754  rd[i].expiration_time = 0;
755  }
756  else
757  {
759  rd[i].expiration_time = pos->expiration_time;
760  }
761  i++;
762  }
763  GNUNET_assert (i == n);
765  "Transmitting standard DNS result with %u records\n",
766  n);
767  rh->proc (rh->proc_cls,
768  n,
769  rd);
770  }
772 }
773 
774 
784 static void
786  uint64_t expiration_time,
787  uint32_t record_type,
788  size_t data_size,
789  const void *data)
790 {
791  struct DnsResult *res;
792 
793  res = GNUNET_malloc (sizeof (struct DnsResult) + data_size);
795  res->data_size = data_size;
796  res->record_type = record_type;
797  res->data = &res[1];
798  GNUNET_memcpy (&res[1],
799  data,
800  data_size);
802  rh->dns_result_tail,
803  res);
804 }
805 
806 
815 static void
816 handle_dns_result (void *cls,
817  const struct sockaddr *addr,
818  socklen_t addrlen)
819 {
820  struct GNS_ResolverHandle *rh = cls;
821  const struct sockaddr_in *sa4;
822  const struct sockaddr_in6 *sa6;
823 
824  if (NULL == addr)
825  {
826  rh->std_resolve = NULL;
828  return;
829  }
831  "Received %u bytes of DNS IP data\n",
832  addrlen);
833  switch (addr->sa_family)
834  {
835  case AF_INET:
836  sa4 = (const struct sockaddr_in *) addr;
837  add_dns_result (rh,
838  0 /* expiration time is unknown */,
840  sizeof (struct in_addr),
841  &sa4->sin_addr);
842  break;
843  case AF_INET6:
844  sa6 = (const struct sockaddr_in6 *) addr;
845  add_dns_result (rh,
846  0 /* expiration time is unknown */,
848  sizeof (struct in6_addr),
849  &sa6->sin6_addr);
850  break;
851  default:
852  GNUNET_break (0);
853  break;
854  }
855 }
856 
857 
864 static void
865 recursive_resolution (void *cls);
866 
867 
874 static void
875 start_resolver_lookup (void *cls);
876 
877 
886 static void
887 dns_result_parser (void *cls,
888  const struct GNUNET_TUN_DnsHeader *dns,
889  size_t dns_len)
890 {
891  struct GNS_ResolverHandle *rh = cls;
892  struct GNUNET_DNSPARSER_Packet *p;
893  const struct GNUNET_DNSPARSER_Record *rec;
894  unsigned int rd_count;
895 
896  if (NULL == dns)
897  {
898  rh->dns_request = NULL;
900  rh->task_id = NULL;
901  fail_resolution (rh);
902  return;
903  }
904  if (rh->original_dns_id != dns->id)
905  {
906  /* DNS answer, but for another query */
907  return;
908  }
909  p = GNUNET_DNSPARSER_parse ((const char *) dns,
910  dns_len);
911  if (NULL == p)
912  {
914  _("Failed to parse DNS response\n"));
915  return;
916  }
917 
918  /* We got a result from DNS */
920  "Received DNS response for `%s' with %u answers\n",
921  rh->ac_tail->label,
922  (unsigned int) p->num_answers);
923  if ( (p->num_answers > 0) &&
926  {
927  int af;
928 
930  "Got CNAME `%s' from DNS for `%s'\n",
931  p->answers[0].data.hostname,
932  rh->name);
933  if (NULL != rh->std_resolve)
934  {
936  "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
937  rh->name);
939  }
940  GNUNET_free (rh->name);
941  rh->name = GNUNET_strdup (p->answers[0].data.hostname);
942  rh->name_resolution_pos = strlen (rh->name);
943  switch (rh->record_type)
944  {
946  af = AF_INET;
947  break;
949  af = AF_INET6;
950  break;
951  default:
952  af = AF_UNSPEC;
953  break;
954  }
955  if (NULL != rh->leho)
956  add_dns_result (rh,
957  GNUNET_TIME_UNIT_HOURS.rel_value_us,
959  strlen (rh->leho),
960  rh->leho);
962  af,
965  rh);
968  rh->dns_request = NULL;
969  return;
970  }
971 
972  /* convert from (parsed) DNS to (binary) GNS format! */
974  {
975  struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
976  int skip;
977  char buf[UINT16_MAX];
978  size_t buf_off;
979  size_t buf_start;
980 
981  buf_off = 0;
982  skip = 0;
983  memset (rd,
984  0,
985  sizeof (rd));
986  for (unsigned int i=0;i<rd_count;i++)
987  {
988  if (i < p->num_answers)
989  rec = &p->answers[i];
990  else if (i < p->num_answers + p->num_authority_records)
991  rec = &p->authority_records[i - p->num_answers];
992  else
994  /* As we copied the full DNS name to 'rh->ac_tail->label', this
995  should be the correct check to see if this record is actually
996  a record for our label... */
997  if (0 != strcmp (rec->name,
998  rh->ac_tail->label))
999  {
1001  "Dropping record `%s', does not match desired name `%s'\n",
1002  rec->name,
1003  rh->ac_tail->label);
1004  skip++;
1005  continue;
1006  }
1007  rd[i - skip].record_type = rec->type;
1008  rd[i - skip].expiration_time = rec->expiration_time.abs_value_us;
1009  switch (rec->type)
1010  {
1012  if (rec->data.raw.data_len != sizeof (struct in_addr))
1013  {
1014  GNUNET_break_op (0);
1015  skip++;
1016  continue;
1017  }
1018  rd[i - skip].data_size = rec->data.raw.data_len;
1019  rd[i - skip].data = rec->data.raw.data;
1020  break;
1022  if (rec->data.raw.data_len != sizeof (struct in6_addr))
1023  {
1024  GNUNET_break_op (0);
1025  skip++;
1026  continue;
1027  }
1028  rd[i - skip].data_size = rec->data.raw.data_len;
1029  rd[i - skip].data = rec->data.raw.data;
1030  break;
1034  buf_start = buf_off;
1035  if (GNUNET_OK !=
1037  sizeof (buf),
1038  &buf_off,
1039  rec->data.hostname))
1040  {
1041  GNUNET_break (0);
1042  skip++;
1043  continue;
1044  }
1045  rd[i - skip].data_size = buf_off - buf_start;
1046  rd[i - skip].data = &buf[buf_start];
1047  break;
1049  buf_start = buf_off;
1050  if (GNUNET_OK !=
1052  sizeof (buf),
1053  &buf_off,
1054  rec->data.soa))
1055  {
1056  GNUNET_break (0);
1057  skip++;
1058  continue;
1059  }
1060  rd[i - skip].data_size = buf_off - buf_start;
1061  rd[i - skip].data = &buf[buf_start];
1062  break;
1064  buf_start = buf_off;
1065  if (GNUNET_OK !=
1067  sizeof (buf),
1068  &buf_off,
1069  rec->data.mx))
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;
1079  buf_start = buf_off;
1080  if (GNUNET_OK !=
1082  sizeof (buf),
1083  &buf_off,
1084  rec->data.srv))
1085  {
1086  GNUNET_break (0);
1087  skip++;
1088  continue;
1089  }
1090  rd[i - skip].data_size = buf_off - buf_start;
1091  rd[i - skip].data = &buf[buf_start];
1092  break;
1093  default:
1095  _("Skipping record of unsupported type %d\n"),
1096  rec->type);
1097  skip++;
1098  continue;
1099  }
1100  } /* end of for all records in answer */
1101  if (NULL != rh->leho)
1102  {
1103  rd[rd_count - skip].record_type = GNUNET_GNSRECORD_TYPE_LEHO;
1104  rd[rd_count - skip].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1105  rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1106  rd[rd_count - skip].data = rh->leho;
1107  rd[rd_count - skip].data_size = strlen (rh->leho);
1108  skip--; /* skip one LESS */
1110  "Adding LEHO %s\n",
1111  rh->leho);
1112  }
1114  "Returning DNS response for `%s' with %u answers\n",
1115  rh->ac_tail->label,
1116  (unsigned int) (rd_count - skip));
1117  rh->proc (rh->proc_cls,
1118  rd_count - skip,
1119  rd);
1121  rh->dns_request = NULL;
1122  }
1124  if (NULL != rh->task_id)
1125  GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1127  rh);
1128 }
1129 
1130 
1139 static void
1141 {
1142  struct AuthorityChain *ac;
1143  struct GNUNET_DNSPARSER_Query *query;
1144  struct GNUNET_DNSPARSER_Packet *p;
1145  char *dns_request;
1146  size_t dns_request_length;
1147  int ret;
1148 
1149  ac = rh->ac_tail;
1150  GNUNET_assert (NULL != ac);
1152  "Starting DNS lookup for `%s'\n",
1153  ac->label);
1155  query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1156  query->name = GNUNET_strdup (ac->label);
1157  query->type = rh->record_type;
1159  p = GNUNET_new (struct GNUNET_DNSPARSER_Packet);
1160  p->queries = query;
1161  p->num_queries = 1;
1163  UINT16_MAX);
1165  p->flags.recursion_desired = 1;
1166  ret = GNUNET_DNSPARSER_pack (p,
1167  1024,
1168  &dns_request,
1169  &dns_request_length);
1170  if (GNUNET_OK != ret)
1171  {
1172  GNUNET_break (0);
1173  rh->proc (rh->proc_cls,
1174  0,
1175  NULL);
1176  GNUNET_assert (NULL == rh->task_id);
1178  rh);
1179  }
1180  else
1181  {
1182  rh->original_dns_id = p->id;
1183  GNUNET_assert (NULL != ac->authority_info.dns_authority.dns_handle);
1184  GNUNET_assert (NULL == rh->dns_request);
1185  rh->leho = GNUNET_strdup (ac->label);
1187  dns_request,
1188  dns_request_length,
1190  rh);
1193  rh);
1194  }
1195  if (GNUNET_SYSERR != ret)
1196  GNUNET_free (dns_request);
1198 }
1199 
1200 
1209 static void
1211  const char *cname)
1212 {
1213  size_t nlen;
1214  char *res;
1215  struct AuthorityChain *ac;
1216  int af;
1217 
1218  nlen = strlen (cname);
1219  if ( (nlen > 2) &&
1220  (0 == strcmp (".+",
1221  &cname[nlen - 2])) )
1222  {
1223  /* CNAME resolution continues relative to current domain */
1224  if (0 == rh->name_resolution_pos)
1225  {
1226  res = GNUNET_strndup (cname, nlen - 2);
1227  rh->name_resolution_pos = nlen - 2;
1228  }
1229  else
1230  {
1231  GNUNET_asprintf (&res,
1232  "%.*s.%.*s",
1233  (int) rh->name_resolution_pos,
1234  rh->name,
1235  (int) (nlen - 2),
1236  cname);
1237  rh->name_resolution_pos = strlen (res);
1238  }
1239  GNUNET_free (rh->name);
1240  rh->name = res;
1241  ac = GNUNET_new (struct AuthorityChain);
1242  ac->rh = rh;
1243  ac->gns_authority = GNUNET_YES;
1246  /* add AC to tail */
1248  rh->ac_tail,
1249  ac);
1251  rh);
1252  return;
1253  }
1255  "Got CNAME `%s' from GNS for `%s'\n",
1256  cname,
1257  rh->name);
1258  if (NULL != rh->std_resolve)
1259  {
1261  "Multiple CNAME results from GNS resolving `%s'! Not really allowed...\n",
1262  rh->name);
1264  }
1265  /* name is absolute, go to DNS */
1266  GNUNET_free (rh->name);
1267  rh->name = GNUNET_strdup (cname);
1268  rh->name_resolution_pos = strlen (rh->name);
1269  switch (rh->record_type)
1270  {
1272  af = AF_INET;
1273  break;
1275  af = AF_INET6;
1276  break;
1277  default:
1278  af = AF_UNSPEC;
1279  break;
1280  }
1282  "Doing standard DNS lookup for `%s'\n",
1283  rh->name);
1285  af,
1288  rh);
1289 }
1290 
1291 
1299 static void
1300 handle_gns_resolution_result (void *cls,
1301  unsigned int rd_count,
1302  const struct GNUNET_GNSRECORD_Data *rd);
1303 
1304 
1319 static void
1321  int af,
1322  const void *address)
1323 {
1324  struct VpnContext *vpn_ctx = cls;
1325  struct GNS_ResolverHandle *rh = vpn_ctx->rh;
1326  struct GNUNET_GNSRECORD_Data rd[vpn_ctx->rd_count];
1327  unsigned int i;
1328 
1329  vpn_ctx->vpn_request = NULL;
1330  rh->vpn_ctx = NULL;
1332  GNUNET_GNSRECORD_records_deserialize ((size_t) vpn_ctx->rd_data_size,
1333  vpn_ctx->rd_data,
1334  vpn_ctx->rd_count,
1335  rd));
1336  for (i=0;i<vpn_ctx->rd_count;i++)
1337  {
1339  {
1340  switch (af)
1341  {
1342  case AF_INET:
1344  rd[i].data_size = sizeof (struct in_addr);
1346  rd[i].flags = 0;
1347  rd[i].data = address;
1348  break;
1349  case AF_INET6:
1352  rd[i].flags = 0;
1353  rd[i].data = address;
1354  rd[i].data_size = sizeof (struct in6_addr);
1355  break;
1356  default:
1357  GNUNET_assert (0);
1358  }
1359  break;
1360  }
1361  }
1362  GNUNET_assert (i < vpn_ctx->rd_count);
1363  if (0 == vpn_ctx->rd_count)
1365  _("VPN returned empty result for `%s'\n"),
1366  rh->name);
1368  vpn_ctx->rd_count,
1369  rd);
1370  GNUNET_free (vpn_ctx->rd_data);
1371  GNUNET_free (vpn_ctx);
1372 }
1373 
1374 
1382 static void
1384 {
1385  struct GNS_ResolverHandle *rh = ac->rh;
1386 
1387  if ( (NULL != ac->authority_info.dns_authority.gp_head) &&
1388  (GNUNET_NO == ac->authority_info.dns_authority.found) )
1389  return; /* more pending and none found yet */
1390  if (GNUNET_NO == ac->authority_info.dns_authority.found)
1391  {
1393  "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1394  ac->authority_info.dns_authority.name);
1395  fail_resolution (rh);
1396  return;
1397  }
1398  if (GNUNET_NO != ac->authority_info.dns_authority.launched)
1399  return; /* already running, do not launch again! */
1400  /* recurse */
1401  ac->authority_info.dns_authority.launched = GNUNET_YES;
1403  "Will continue resolution using DNS to resolve `%s'\n",
1404  ac->label);
1405  GNUNET_assert (NULL == rh->task_id);
1407  rh);
1408 
1409 }
1410 
1411 
1420 static void
1422  unsigned int rd_count,
1423  const struct GNUNET_GNSRECORD_Data *rd)
1424 {
1425  struct Gns2DnsPending *gp = cls;
1426  struct AuthorityChain *ac = gp->ac;
1427 
1429  ac->authority_info.dns_authority.gp_tail,
1430  gp);
1431  /* enable cleanup of 'rh' handle that automatically comes after we return,
1432  and which expects 'rh' to be in the #rlh_head DLL. */
1433  if (NULL != gp->rh)
1434  {
1435  GNUNET_CONTAINER_DLL_insert (rlh_head,
1436  rlh_tail,
1437  gp->rh);
1438  gp->rh = NULL;
1439  }
1440  GNUNET_free (gp);
1442  "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1443  rd_count);
1444  /* find suitable A/AAAA record */
1445  for (unsigned int j=0;j<rd_count;j++)
1446  {
1447  switch (rd[j].record_type)
1448  {
1450  {
1451  struct sockaddr_in v4;
1452 
1453  if (sizeof (struct in_addr) != rd[j].data_size)
1454  {
1455  GNUNET_break_op (0);
1456  continue;
1457  }
1458  memset (&v4,
1459  0,
1460  sizeof (v4));
1461  v4.sin_family = AF_INET;
1462  v4.sin_port = htons (53);
1463 #if HAVE_SOCKADDR_IN_SIN_LEN
1464  v4.sin_len = (u_char) sizeof (v4);
1465 #endif
1466  GNUNET_memcpy (&v4.sin_addr,
1467  rd[j].data,
1468  sizeof (struct in_addr));
1469  if (GNUNET_OK ==
1471  (const struct sockaddr *) &v4))
1473  break;
1474  }
1476  {
1477  struct sockaddr_in6 v6;
1478 
1479  if (sizeof (struct in6_addr) != rd[j].data_size)
1480  {
1481  GNUNET_break_op (0);
1482  continue;
1483  }
1484  /* FIXME: might want to check if we support IPv6 here,
1485  and otherwise skip this one and hope we find another */
1486  memset (&v6,
1487  0,
1488  sizeof (v6));
1489  v6.sin6_family = AF_INET6;
1490  v6.sin6_port = htons (53);
1491 #if HAVE_SOCKADDR_IN_SIN_LEN
1492  v6.sin6_len = (u_char) sizeof (v6);
1493 #endif
1494  GNUNET_memcpy (&v6.sin6_addr,
1495  rd[j].data,
1496  sizeof (struct in6_addr));
1497  if (GNUNET_OK ==
1499  (const struct sockaddr *) &v6))
1501  break;
1502  }
1503  default:
1504  break;
1505  }
1506  }
1507  continue_with_gns2dns (ac);
1508 }
1509 
1510 
1518 static void
1520  const struct sockaddr *addr,
1521  socklen_t addrlen)
1522 {
1523  struct Gns2DnsPending *gp = cls;
1524  struct AuthorityChain *ac = gp->ac;
1525  struct sockaddr_storage ss;
1526  struct sockaddr_in *v4;
1527  struct sockaddr_in6 *v6;
1528 
1529  if (NULL == addr)
1530  {
1531  /* DNS resolution finished */
1532  if (0 == gp->num_results)
1534  "Failed to use DNS to resolve name of DNS resolver\n");
1536  ac->authority_info.dns_authority.gp_tail,
1537  gp);
1538  GNUNET_free (gp);
1539  continue_with_gns2dns (ac);
1540  return;
1541  }
1542  GNUNET_memcpy (&ss,
1543  addr,
1544  addrlen);
1545  switch (ss.ss_family)
1546  {
1547  case AF_INET:
1548  v4 = (struct sockaddr_in *) &ss;
1549  v4->sin_port = htons (53);
1550  gp->num_results++;
1551  break;
1552  case AF_INET6:
1553  v6 = (struct sockaddr_in6 *) &ss;
1554  v6->sin6_port = htons (53);
1555  gp->num_results++;
1556  break;
1557  default:
1559  "Unsupported AF %d\n",
1560  ss.ss_family);
1561  return;
1562  }
1563  if (GNUNET_OK ==
1565  (struct sockaddr *) &ss))
1567 }
1568 
1569 
1576 static void
1578  const struct GNUNET_GNSRECORD_Data *rd)
1579 {
1580  char *cname;
1581  size_t off;
1582 
1583  off = 0;
1584  cname = GNUNET_DNSPARSER_parse_name (rd->data,
1585  rd->data_size,
1586  &off);
1587  if ( (NULL == cname) ||
1588  (off != rd->data_size) )
1589  {
1590  GNUNET_break_op (0); /* record not well-formed */
1591  GNUNET_free_non_null (cname);
1592  fail_resolution (rh);
1593  return;
1594  }
1596  cname);
1597  GNUNET_free (cname);
1598 }
1599 
1600 
1607 static void
1609  const struct GNUNET_GNSRECORD_Data *rd)
1610 {
1611  struct AuthorityChain *ac;
1612 
1613  /* delegation to another zone */
1614  if (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) !=
1615  rd->data_size)
1616  {
1617  GNUNET_break_op (0);
1618  fail_resolution (rh);
1619  return;
1620  }
1621  /* expand authority chain */
1622  ac = GNUNET_new (struct AuthorityChain);
1623  ac->rh = rh;
1624  ac->gns_authority = GNUNET_YES;
1626  rd->data,
1627  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1629  /* add AC to tail */
1631  rh->ac_tail,
1632  ac);
1633  /* recurse */
1635  rh);
1636 }
1637 
1638 
1649 static int
1651  unsigned int rd_count,
1652  const struct GNUNET_GNSRECORD_Data *rd)
1653 {
1654  struct AuthorityChain *ac;
1655  const char *tld;
1656  char *ns;
1657 
1658  ns = NULL;
1659  /* expand authority chain */
1660  ac = GNUNET_new (struct AuthorityChain);
1661  ac->rh = rh;
1662  ac->authority_info.dns_authority.dns_handle = GNUNET_DNSSTUB_start (4);
1663 
1664  for (unsigned int i=0;i<rd_count;i++)
1665  {
1666  char *ip;
1667  char *n;
1668  size_t off;
1669  struct Gns2DnsPending *gp;
1670  struct GNUNET_CRYPTO_EcdsaPublicKey zone;
1671  struct sockaddr_in v4;
1672  struct sockaddr_in6 v6;
1673 
1674  if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1675  continue;
1676  off = 0;
1677  n = GNUNET_DNSPARSER_parse_name (rd[i].data,
1678  rd[i].data_size,
1679  &off);
1680  ip = GNUNET_DNSPARSER_parse_name (rd[i].data,
1681  rd[i].data_size,
1682  &off);
1683  if ( (NULL == n) ||
1684  (NULL == ip) ||
1685  (off != rd[i].data_size) )
1686  {
1687  GNUNET_break_op (0);
1689  GNUNET_free_non_null (ip);
1690  continue;
1691  }
1692  /* resolve 'ip' to determine the IP(s) of the DNS
1693  resolver to use for lookup of 'ns' */
1694  if (NULL != ns)
1695  {
1696  if (0 != strcasecmp (ns,
1697  n))
1698  {
1699  /* NS values must all be the same for all GNS2DNS records,
1700  anything else leads to insanity */
1701  GNUNET_break_op (0);
1702  GNUNET_free (n);
1703  GNUNET_free (ip);
1704  continue;
1705  }
1706  GNUNET_free (n);
1707  }
1708  else
1709  {
1710  ns = n;
1711  }
1712 
1713  /* check if 'ip' is already an IPv4/IPv6 address */
1714  if ( (1 == inet_pton (AF_INET,
1715  ip,
1716  &v4)) ||
1717  (1 == inet_pton (AF_INET6,
1718  ip,
1719  &v6)) )
1720  {
1723  ip));
1725  GNUNET_free (ip);
1726  continue;
1727  }
1728  tld = GNS_get_tld (ip);
1729  if (0 != strcmp (tld,
1730  "+"))
1731  {
1732  /* 'ip' is a DNS name */
1733  gp = GNUNET_new (struct Gns2DnsPending);
1734  gp->ac = ac;
1736  ac->authority_info.dns_authority.gp_tail,
1737  gp);
1738  gp->dns_rh = GNUNET_RESOLVER_ip_get (ip,
1739  AF_UNSPEC,
1742  gp);
1743  GNUNET_free (ip);
1744  continue;
1745  }
1746  /* 'ip' should be a GNS name */
1747  gp = GNUNET_new (struct Gns2DnsPending);
1748  gp->ac = ac;
1750  ac->authority_info.dns_authority.gp_tail,
1751  gp);
1752  gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1753  ip = translate_dot_plus (rh,
1754  ip);
1755  tld = GNS_get_tld (ip);
1756  if (GNUNET_OK !=
1758  &zone))
1759  {
1760  GNUNET_break_op (0);
1761  GNUNET_free (ip);
1762  continue;
1763  }
1764  gp->rh->authority_zone = zone;
1766  "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1767  ip,
1768  ns);
1769  gp->rh->name = ip;
1770  gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1771  gp->rh->proc = &handle_gns2dns_result;
1772  gp->rh->proc_cls = gp;
1775  gp->rh->loop_limiter = rh->loop_limiter + 1;
1776  gp->rh->task_id
1778  gp->rh);
1779  } /* end 'for all records' */
1780 
1781  if (NULL == ns)
1782  {
1783  /* not a single GNS2DNS record found */
1784  GNUNET_free (ac);
1785  return GNUNET_SYSERR;
1786  }
1788  strcpy (ac->authority_info.dns_authority.name,
1789  ns);
1790  /* for DNS recursion, the label is the full DNS name,
1791  created from the remainder of the GNS name and the
1792  name in the NS record */
1793  GNUNET_asprintf (&ac->label,
1794  "%.*s%s%s",
1795  (int) rh->name_resolution_pos,
1796  rh->name,
1797  (0 != rh->name_resolution_pos) ? "." : "",
1798  ns);
1799  GNUNET_free (ns);
1801  rh->ac_tail,
1802  ac);
1803  if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1804  {
1806  _("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1807  ac->label);
1808  return GNUNET_SYSERR;
1809  }
1810  continue_with_gns2dns (ac);
1811  return GNUNET_OK;
1812 }
1813 
1814 
1822 static void
1824  unsigned int rd_count,
1825  const struct GNUNET_GNSRECORD_Data *rd)
1826 {
1827  struct GNS_ResolverHandle *rh = cls;
1828  char *cname;
1829  struct VpnContext *vpn_ctx;
1830  const struct GNUNET_TUN_GnsVpnRecord *vpn;
1831  const char *vname;
1832  struct GNUNET_HashCode vhash;
1833  int af;
1834  char scratch[UINT16_MAX];
1835  size_t scratch_off;
1836  size_t scratch_start;
1837  size_t off;
1838  struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1839  unsigned int rd_off;
1840 
1842  "Resolution succeeded for `%s' in zone %s, got %u records\n",
1843  rh->ac_tail->label,
1845  rd_count);
1846  if (0 == rd_count)
1847  {
1849  _("GNS lookup failed (zero records found for `%s')\n"),
1850  rh->name);
1851  fail_resolution (rh);
1852  return;
1853  }
1854 
1855  if (0 == rh->name_resolution_pos)
1856  {
1857  /* top-level match, are we done yet? */
1858  if ( (rd_count > 0) &&
1861  {
1862  off = 0;
1863  cname = GNUNET_DNSPARSER_parse_name (rd[0].data,
1864  rd[0].data_size,
1865  &off);
1866  if ( (NULL == cname) ||
1867  (off != rd[0].data_size) )
1868  {
1869  GNUNET_break_op (0);
1870  GNUNET_free_non_null (cname);
1871  fail_resolution (rh);
1872  return;
1873  }
1875  cname);
1876  GNUNET_free (cname);
1877  return;
1878  }
1879  /* If A/AAAA was requested, but we got a VPN
1880  record, we convert it to A/AAAA using GNUnet VPN */
1881  if ( (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
1883  {
1884  for (unsigned int i=0;i<rd_count;i++)
1885  {
1886  switch (rd[i].record_type)
1887  {
1889  {
1890  af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET : AF_INET6;
1891  if (sizeof (struct GNUNET_TUN_GnsVpnRecord) >
1892  rd[i].data_size)
1893  {
1894  GNUNET_break_op (0);
1895  fail_resolution (rh);
1896  return;
1897  }
1898  vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
1899  vname = (const char *) &vpn[1];
1900  if ('\0' != vname[rd[i].data_size - 1 - sizeof (struct GNUNET_TUN_GnsVpnRecord)])
1901  {
1902  GNUNET_break_op (0);
1903  fail_resolution (rh);
1904  return;
1905  }
1907  &vhash);
1909  "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n",
1910  GNUNET_i2s (&vpn->peer),
1911  vname,
1912  (int) af,
1913  (int) ntohs (vpn->proto));
1914  vpn_ctx = GNUNET_new (struct VpnContext);
1915  rh->vpn_ctx = vpn_ctx;
1916  vpn_ctx->rh = rh;
1917  vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
1918  rd);
1919  if (vpn_ctx->rd_data_size < 0)
1920  {
1921  GNUNET_break_op (0);
1922  GNUNET_free (vpn_ctx);
1923  fail_resolution (rh);
1924  return;
1925  }
1926  vpn_ctx->rd_data = GNUNET_malloc ((size_t) vpn_ctx->rd_data_size);
1927  vpn_ctx->rd_count = rd_count;
1928  GNUNET_assert (vpn_ctx->rd_data_size ==
1930  rd,
1931  (size_t) vpn_ctx->rd_data_size,
1932  vpn_ctx->rd_data));
1933  vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
1934  af,
1935  ntohs (vpn->proto),
1936  &vpn->peer,
1937  &vhash,
1940  vpn_ctx);
1941  return;
1942  }
1944  {
1945  /* delegation to DNS */
1947  "Found GNS2DNS record, delegating to DNS!\n");
1948  if (GNUNET_OK ==
1950  rd_count,
1951  rd))
1952  return;
1953  else
1954  goto fail;
1955  }
1956  default:
1957  break;
1958  } /* end: switch */
1959  } /* end: for rd */
1960  } /* end: name_resolution_pos */
1961  /* convert relative names in record values to absolute names,
1962  using 'scratch' array for memory allocations */
1963  scratch_off = 0;
1964  rd_off = 0;
1965  for (unsigned int i=0;i<rd_count;i++)
1966  {
1967  GNUNET_assert (rd_off <= i);
1968  if ( (0 != rh->protocol) &&
1969  (0 != rh->service) &&
1971  continue; /* we _only_ care about boxed records */
1972 
1973  GNUNET_assert (rd_off < rd_count);
1974  rd_new[rd_off] = rd[i];
1975  /* Check if the embedded name(s) end in "+", and if so,
1976  replace the "+" with the zone at "ac_tail", changing the name
1977  to a ".ZONEKEY". The name is allocated on the 'scratch' array,
1978  so we can free it afterwards. */
1979  switch (rd[i].record_type)
1980  {
1982  {
1983  char *cname;
1984 
1985  off = 0;
1986  cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
1987  rd[i].data_size,
1988  &off);
1989  if ( (NULL == cname) ||
1990  (off != rd[i].data_size) )
1991  {
1992  GNUNET_break_op (0); /* record not well-formed */
1993  }
1994  else
1995  {
1996  cname = translate_dot_plus (rh, cname);
1997  GNUNET_break (NULL != cname);
1998  scratch_start = scratch_off;
1999  if (GNUNET_OK !=
2001  sizeof (scratch),
2002  &scratch_off,
2003  cname))
2004  {
2005  GNUNET_break (0);
2006  }
2007  else
2008  {
2009  GNUNET_assert (rd_off < rd_count);
2010  rd_new[rd_off].data = &scratch[scratch_start];
2011  rd_new[rd_off].data_size = scratch_off - scratch_start;
2012  rd_off++;
2013  }
2014  }
2015  GNUNET_free_non_null (cname);
2016  }
2017  break;
2019  {
2020  struct GNUNET_DNSPARSER_SoaRecord *soa;
2021 
2022  off = 0;
2023  soa = GNUNET_DNSPARSER_parse_soa (rd[i].data,
2024  rd[i].data_size,
2025  &off);
2026  if ( (NULL == soa) ||
2027  (off != rd[i].data_size) )
2028  {
2029  GNUNET_break_op (0); /* record not well-formed */
2030  }
2031  else
2032  {
2033  soa->mname = translate_dot_plus (rh, soa->mname);
2034  soa->rname = translate_dot_plus (rh, soa->rname);
2035  scratch_start = scratch_off;
2036  if (GNUNET_OK !=
2038  sizeof (scratch),
2039  &scratch_off,
2040  soa))
2041  {
2042  GNUNET_break (0);
2043  }
2044  else
2045  {
2046  GNUNET_assert (rd_off < rd_count);
2047  rd_new[rd_off].data = &scratch[scratch_start];
2048  rd_new[rd_off].data_size = scratch_off - scratch_start;
2049  rd_off++;
2050  }
2051  }
2052  if (NULL != soa)
2054  }
2055  break;
2057  {
2058  struct GNUNET_DNSPARSER_MxRecord *mx;
2059 
2060  off = 0;
2061  mx = GNUNET_DNSPARSER_parse_mx (rd[i].data,
2062  rd[i].data_size,
2063  &off);
2064  if ( (NULL == mx) ||
2065  (off != rd[i].data_size) )
2066  {
2067  GNUNET_break_op (0); /* record not well-formed */
2068  }
2069  else
2070  {
2071  mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2072  scratch_start = scratch_off;
2073  if (GNUNET_OK !=
2075  sizeof (scratch),
2076  &scratch_off,
2077  mx))
2078  {
2079  GNUNET_break (0);
2080  }
2081  else
2082  {
2083  GNUNET_assert (rd_off < rd_count);
2084  rd_new[rd_off].data = &scratch[scratch_start];
2085  rd_new[rd_off].data_size = scratch_off - scratch_start;
2086  rd_off++;
2087  }
2088  }
2089  if (NULL != mx)
2091  }
2092  break;
2094  {
2095  struct GNUNET_DNSPARSER_SrvRecord *srv;
2096 
2097  off = 0;
2098  srv = GNUNET_DNSPARSER_parse_srv (rd[i].data,
2099  rd[i].data_size,
2100  &off);
2101  if ( (NULL == srv) ||
2102  (off != rd[i].data_size) )
2103  {
2104  GNUNET_break_op (0); /* record not well-formed */
2105  }
2106  else
2107  {
2108  srv->target = translate_dot_plus (rh, srv->target);
2109  scratch_start = scratch_off;
2110  if (GNUNET_OK !=
2112  sizeof (scratch),
2113  &scratch_off,
2114  srv))
2115  {
2116  GNUNET_break (0);
2117  }
2118  else
2119  {
2120  GNUNET_assert (rd_off < rd_count);
2121  rd_new[rd_off].data = &scratch[scratch_start];
2122  rd_new[rd_off].data_size = scratch_off - scratch_start;
2123  rd_off++;
2124  }
2125  }
2126  if (NULL != srv)
2128  }
2129  break;
2130 
2132  {
2133  const char *nick;
2134 
2135  nick = rd[i].data;
2136  if ((rd[i].data_size > 0) &&
2137  (nick[rd[i].data_size -1] != '\0'))
2138  {
2139  GNUNET_break_op (0);
2140  break;
2141  }
2142  break;
2143  }
2145  {
2146  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
2147 
2148  if (rd[i].data_size != sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))
2149  {
2150  GNUNET_break_op (0);
2151  break;
2152  }
2153  GNUNET_memcpy (&pub,
2154  rd[i].data,
2155  rd[i].data_size);
2156  rd_off++;
2158  {
2159  /* try to resolve "@" */
2160  struct AuthorityChain *ac;
2161 
2162  ac = GNUNET_new (struct AuthorityChain);
2163  ac->rh = rh;
2164  ac->gns_authority = GNUNET_YES;
2168  rh->ac_tail,
2169  ac);
2171  rh);
2172  return;
2173  }
2174  }
2175  break;
2177  {
2178  /* delegation to DNS */
2180  {
2181  rd_off++;
2182  break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2183  }
2185  "Found GNS2DNS record, delegating to DNS!\n");
2186  if (GNUNET_OK ==
2188  rd_count,
2189  rd))
2190  return;
2191  else
2192  goto fail;
2193  }
2195  {
2196  /* unbox SRV/TLSA records if a specific one was requested */
2197  if ( (0 != rh->protocol) &&
2198  (0 != rh->service) &&
2199  (rd[i].data_size >= sizeof (struct GNUNET_GNSRECORD_BoxRecord)) )
2200  {
2201  const struct GNUNET_GNSRECORD_BoxRecord *box;
2202 
2203  box = rd[i].data;
2204  if ( (ntohs (box->protocol) == rh->protocol) &&
2205  (ntohs (box->service) == rh->service) )
2206  {
2207  /* Box matches, unbox! */
2208  GNUNET_assert (rd_off < rd_count);
2209  rd_new[rd_off].record_type = ntohl (box->record_type);
2210  rd_new[rd_off].data_size -= sizeof (struct GNUNET_GNSRECORD_BoxRecord);
2211  rd_new[rd_off].data = &box[1];
2212  rd_off++;
2213  }
2214  }
2215  else
2216  {
2217  /* no specific protocol/service specified, preserve all BOX
2218  records (for modern, GNS-enabled applications) */
2219  rd_off++;
2220  }
2221  break;
2222  }
2223  default:
2224  rd_off++;
2225  break;
2226  } /* end: switch */
2227  } /* end: for rd_count */
2228 
2229  /* yes, we are done, return result */
2231  "Returning GNS response for `%s' with %u answers\n",
2232  rh->ac_tail->label,
2233  rd_off);
2234  rh->proc (rh->proc_cls,
2235  rd_off,
2236  rd_new);
2238  rh);
2239  return;
2240  }
2241 
2242  switch (rd[0].record_type)
2243  {
2245  GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2247  &rd[0]);
2248  return;
2250  GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2252  &rd[0]);
2253  return;
2254  default:
2255  if (GNUNET_OK ==
2257  rd_count,
2258  rd))
2259  return;
2260  break;
2261  }
2262  fail:
2264  _("GNS lookup recursion failed (no delegation record found)\n"));
2265  fail_resolution (rh);
2266 }
2267 
2268 
2277 static void
2279  int32_t success,
2280  const char *emsg)
2281 {
2282  struct CacheOps *co = cls;
2283 
2284  co->namecache_qe_cache = NULL;
2285  if (GNUNET_OK != success)
2287  _("Failed to cache GNS resolution: %s\n"),
2288  emsg);
2289  GNUNET_CONTAINER_DLL_remove (co_head,
2290  co_tail,
2291  co);
2292  GNUNET_free (co);
2293 }
2294 
2295 
2313 static void
2315  struct GNUNET_TIME_Absolute exp,
2316  const struct GNUNET_HashCode *key,
2317  const struct GNUNET_PeerIdentity *get_path,
2318  unsigned int get_path_length,
2319  const struct GNUNET_PeerIdentity *put_path,
2320  unsigned int put_path_length,
2321  enum GNUNET_BLOCK_Type type,
2322  size_t size,
2323  const void *data)
2324 {
2325  struct GNS_ResolverHandle *rh = cls;
2326  struct AuthorityChain *ac = rh->ac_tail;
2327  const struct GNUNET_GNSRECORD_Block *block;
2328  struct CacheOps *co;
2329 
2330  (void) exp;
2331  (void) key;
2332  (void) get_path;
2333  (void) get_path_length;
2334  (void) put_path;
2335  (void) put_path_length;
2336  (void) type;
2338  rh->get_handle = NULL;
2340  rh->dht_heap_node = NULL;
2342  "Handling response from the DHT\n");
2343  if (size < sizeof (struct GNUNET_GNSRECORD_Block))
2344  {
2345  /* how did this pass DHT block validation!? */
2346  GNUNET_break (0);
2347  fail_resolution (rh);
2348  return;
2349  }
2350  block = data;
2351  if (size !=
2352  ntohl (block->purpose.size) +
2353  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) +
2354  sizeof (struct GNUNET_CRYPTO_EcdsaSignature))
2355  {
2356  /* how did this pass DHT block validation!? */
2357  GNUNET_break (0);
2358  fail_resolution (rh);
2359  return;
2360  }
2362  "Decrypting DHT block of size %u for `%s', expires %s\n",
2363  ntohl (block->purpose.size),
2364  rh->name,
2366  if (GNUNET_OK !=
2369  ac->label,
2371  rh))
2372  {
2373  GNUNET_break_op (0); /* block was ill-formed */
2374  fail_resolution (rh);
2375  return;
2376  }
2378  {
2380  "Received expired block from the DHT, will not cache it.\n");
2381  return;
2382  }
2383  if (GNUNET_YES == disable_cache)
2384  return;
2385  /* Cache well-formed blocks */
2387  "Caching response from the DHT in namecache\n");
2388  co = GNUNET_new (struct CacheOps);
2389  co->namecache_qe_cache = GNUNET_NAMECACHE_block_cache (namecache_handle,
2390  block,
2392  co);
2393  GNUNET_CONTAINER_DLL_insert (co_head,
2394  co_tail,
2395  co);
2396 }
2397 
2398 
2405 static void
2407  const struct GNUNET_HashCode *query)
2408 {
2409  struct GNS_ResolverHandle *rx;
2410 
2411  GNUNET_assert (NULL == rh->get_handle);
2412  rh->get_handle = GNUNET_DHT_get_start (dht_handle,
2414  query,
2417  NULL, 0,
2418  &handle_dht_response, rh);
2419  rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
2420  rh,
2421  GNUNET_TIME_absolute_get ().abs_value_us);
2423  {
2424  /* fail longest-standing DHT request */
2425  rx = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
2426  rx->dht_heap_node = NULL;
2427  GNUNET_assert (NULL != rx);
2428  fail_resolution (rx);
2429  }
2430 }
2431 
2432 
2441 static void
2443  unsigned int rd_count,
2444  const struct GNUNET_GNSRECORD_Data *rd)
2445 {
2446  struct GNS_ResolverHandle *rh = cls;
2447 
2448  if (0 == rd_count)
2450  _("GNS namecache returned empty result for `%s'\n"),
2451  rh->name);
2453  rd_count,
2454  rd);
2455 }
2456 
2457 
2464 static void
2466  const struct GNUNET_GNSRECORD_Block *block)
2467 {
2468  struct GNS_ResolverHandle *rh = cls;
2469  struct AuthorityChain *ac = rh->ac_tail;
2470  const char *label = ac->label;
2471  const struct GNUNET_CRYPTO_EcdsaPublicKey *auth = &ac->authority_info.gns_authority;
2472  struct GNUNET_HashCode query;
2473 
2474  GNUNET_assert (NULL != rh->namecache_qe);
2475  rh->namecache_qe = NULL;
2476  if ( ( (GNUNET_GNS_LO_DEFAULT == rh->options) ||
2477  ( (GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2478  (ac != rh->ac_head) ) ) &&
2479  ( (NULL == block) ||
2481  {
2482  /* namecache knows nothing; try DHT lookup */
2484  label,
2485  &query);
2487  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2488  ac->label,
2490  GNUNET_h2s (&query));
2491  start_dht_request (rh, &query);
2492  return;
2493  }
2494 
2495  if ( (NULL == block) ||
2497  {
2498  /* DHT not permitted and no local result, fail */
2500  "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2501  ac->label,
2503  fail_resolution (rh);
2504  return;
2505  }
2507  "Received result from namecache for label `%s'\n",
2508  ac->label);
2509 
2510  if (GNUNET_OK !=
2512  auth,
2513  label,
2515  rh))
2516  {
2517  GNUNET_break_op (0); /* block was ill-formed */
2518  /* try DHT instead */
2520  label,
2521  &query);
2523  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2524  ac->label,
2526  GNUNET_h2s (&query));
2527  start_dht_request (rh, &query);
2528  return;
2529  }
2530 }
2531 
2532 
2538 static void
2540 {
2541  struct AuthorityChain *ac = rh->ac_tail;
2542  struct GNUNET_HashCode query;
2543 
2545  "Starting GNS resolution for `%s' in zone %s\n",
2546  ac->label,
2549  ac->label,
2550  &query);
2551  if (GNUNET_YES != disable_cache)
2552  {
2553  rh->namecache_qe
2554  = GNUNET_NAMECACHE_lookup_block (namecache_handle,
2555  &query,
2557  rh);
2558  GNUNET_assert (NULL != rh->namecache_qe);
2559  }
2560  else
2561  {
2562  start_dht_request (rh,
2563  &query);
2564  }
2565 }
2566 
2567 
2574 static void
2576  int is_valid)
2577 {
2578  struct GNS_ResolverHandle *rh = cls;
2579  struct AuthorityChain *ac = rh->ac_tail;
2580 
2581  rh->rev_check = NULL;
2582  if (GNUNET_YES != is_valid)
2583  {
2585  _("Zone %s was revoked, resolution fails\n"),
2587  fail_resolution (rh);
2588  return;
2589  }
2591 }
2592 
2593 
2599 static void
2601 {
2602  struct AuthorityChain *ac = rh->ac_tail;
2603 
2605  "Starting revocation check for zone %s\n",
2610  rh);
2611  GNUNET_assert (NULL != rh->rev_check);
2612 }
2613 
2614 
2620 static void
2622 {
2623  struct GNS_ResolverHandle *rh = cls;
2624 
2625  rh->task_id = NULL;
2626  if (MAX_RECURSION < rh->loop_limiter++)
2627  {
2629  "Encountered unbounded recursion resolving `%s'\n",
2630  rh->name);
2631  fail_resolution (rh);
2632  return;
2633  }
2634  if (GNUNET_YES == rh->ac_tail->gns_authority)
2636  else
2638 }
2639 
2640 
2647 static void
2649 {
2650  struct GNS_ResolverHandle *rh = cls;
2651  struct AuthorityChain *ac;
2652  struct in_addr v4;
2653  struct in6_addr v6;
2654 
2655  rh->task_id = NULL;
2656  if (1 == inet_pton (AF_INET,
2657  rh->name,
2658  &v4))
2659  {
2660  /* name is IPv4 address, pretend it's an A record */
2661  struct GNUNET_GNSRECORD_Data rd;
2662 
2663  rd.data = &v4;
2664  rd.data_size = sizeof (v4);
2665  rd.expiration_time = UINT64_MAX;
2667  rd.flags = 0;
2668  rh->proc (rh->proc_cls,
2669  1,
2670  &rd);
2671  GNUNET_assert (NULL == rh->task_id);
2673  rh);
2674  return;
2675  }
2676  if (1 == inet_pton (AF_INET6,
2677  rh->name,
2678  &v6))
2679  {
2680  /* name is IPv6 address, pretend it's an AAAA record */
2681  struct GNUNET_GNSRECORD_Data rd;
2682 
2683  rd.data = &v6;
2684  rd.data_size = sizeof (v6);
2685  rd.expiration_time = UINT64_MAX;
2687  rd.flags = 0;
2688  rh->proc (rh->proc_cls,
2689  1,
2690  &rd);
2691  GNUNET_assert (NULL == rh->task_id);
2693  rh);
2694  return;
2695  }
2696 
2697  ac = GNUNET_new (struct AuthorityChain);
2698  ac->rh = rh;
2700  if (NULL == ac->label)
2701  /* name was just the "TLD", so we default to label
2702  #GNUNET_GNS_EMPTY_LABEL_AT */
2704  ac->gns_authority = GNUNET_YES;
2707  rh->ac_tail,
2708  ac);
2710  rh);
2711 }
2712 
2713 
2726 struct GNS_ResolverHandle *
2728  uint32_t record_type,
2729  const char *name,
2732  void *proc_cls)
2733 {
2734  struct GNS_ResolverHandle *rh;
2735 
2737  "Starting lookup for `%s'\n",
2738  name);
2739  rh = GNUNET_new (struct GNS_ResolverHandle);
2740  GNUNET_CONTAINER_DLL_insert (rlh_head,
2741  rlh_tail,
2742  rh);
2743  rh->authority_zone = *zone;
2744  rh->proc = proc;
2745  rh->proc_cls = proc_cls;
2746  rh->options = options;
2747  rh->record_type = record_type;
2748  rh->name = GNUNET_strdup (name);
2749  rh->name_resolution_pos = strlen (name);
2751  rh);
2752  return rh;
2753 }
2754 
2755 
2761 void
2763 {
2764  struct DnsResult *dr;
2765  struct AuthorityChain *ac;
2766  struct VpnContext *vpn_ctx;
2767 
2768  GNUNET_CONTAINER_DLL_remove (rlh_head,
2769  rlh_tail,
2770  rh);
2771  if (NULL != rh->dns_request)
2772  {
2774  rh->dns_request = NULL;
2775  }
2776  while (NULL != (ac = rh->ac_head))
2777  {
2779  rh->ac_tail,
2780  ac);
2781  if (GNUNET_NO == ac->gns_authority)
2782  {
2783  struct Gns2DnsPending *gp;
2784 
2785  while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2786  {
2788  ac->authority_info.dns_authority.gp_tail,
2789  gp);
2790  if (NULL != gp->rh)
2791  {
2792  /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2793  using GNS_resolver_lookup_cancel here, we need to
2794  add it first... */
2795  GNUNET_CONTAINER_DLL_insert (rlh_head,
2796  rlh_tail,
2797  gp->rh);
2798  GNUNET_assert (NULL == gp->rh->task_id);
2800  gp->rh);
2801  gp->rh = NULL;
2802  }
2803  if (NULL != gp->dns_rh)
2804  {
2806  gp->dns_rh = NULL;
2807  }
2808  GNUNET_free (gp);
2809  }
2811  }
2812  GNUNET_free (ac->label);
2813  GNUNET_free (ac);
2814  }
2815  if (NULL != rh->task_id)
2816  {
2818  rh->task_id = NULL;
2819  }
2820  if (NULL != rh->get_handle)
2821  {
2823  rh->get_handle = NULL;
2824  }
2825  if (NULL != rh->dht_heap_node)
2826  {
2828  rh->dht_heap_node = NULL;
2829  }
2830  if (NULL != (vpn_ctx = rh->vpn_ctx))
2831  {
2833  GNUNET_free (vpn_ctx->rd_data);
2834  GNUNET_free (vpn_ctx);
2835  }
2836  if (NULL != rh->namecache_qe)
2837  {
2839  rh->namecache_qe = NULL;
2840  }
2841  if (NULL != rh->rev_check)
2842  {
2844  rh->rev_check = NULL;
2845  }
2846  if (NULL != rh->std_resolve)
2847  {
2849  "Canceling standard DNS resolution\n");
2851  rh->std_resolve = NULL;
2852  }
2853  while (NULL != (dr = rh->dns_result_head))
2854  {
2856  rh->dns_result_tail,
2857  dr);
2858  GNUNET_free (dr);
2859  }
2860  GNUNET_free_non_null (rh->leho);
2861  GNUNET_free (rh->name);
2862  GNUNET_free (rh);
2863 }
2864 
2865 
2866 /* ***************** Resolver initialization ********************* */
2867 
2868 
2877 void
2879  struct GNUNET_DHT_Handle *dht,
2880  const struct GNUNET_CONFIGURATION_Handle *c,
2881  unsigned long long max_bg_queries)
2882 {
2883  cfg = c;
2884  namecache_handle = nc;
2885  dht_handle = dht;
2886  dht_lookup_heap =
2888  max_allowed_background_queries = max_bg_queries;
2890  "namecache",
2891  "DISABLE");
2892  if (GNUNET_YES == disable_cache)
2894  "Namecache disabled\n");
2895  vpn_handle = GNUNET_VPN_connect (cfg);
2896 }
2897 
2898 
2902 void
2904 {
2905  struct GNS_ResolverHandle *rh;
2906  struct CacheOps *co;
2907 
2908  /* abort active resolutions */
2909  while (NULL != (rh = rlh_head))
2910  {
2911  rh->proc (rh->proc_cls,
2912  0,
2913  NULL);
2915  }
2916  while (NULL != (co = co_head))
2917  {
2918  GNUNET_CONTAINER_DLL_remove (co_head,
2919  co_tail,
2920  co);
2922  GNUNET_free (co);
2923  }
2924  GNUNET_CONTAINER_heap_destroy (dht_lookup_heap);
2925  dht_lookup_heap = NULL;
2926  GNUNET_VPN_disconnect (vpn_handle);
2927  vpn_handle = NULL;
2928  dht_handle = NULL;
2929  namecache_handle = NULL;
2930 }
2931 
2932 
2933 /* 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:119
struct GNUNET_DNSPARSER_Record * answers
Array of all answers in the packet, must contain "num_answers" entries.
static struct GNUNET_VPN_Handle * vpn_handle
Our handle to the vpn service.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
Information from SOA records (RFC 1035).
For the rightmost label, only look in the cache (it is our local namestore), for the others...
static struct GNUNET_NAMECACHE_Handle * namecache_handle
Our handle to the namecache service.
struct GNUNET_TIME_AbsoluteNBO expiration_time
Expiration time of the block.
Payload of GNS VPN record.
unsigned int num_results
How many results did we get?
GNUNET_NETWORK_STRUCT_END ssize_t GNUNET_GNSRECORD_records_get_size(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Calculate how many bytes we will need to serialize the given records.
#define memrchr(s, c, n)
Definition: compat.h:48
struct GNS_ResolverHandle * rh
Handle for the resolution of the IP part of the GNS2DNS record.
void GNUNET_REVOCATION_query_cancel(struct GNUNET_REVOCATION_Query *q)
Cancel key revocation check.
static struct GNUNET_CONTAINER_Heap * dht_lookup_heap
Heap for limiting parallel DHT lookups.
void GNS_resolver_lookup_cancel(struct GNS_ResolverHandle *rh)
Cancel active resolution (i.e.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
uint16_t service
Service of the boxed record (aka port number), in NBO.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
#define GNUNET_TIME_UNIT_HOURS
One hour.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:670
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:344
uint64_t rel_value_us
The actual value.
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:150
GNUNET_BLOCK_Type
Blocks in the datastore and the datacache must have a unique type.
static void recursive_gns_resolution_revocation(struct GNS_ResolverHandle *rh)
Perform revocation check on tail of our authority chain.
#define GNUNET_DNSPARSER_TYPE_CNAME
#define DHT_GNS_REPLICATION_LEVEL
DHT replication level.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe_cache
Pending Namestore caching task.
struct GNUNET_DHT_GetHandle * get_handle
Handle for DHT lookups.
static void handle_namecache_block_response(void *cls, const struct GNUNET_GNSRECORD_Block *block)
Process a record that was stored in the namecache.
char * mxhost
Name of the mail server.
struct GNUNET_DNSPARSER_SrvRecord * srv
SRV data for SRV records.
ssize_t GNUNET_GNSRECORD_records_serialize(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, size_t dest_size, char *dest)
Serialize the given records to the given destination buffer.
static void handle_dns_result(void *cls, const struct sockaddr *addr, socklen_t addrlen)
We had to do a DNS lookup.
static void GNS_resolver_lookup_cancel_(void *cls)
Wrapper around GNS_resolver_lookup_cancel() as a task.
const char * GNS_get_tld(const char *name)
Obtain the TLD of the given name.
struct GNS_ResolverHandle * next
DLL.
static void timeout_resolution(void *cls)
Function called when a resolution times out.
uint64_t expiration_time
Expiration time for the DNS record, 0 if we didn&#39;t get anything useful (i.e.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:245
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:731
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
char * label
label/name corresponding to the authority
#define GNUNET_GNSRECORD_TYPE_ANY
Record type indicating any record/&#39;*&#39;.
static unsigned long long max_allowed_background_queries
Maximum amount of parallel queries to the DHT.
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
Convert an absolute domain name to the respective public key.
int GNUNET_DNSSTUB_add_dns_ip(struct GNUNET_DNSSTUB_Context *ctx, const char *dns_ip)
Add nameserver for use by the DNSSTUB.
Definition: dnsstub.c:622
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:1125
uint16_t id
DNS ID (to match replies to requests).
struct AuthorityChain * prev
This is a DLL.
GNUNET_GNS_LocalOptions
Options for the GNS lookup.
GNS_ResultProcessor proc
called when resolution phase finishes
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:854
struct GNUNET_VPN_RedirectionRequest * vpn_request
Handle to the VPN request that we were performing.
#define VPN_TIMEOUT
Default timeout for VPN redirections.
#define GNUNET_NO
Definition: gnunet_common.h:81
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:401
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:927
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
size_t data_size
Number of bytes in data.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
char * name
The name to resolve.
int gns_authority
GNUNET_YES if the authority was a GNS authority, GNUNET_NO if the authority was a DNS authority...
int GNUNET_GNSRECORD_records_deserialize(size_t len, const char *src, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest)
Deserialize the given records to the given destination.
Information we have in an encrypted block with record data (i.e.
struct GNUNET_DNSPARSER_Record * additional_records
Array of all additional answers in the packet, must contain "num_additional_records" entries...
#define GNUNET_GNSRECORD_TYPE_BOX
Record type for a boxed record (see TLSA/SRV handling in GNS).
static int ret
Final status code.
Definition: gnunet-arm.c:89
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).
#define GNUNET_GNSRECORD_TYPE_NICK
Record type for GNS nick names ("NICK").
static int disable_cache
Use namecache.
unsigned int num_answers
Number of answers in the packet, should be 0 for queries.
uint64_t abs_value_us
The actual value.
uint16_t id
Unique identifier for the request/response.
IPC messages between GNS API and GNS service.
struct AuthorityChain * ac_head
DLL to store the authority chain.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static void namecache_cache_continuation(void *cls, int32_t success, const char *emsg)
Function called once the namestore has completed the request for caching a block. ...
Handle to a currenty pending resolution.
void * proc_cls
closure passed to proc
Connection to the DHT service.
Definition: dht_api.c:205
uint32_t record_type
Type of the GNS/DNS record.
#define GNUNET_GNSRECORD_TYPE_VPN
Record type for VPN resolution.
static void start_resolver_lookup(void *cls)
Begin the resolution process from &#39;name&#39;, starting with the identification of the zone specified by &#39;...
Opaque VPN handle.
Definition: vpn_api.c:34
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
Active namestore caching operations.
#define GNUNET_DNSPARSER_TYPE_PTR
const void * data
Binary value stored in the DNS record (appended to this struct)
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
static char * zone
Name of the zone we manage.
int found
Did we succeed in getting an IP address for any of the DNS servers listed? Once we do...
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
#define GNUNET_DNSPARSER_MAX_NAME_LENGTH
Maximum length of a name in DNS.
#define GNUNET_DNSPARSER_TYPE_SOA
int service
For SRV and TLSA records, the number of the service specified in the name.
char * name
Name of the record that the query is for (0-terminated).
char * hostname
For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
#define GNUNET_memcpy(dst, src, n)
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:662
#define GNUNET_GNSRECORD_TYPE_PKEY
Record type for GNS zone transfer ("PKEY").
struct AuthorityChain * ac_tail
DLL to store the authority chain.
static int recursive_gns2dns_resolution(struct GNS_ResolverHandle *rh, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
We found one or more GNS2DNS records, perform recursive resolution on it.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition: dnsstub.c:595
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:1273
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Record type for delegation to DNS.
int is_canonical(const char *name)
Determine if this name is canonical (is a legal name in a zone, without delegation); note that we do ...
char * rname
A domainname which specifies the mailbox of the person responsible for this zone. ...
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:487
void GNUNET_VPN_disconnect(struct GNUNET_VPN_Handle *vh)
Disconnect from the VPN service.
Definition: vpn_api.c:526
Randomness for IVs etc.
int protocol
For SRV and TLSA records, the number of the protocol specified in the name.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe
Pending Namecache lookup task.
an ECC signature using ECDSA
static char buf[2048]
static struct GNUNET_DHT_Handle * dht_handle
Resolver handle to the dht.
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:804
#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:1084
uint16_t protocol
Protocol of the boxed record (6 = TCP, 17 = UDP, etc.).
struct GNUNET_SCHEDULER_Task * task_id
ID of a task associated with the resolution process.
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
A DNS response record.
Heap with the minimum cost at the root.
struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_block_cache(struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_GNSRECORD_Block *block, GNUNET_NAMECACHE_ContinuationWithStatus cont, void *cont_cls)
Store an item in the namecache.
Block for storing record data.
struct GNUNET_DNSPARSER_Record * authority_records
Array of all authority records in the packet, must contain "num_authority_records" entries...
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
A 512-bit hashcode.
Handle to the stub resolver.
Definition: dnsstub.c:125
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_CRYPTO_EcdsaPublicKey *z)
Convert a zone key to a string (for printing debug messages).
struct GNUNET_DNSPARSER_Query * queries
Array of all queries in the packet, must contain "num_queries" entries.
void GNUNET_DHT_get_stop(struct GNUNET_DHT_GetHandle *get_handle)
Stop async DHT-get.
Definition: dht_api.c:1160
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:446
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
void GNUNET_VPN_cancel_request(struct GNUNET_VPN_RedirectionRequest *rr)
Cancel redirection request with the service.
Definition: vpn_api.c:369
size_t name_resolution_pos
Current offset in &#39;name&#39; where we are resolving.
static void handle_gns_namecache_resolution_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process a records that were decrypted from a block that we got from the namecache.
static void transmit_lookup_dns_result(struct GNS_ResolverHandle *rh)
Gives the cummulative result obtained to the callback and clean up the request.
struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve(struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls)
Perform DNS resolution using our default IP from init.
Definition: dnsstub.c:533
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:404
#define DNS_LOOKUP_TIMEOUT
Default timeout for DNS lookups.
struct GNUNET_PeerIdentity peer
The peer to contact.
struct GNUNET_CONTAINER_HeapNode * dht_heap_node
Heap node associated with this lookup.
GNUnet GNS service.
static void handle_gns2dns_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
We&#39;ve resolved the IP address for the DNS resolver to use after encountering a GNS2DNS record...
uint16_t proto
The protocol to use.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
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:1008
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:100
Opaque redirection request handle.
Definition: vpn_api.c:77
const char * name
void(* GNS_ResultProcessor)(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Function called with results for a GNS resolution.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static void continue_with_gns2dns(struct AuthorityChain *ac)
We have resolved one or more of the nameservers for a GNS2DNS lookup.
unsigned int num_authority_records
Number of authoritative answers in the packet, should be 0 for queries.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
struct DnsResult * prev
Kept in DLL.
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, uint32_t record_type, const char *name, enum GNUNET_GNS_LocalOptions options, GNS_ResultProcessor proc, void *proc_cls)
Lookup of a record in a specific zone calls lookup result processor on result.
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.
static struct GNUNET_NAMESTORE_Handle * ns
Handle to the namestore.
struct GNUNET_CRYPTO_EcdsaPublicKey authority_zone
The top-level GNS authoritative zone to query.
uint32_t record_type
GNS record type of the boxed record.
#define GNUNET_TUN_DNS_CLASS_INTERNET
A few common DNS classes (ok, only one is common, but I list a couple more to make it clear what we&#39;r...
char * rd_data
Serialized records.
Handle to a GET request.
Definition: dht_api.c:80
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_lookup_block(struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_HashCode *derived_hash, GNUNET_NAMECACHE_BlockProcessor proc, void *proc_cls)
Get a result for a particular key from the namecache.
static char * translate_dot_plus(struct GNS_ResolverHandle *rh, char *name)
Expands a name ending in .
static void handle_gns2dns_ip(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Function called by the resolver for each address obtained from DNS.
struct GNUNET_DNSSTUB_RequestSocket * dns_request
Socket for a DNS request, NULL if none is active.
struct Gns2DnsPending * prev
Kept in a DLL.
struct GNUNET_TIME_Absolute expiration_time
When does the record expire?
#define GNUNET_GNSRECORD_TYPE_LEHO
Record type for GNS legacy hostnames ("LEHO").
static void fail_resolution(struct GNS_ResolverHandle *rh)
Function called to asynchronously fail a resolution.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
uint16_t original_dns_id
16 bit random ID we used in the dns_request.
static void handle_gns_cname_result(struct GNS_ResolverHandle *rh, const char *cname)
We encountered a CNAME record during our resolution.
struct GNUNET_VPN_Handle * GNUNET_VPN_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the VPN service.
Definition: vpn_api.c:504
The identity of the host (wraps the signing key of the peer).
struct GNUNET_DNSPARSER_MxRecord * mx
MX data for MX records.
struct GNUNET_RESOLVER_RequestHandle * dns_rh
Handle for DNS resolution of the DNS nameserver.
uint32_t record_type
Type of the GNS/DNS record.
#define GNUNET_DNSPARSER_TYPE_AAAA
configuration data
Definition: configuration.c:85
Closure for vpn_allocation_cb.
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition: dnsstub.c:571
#define GNUNET_DNSPARSER_TYPE_NS
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:1072
static struct GNUNET_CRYPTO_EddsaPublicKey pub
Definition: gnunet-scrypt.c:39
Easy-to-process, parsed version of a DNS packet.
static void start_dht_request(struct GNS_ResolverHandle *rh, const struct GNUNET_HashCode *query)
Initiate a DHT query for a set of GNS records.
static void dns_result_parser(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
Function called with the result of a DNS resolution.
int GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls)
Decrypt block.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
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:96
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.
static int inet_pton(int af, const char *cp, struct in_addr *buf)
Convert IPv4 address from text to binary form.
#define GNUNET_log(kind,...)
static struct GNS_ResolverHandle * rlh_head
Head of resolver lookup list.
Entry in list of pending tasks.
Definition: scheduler.c:134
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
static struct GNS_ResolverHandle * rlh_tail
Tail of resolver lookup list.
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EcdsaPublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.
static char * rp
Relying party.
char * name
Name of the record that the query is for (0-terminated).
#define GNUNET_TUN_DNS_OPCODE_QUERY
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
struct CacheOps * next
Organized in a DLL.
unsigned int num_queries
Number of queries in the packet.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct Gns2DnsPending * next
Kept in a DLL.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
struct GNUNET_REVOCATION_Query * rev_check
Pending revocation check.
An QueueEntry used to store information for a pending NAMECACHE record operation. ...
Definition: namecache_api.c:47
Defaults, look in cache, then in DHT.
struct DnsResult * dns_result_tail
DLL of results we got from DNS.
void GNUNET_GNSRECORD_query_from_public_key(const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
struct Gns2DnsPending * gp_head
List of resolutions of the &#39;ip&#39; of the name server that are still pending.
static struct CacheOps * co_tail
Organized in a DLL.
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
This flag is currently unused; former RF_PENDING flag.
union GNUNET_DNSPARSER_Record::@27 data
Payload of the record (which one of these is valid depends on the &#39;type&#39;).
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:792
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:43
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
static void recursive_dns_resolution(struct GNS_ResolverHandle *rh)
Perform recursive DNS resolution.
char * leho
Legacy Hostname to use if we encountered GNS2DNS record and thus can deduct the LEHO from that transi...
#define GNUNET_DNSPARSER_TYPE_SRV
uint32_t data
The data value.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
struct AuthorityChain * next
This is a DLL.
static size_t data_size
Number of bytes in data.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Number of bytes signed; also specifies the number of bytes of encrypted data that follow...
static struct GNUNET_DHT_Handle * dht
Handle to the DHT.
static char * address
GNS address for this phone.
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
void GNUNET_DNSPARSER_free_mx(struct GNUNET_DNSPARSER_MxRecord *mx)
Free MX information record.
Definition: dnsparser.c:165
#define GNUNET_DNSPARSER_TYPE_A
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
int GNUNET_DNSSTUB_add_dns_sa(struct GNUNET_DNSSTUB_Context *ctx, const struct sockaddr *sa)
Add nameserver for use by the DNSSTUB.
Definition: dnsstub.c:680
union AuthorityChain::@22 authority_info
Information about the resolver authority for this label.
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...
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...
struct AuthorityChain::@22::@23 dns_authority
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965