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 
88 
93 
97  struct AuthorityChain *ac;
98 
105 
110 
114  unsigned int num_results;
115 };
116 
117 
122 struct GNS_ResolverHandle;
123 
124 
134 
139 
144 
148  char *label;
149 
155 
159  union {
163  struct GNUNET_CRYPTO_EcdsaPublicKey gns_authority;
164 
165  struct {
172 
178 
184 
189 
194  int found;
195 
199  int launched;
200  } dns_authority;
201  } authority_info;
202 };
203 
204 
208 struct DnsResult {
212  struct DnsResult *next;
213 
217  struct DnsResult *prev;
218 
222  const void *data;
223 
228  uint64_t expiration_time;
229 
233  size_t data_size;
234 
238  uint32_t record_type;
239 };
240 
241 
245 struct VpnContext {
250 
255 
259  unsigned int rd_count;
260 
264  char *rd_data;
265 
269  ssize_t rd_data_size;
270 };
271 
272 
282 
287 
291  struct GNUNET_CRYPTO_EcdsaPublicKey authority_zone;
292 
297 
301  void* proc_cls;
302 
307 
312 
317 
322 
327 
332 
338 
343 
348 
353 
357  char *name;
358 
363  char *leho;
364 
369 
374 
379 
384 
389  int protocol;
390 
395  int service;
396 
401 
407  unsigned int loop_limiter;
408 
412  uint16_t original_dns_id;
413 };
414 
415 
419 struct CacheOps {
423  struct CacheOps *next;
424 
428  struct CacheOps *prev;
429 
434 };
435 
436 
441 
446 
451 
456 
460 static unsigned long long max_allowed_background_queries;
461 
466 
471 
475 static struct CacheOps *co_head;
476 
480 static struct CacheOps *co_tail;
481 
485 static int disable_cache;
486 
490 static const struct GNUNET_CONFIGURATION_Handle *cfg;
491 
492 
508 /* dead, but keep for now */ int
509 is_canonical(const char *name)
510 {
511  const char *pos;
512  const char *dot;
513 
514  if (NULL == strchr(name,
515  (unsigned char)'.'))
516  return GNUNET_YES;
517  if ('_' != name[0])
518  return GNUNET_NO;
519  pos = &name[1];
520  while (NULL != (dot = strchr(pos,
521  (unsigned char)'.')))
522  if ('_' != dot[1])
523  return GNUNET_NO;
524  else
525  pos = dot + 1;
526  return GNUNET_YES;
527 }
528 
529 /* ************************** Resolution **************************** */
530 
538 static char *
540  char *name)
541 {
542  char *ret;
543  size_t s_len = strlen(name);
544 
545  if (0 != strcmp(&name[s_len - 2],
546  ".+"))
547  return name; /* did not end in ".+" */
549  GNUNET_asprintf(&ret,
550  "%.*s.%s",
551  (int)(s_len - 2),
552  name,
554  GNUNET_free(name);
555  return ret;
556 }
557 
558 
565 static void
567 {
568  struct GNS_ResolverHandle *rh = cls;
569 
570  rh->task_id = NULL;
572 }
573 
574 
580 static void
582 {
583  rh->proc(rh->proc_cls,
584  0,
585  NULL);
586  GNUNET_assert(NULL == rh->task_id);
588  rh);
589 }
590 
591 
597 static void
599 {
600  struct GNS_ResolverHandle *rh = cls;
601 
602  rh->task_id = NULL;
603  fail_resolution(rh);
604 }
605 
606 
624 static char *
626 {
627  const char *rp;
628  const char *dot;
629  size_t len;
630  char *ret;
631  char *srv_name;
632  char *proto_name;
633  struct protoent *pe;
634  struct servent *se;
635 
636  if (0 == rh->name_resolution_pos)
637  return NULL;
638  dot = memrchr(rh->name,
639  (int)'.',
640  rh->name_resolution_pos);
641  if (NULL == dot)
642  {
643  /* done, this was the last one */
644  len = rh->name_resolution_pos;
645  rp = rh->name;
646  rh->name_resolution_pos = 0;
647  }
648  else
649  {
650  /* advance by one label */
651  len = rh->name_resolution_pos - (dot - rh->name) - 1;
652  rp = dot + 1;
653  rh->name_resolution_pos = dot - rh->name;
654  }
655  rh->protocol = 0;
656  rh->service = 0;
657  ret = GNUNET_strndup(rp, len);
658  /* If we have labels starting with underscore with label on
659  * the right (SRV/DANE/BOX case), determine port/protocol;
660  * The format of `rh->name` must be "_PORT._PROTOCOL".
661  */
662  if (('_' == rh->name[0]) &&
663  (NULL != (dot = memrchr(rh->name,
664  (int)'.',
665  rh->name_resolution_pos))) &&
666  ('_' == dot[1]) &&
667  (NULL == memrchr(rh->name,
668  (int)'.',
669  dot - rh->name)))
670  {
671  srv_name = GNUNET_strndup(&rh->name[1],
672  (dot - rh->name) - 1);
673  proto_name = GNUNET_strndup(&dot[2],
674  rh->name_resolution_pos - (dot - rh->name) - 1);
675  rh->name_resolution_pos = 0;
676  pe = getprotobyname(proto_name);
677  if (NULL == pe)
678  {
680  _("Protocol `%s' unknown, skipping labels.\n"),
681  proto_name);
682  GNUNET_free(proto_name);
683  GNUNET_free(srv_name);
684  return ret;
685  }
686  se = getservbyname(srv_name,
687  proto_name);
688  if (NULL == se)
689  {
691  _("Service `%s' unknown for protocol `%s', skipping labels.\n"),
692  srv_name,
693  proto_name);
694  GNUNET_free(proto_name);
695  GNUNET_free(srv_name);
696  return ret;
697  }
698  rh->protocol = pe->p_proto;
699  rh->service = se->s_port;
700  GNUNET_free(proto_name);
701  GNUNET_free(srv_name);
702  }
703  return ret;
704 }
705 
706 
712 static void
714 {
715  struct DnsResult *pos;
716  unsigned int n;
717  unsigned int i;
718 
719  n = 0;
720  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
721  n++;
722  {
723  struct GNUNET_GNSRECORD_Data rd[n];
724 
725  i = 0;
726  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
727  {
728  rd[i].data = pos->data;
729  rd[i].data_size = pos->data_size;
730  rd[i].record_type = pos->record_type;
731  if (0 == pos->expiration_time)
732  {
734  rd[i].expiration_time = 0;
735  }
736  else
737  {
739  rd[i].expiration_time = pos->expiration_time;
740  }
741  i++;
742  }
743  GNUNET_assert(i == n);
745  "Transmitting standard DNS result with %u records\n",
746  n);
747  rh->proc(rh->proc_cls,
748  n,
749  rd);
750  }
752 }
753 
754 
764 static void
766  uint64_t expiration_time,
767  uint32_t record_type,
768  size_t data_size,
769  const void *data)
770 {
771  struct DnsResult *res;
772 
773  res = GNUNET_malloc(sizeof(struct DnsResult) + data_size);
775  res->data_size = data_size;
776  res->record_type = record_type;
777  res->data = &res[1];
778  GNUNET_memcpy(&res[1],
779  data,
780  data_size);
782  rh->dns_result_tail,
783  res);
784 }
785 
786 
795 static void
797  const struct sockaddr *addr,
798  socklen_t addrlen)
799 {
800  struct GNS_ResolverHandle *rh = cls;
801  const struct sockaddr_in *sa4;
802  const struct sockaddr_in6 *sa6;
803 
804  if (NULL == addr)
805  {
806  rh->std_resolve = NULL;
808  return;
809  }
811  "Received %u bytes of DNS IP data\n",
812  addrlen);
813  switch (addr->sa_family)
814  {
815  case AF_INET:
816  sa4 = (const struct sockaddr_in *)addr;
817  add_dns_result(rh,
818  0 /* expiration time is unknown */,
820  sizeof(struct in_addr),
821  &sa4->sin_addr);
822  break;
823 
824  case AF_INET6:
825  sa6 = (const struct sockaddr_in6 *)addr;
826  add_dns_result(rh,
827  0 /* expiration time is unknown */,
829  sizeof(struct in6_addr),
830  &sa6->sin6_addr);
831  break;
832 
833  default:
834  GNUNET_break(0);
835  break;
836  }
837 }
838 
839 
846 static void
847 recursive_resolution(void *cls);
848 
849 
856 static void
857 start_resolver_lookup(void *cls);
858 
859 
868 static void
870  const struct GNUNET_TUN_DnsHeader *dns,
871  size_t dns_len)
872 {
873  struct GNS_ResolverHandle *rh = cls;
874  struct GNUNET_DNSPARSER_Packet *p;
875  const struct GNUNET_DNSPARSER_Record *rec;
876  unsigned int rd_count;
877 
878  if (NULL == dns)
879  {
880  rh->dns_request = NULL;
882  rh->task_id = NULL;
883  fail_resolution(rh);
884  return;
885  }
886  if (rh->original_dns_id != dns->id)
887  {
888  /* DNS answer, but for another query */
889  return;
890  }
891  p = GNUNET_DNSPARSER_parse((const char *)dns,
892  dns_len);
893  if (NULL == p)
894  {
896  _("Failed to parse DNS response\n"));
897  return;
898  }
899 
900  /* We got a result from DNS */
902  "Received DNS response for `%s' with %u answers\n",
903  rh->ac_tail->label,
904  (unsigned int)p->num_answers);
905  if ((p->num_answers > 0) &&
908  {
909  int af;
910 
912  "Got CNAME `%s' from DNS for `%s'\n",
913  p->answers[0].data.hostname,
914  rh->name);
915  if (NULL != rh->std_resolve)
916  {
918  "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
919  rh->name);
921  }
922  GNUNET_free(rh->name);
923  rh->name = GNUNET_strdup(p->answers[0].data.hostname);
924  rh->name_resolution_pos = strlen(rh->name);
925  switch (rh->record_type)
926  {
928  af = AF_INET;
929  break;
930 
932  af = AF_INET6;
933  break;
934 
935  default:
936  af = AF_UNSPEC;
937  break;
938  }
939  if (NULL != rh->leho)
940  add_dns_result(rh,
941  GNUNET_TIME_UNIT_HOURS.rel_value_us,
943  strlen(rh->leho),
944  rh->leho);
946  af,
949  rh);
952  rh->dns_request = NULL;
953  return;
954  }
955 
956  /* convert from (parsed) DNS to (binary) GNS format! */
958  {
959  struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
960  int skip;
961  char buf[UINT16_MAX];
962  size_t buf_off;
963  size_t buf_start;
964 
965  buf_off = 0;
966  skip = 0;
967  memset(rd,
968  0,
969  sizeof(rd));
970  for (unsigned int i = 0; i < rd_count; i++)
971  {
972  if (i < p->num_answers)
973  rec = &p->answers[i];
974  else if (i < p->num_answers + p->num_authority_records)
975  rec = &p->authority_records[i - p->num_answers];
976  else
978  /* As we copied the full DNS name to 'rh->ac_tail->label', this
979  should be the correct check to see if this record is actually
980  a record for our label... */
981  if (0 != strcmp(rec->name,
982  rh->ac_tail->label))
983  {
985  "Dropping record `%s', does not match desired name `%s'\n",
986  rec->name,
987  rh->ac_tail->label);
988  skip++;
989  continue;
990  }
991  rd[i - skip].record_type = rec->type;
992  rd[i - skip].expiration_time = rec->expiration_time.abs_value_us;
993  switch (rec->type)
994  {
996  if (rec->data.raw.data_len != sizeof(struct in_addr))
997  {
998  GNUNET_break_op(0);
999  skip++;
1000  continue;
1001  }
1002  rd[i - skip].data_size = rec->data.raw.data_len;
1003  rd[i - skip].data = rec->data.raw.data;
1004  break;
1005 
1007  if (rec->data.raw.data_len != sizeof(struct in6_addr))
1008  {
1009  GNUNET_break_op(0);
1010  skip++;
1011  continue;
1012  }
1013  rd[i - skip].data_size = rec->data.raw.data_len;
1014  rd[i - skip].data = rec->data.raw.data;
1015  break;
1016 
1020  buf_start = buf_off;
1021  if (GNUNET_OK !=
1023  sizeof(buf),
1024  &buf_off,
1025  rec->data.hostname))
1026  {
1027  GNUNET_break(0);
1028  skip++;
1029  continue;
1030  }
1031  rd[i - skip].data_size = buf_off - buf_start;
1032  rd[i - skip].data = &buf[buf_start];
1033  break;
1034 
1036  buf_start = buf_off;
1037  if (GNUNET_OK !=
1039  sizeof(buf),
1040  &buf_off,
1041  rec->data.soa))
1042  {
1043  GNUNET_break(0);
1044  skip++;
1045  continue;
1046  }
1047  rd[i - skip].data_size = buf_off - buf_start;
1048  rd[i - skip].data = &buf[buf_start];
1049  break;
1050 
1052  buf_start = buf_off;
1053  if (GNUNET_OK !=
1055  sizeof(buf),
1056  &buf_off,
1057  rec->data.mx))
1058  {
1059  GNUNET_break(0);
1060  skip++;
1061  continue;
1062  }
1063  rd[i - skip].data_size = buf_off - buf_start;
1064  rd[i - skip].data = &buf[buf_start];
1065  break;
1066 
1068  buf_start = buf_off;
1069  if (GNUNET_OK !=
1071  sizeof(buf),
1072  &buf_off,
1073  rec->data.srv))
1074  {
1075  GNUNET_break(0);
1076  skip++;
1077  continue;
1078  }
1079  rd[i - skip].data_size = buf_off - buf_start;
1080  rd[i - skip].data = &buf[buf_start];
1081  break;
1082 
1083  default:
1085  _("Skipping record of unsupported type %d\n"),
1086  rec->type);
1087  skip++;
1088  continue;
1089  }
1090  } /* end of for all records in answer */
1091  if (NULL != rh->leho)
1092  {
1093  rd[rd_count - skip].record_type = GNUNET_GNSRECORD_TYPE_LEHO;
1094  rd[rd_count - skip].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1095  rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1096  rd[rd_count - skip].data = rh->leho;
1097  rd[rd_count - skip].data_size = strlen(rh->leho);
1098  skip--; /* skip one LESS */
1100  "Adding LEHO %s\n",
1101  rh->leho);
1102  }
1104  "Returning DNS response for `%s' with %u answers\n",
1105  rh->ac_tail->label,
1106  (unsigned int)(rd_count - skip));
1107  rh->proc(rh->proc_cls,
1108  rd_count - skip,
1109  rd);
1111  rh->dns_request = NULL;
1112  }
1114  if (NULL != rh->task_id)
1115  GNUNET_SCHEDULER_cancel(rh->task_id); /* should be timeout task */
1117  rh);
1118 }
1119 
1120 
1129 static void
1131 {
1132  struct AuthorityChain *ac;
1133  struct GNUNET_DNSPARSER_Query *query;
1134  struct GNUNET_DNSPARSER_Packet *p;
1135  char *dns_request;
1136  size_t dns_request_length;
1137  int ret;
1138 
1139  ac = rh->ac_tail;
1140  GNUNET_assert(NULL != ac);
1142  "Starting DNS lookup for `%s'\n",
1143  ac->label);
1145  query = GNUNET_new(struct GNUNET_DNSPARSER_Query);
1146  query->name = GNUNET_strdup(ac->label);
1147  query->type = rh->record_type;
1149  p = GNUNET_new(struct GNUNET_DNSPARSER_Packet);
1150  p->queries = query;
1151  p->num_queries = 1;
1153  UINT16_MAX);
1155  p->flags.recursion_desired = 1;
1156  ret = GNUNET_DNSPARSER_pack(p,
1157  1024,
1158  &dns_request,
1159  &dns_request_length);
1160  if (GNUNET_OK != ret)
1161  {
1162  GNUNET_break(0);
1163  rh->proc(rh->proc_cls,
1164  0,
1165  NULL);
1166  GNUNET_assert(NULL == rh->task_id);
1168  rh);
1169  }
1170  else
1171  {
1172  rh->original_dns_id = p->id;
1173  GNUNET_assert(NULL != ac->authority_info.dns_authority.dns_handle);
1174  GNUNET_assert(NULL == rh->dns_request);
1175  rh->leho = GNUNET_strdup(ac->label);
1177  dns_request,
1178  dns_request_length,
1180  rh);
1183  rh);
1184  }
1185  if (GNUNET_SYSERR != ret)
1186  GNUNET_free(dns_request);
1188 }
1189 
1190 
1199 static void
1201  const char *cname)
1202 {
1203  size_t nlen;
1204  char *res;
1205  struct AuthorityChain *ac;
1206  int af;
1207 
1208  nlen = strlen(cname);
1209  if ((nlen > 2) &&
1210  (0 == strcmp(".+",
1211  &cname[nlen - 2])))
1212  {
1213  /* CNAME resolution continues relative to current domain */
1214  if (0 == rh->name_resolution_pos)
1215  {
1216  res = GNUNET_strndup(cname, nlen - 2);
1217  rh->name_resolution_pos = nlen - 2;
1218  }
1219  else
1220  {
1221  GNUNET_asprintf(&res,
1222  "%.*s.%.*s",
1223  (int)rh->name_resolution_pos,
1224  rh->name,
1225  (int)(nlen - 2),
1226  cname);
1227  rh->name_resolution_pos = strlen(res);
1228  }
1229  GNUNET_free(rh->name);
1230  rh->name = res;
1231  ac = GNUNET_new(struct AuthorityChain);
1232  ac->rh = rh;
1233  ac->gns_authority = GNUNET_YES;
1236  /* add AC to tail */
1238  rh->ac_tail,
1239  ac);
1241  rh);
1242  return;
1243  }
1245  "Got CNAME `%s' from GNS for `%s'\n",
1246  cname,
1247  rh->name);
1248  if (NULL != rh->std_resolve)
1249  {
1251  "Multiple CNAME results from GNS resolving `%s'! Not really allowed...\n",
1252  rh->name);
1254  }
1255  /* name is absolute, go to DNS */
1256  GNUNET_free(rh->name);
1257  rh->name = GNUNET_strdup(cname);
1258  rh->name_resolution_pos = strlen(rh->name);
1259  switch (rh->record_type)
1260  {
1262  af = AF_INET;
1263  break;
1264 
1266  af = AF_INET6;
1267  break;
1268 
1269  default:
1270  af = AF_UNSPEC;
1271  break;
1272  }
1274  "Doing standard DNS lookup for `%s'\n",
1275  rh->name);
1277  af,
1280  rh);
1281 }
1282 
1283 
1291 static void
1293  unsigned int rd_count,
1294  const struct GNUNET_GNSRECORD_Data *rd);
1295 
1296 
1311 static void
1313  int af,
1314  const void *address)
1315 {
1316  struct VpnContext *vpn_ctx = cls;
1317  struct GNS_ResolverHandle *rh = vpn_ctx->rh;
1318  struct GNUNET_GNSRECORD_Data rd[vpn_ctx->rd_count];
1319  unsigned int i;
1320 
1321  vpn_ctx->vpn_request = NULL;
1322  rh->vpn_ctx = NULL;
1324  GNUNET_GNSRECORD_records_deserialize((size_t)vpn_ctx->rd_data_size,
1325  vpn_ctx->rd_data,
1326  vpn_ctx->rd_count,
1327  rd));
1328  for (i = 0; i < vpn_ctx->rd_count; i++)
1329  {
1331  {
1332  switch (af)
1333  {
1334  case AF_INET:
1336  rd[i].data_size = sizeof(struct in_addr);
1338  rd[i].flags = 0;
1339  rd[i].data = address;
1340  break;
1341 
1342  case AF_INET6:
1345  rd[i].flags = 0;
1346  rd[i].data = address;
1347  rd[i].data_size = sizeof(struct in6_addr);
1348  break;
1349 
1350  default:
1351  GNUNET_assert(0);
1352  }
1353  break;
1354  }
1355  }
1356  GNUNET_assert(i < vpn_ctx->rd_count);
1357  if (0 == vpn_ctx->rd_count)
1359  _("VPN returned empty result for `%s'\n"),
1360  rh->name);
1362  vpn_ctx->rd_count,
1363  rd);
1364  GNUNET_free(vpn_ctx->rd_data);
1365  GNUNET_free(vpn_ctx);
1366 }
1367 
1368 
1376 static void
1378 {
1379  struct GNS_ResolverHandle *rh = ac->rh;
1380 
1381  if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1382  (GNUNET_NO == ac->authority_info.dns_authority.found))
1383  return; /* more pending and none found yet */
1384  if (GNUNET_NO == ac->authority_info.dns_authority.found)
1385  {
1387  "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1388  ac->authority_info.dns_authority.name);
1389  fail_resolution(rh);
1390  return;
1391  }
1392  if (GNUNET_NO != ac->authority_info.dns_authority.launched)
1393  return; /* already running, do not launch again! */
1394  /* recurse */
1395  ac->authority_info.dns_authority.launched = GNUNET_YES;
1397  "Will continue resolution using DNS to resolve `%s'\n",
1398  ac->label);
1399  GNUNET_assert(NULL == rh->task_id);
1401  rh);
1402 }
1403 
1404 
1413 static void
1415  unsigned int rd_count,
1416  const struct GNUNET_GNSRECORD_Data *rd)
1417 {
1418  struct Gns2DnsPending *gp = cls;
1419  struct AuthorityChain *ac = gp->ac;
1420 
1422  ac->authority_info.dns_authority.gp_tail,
1423  gp);
1424  /* enable cleanup of 'rh' handle that automatically comes after we return,
1425  and which expects 'rh' to be in the #rlh_head DLL. */
1426  if (NULL != gp->rh)
1427  {
1428  GNUNET_CONTAINER_DLL_insert(rlh_head,
1429  rlh_tail,
1430  gp->rh);
1431  gp->rh = NULL;
1432  }
1433  GNUNET_free(gp);
1435  "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1436  rd_count);
1437  /* find suitable A/AAAA record */
1438  for (unsigned int j = 0; j < rd_count; j++)
1439  {
1440  switch (rd[j].record_type)
1441  {
1443  {
1444  struct sockaddr_in v4;
1445 
1446  if (sizeof(struct in_addr) != rd[j].data_size)
1447  {
1448  GNUNET_break_op(0);
1449  continue;
1450  }
1451  memset(&v4,
1452  0,
1453  sizeof(v4));
1454  v4.sin_family = AF_INET;
1455  v4.sin_port = htons(53);
1456 #if HAVE_SOCKADDR_IN_SIN_LEN
1457  v4.sin_len = (u_char)sizeof(v4);
1458 #endif
1459  GNUNET_memcpy(&v4.sin_addr,
1460  rd[j].data,
1461  sizeof(struct in_addr));
1462  if (GNUNET_OK ==
1464  (const struct sockaddr *)&v4))
1466  break;
1467  }
1468 
1470  {
1471  struct sockaddr_in6 v6;
1472 
1473  if (sizeof(struct in6_addr) != rd[j].data_size)
1474  {
1475  GNUNET_break_op(0);
1476  continue;
1477  }
1478  /* FIXME: might want to check if we support IPv6 here,
1479  and otherwise skip this one and hope we find another */
1480  memset(&v6,
1481  0,
1482  sizeof(v6));
1483  v6.sin6_family = AF_INET6;
1484  v6.sin6_port = htons(53);
1485 #if HAVE_SOCKADDR_IN_SIN_LEN
1486  v6.sin6_len = (u_char)sizeof(v6);
1487 #endif
1488  GNUNET_memcpy(&v6.sin6_addr,
1489  rd[j].data,
1490  sizeof(struct in6_addr));
1491  if (GNUNET_OK ==
1493  (const struct sockaddr *)&v6))
1495  break;
1496  }
1497 
1498  default:
1499  break;
1500  }
1501  }
1503 }
1504 
1505 
1513 static void
1515  const struct sockaddr *addr,
1516  socklen_t addrlen)
1517 {
1518  struct Gns2DnsPending *gp = cls;
1519  struct AuthorityChain *ac = gp->ac;
1520  struct sockaddr_storage ss;
1521  struct sockaddr_in *v4;
1522  struct sockaddr_in6 *v6;
1523 
1524  if (NULL == addr)
1525  {
1526  /* DNS resolution finished */
1527  if (0 == gp->num_results)
1529  "Failed to use DNS to resolve name of DNS resolver\n");
1531  ac->authority_info.dns_authority.gp_tail,
1532  gp);
1533  GNUNET_free(gp);
1535  return;
1536  }
1537  GNUNET_memcpy(&ss,
1538  addr,
1539  addrlen);
1540  switch (ss.ss_family)
1541  {
1542  case AF_INET:
1543  v4 = (struct sockaddr_in *)&ss;
1544  v4->sin_port = htons(53);
1545  gp->num_results++;
1546  break;
1547 
1548  case AF_INET6:
1549  v6 = (struct sockaddr_in6 *)&ss;
1550  v6->sin6_port = htons(53);
1551  gp->num_results++;
1552  break;
1553 
1554  default:
1556  "Unsupported AF %d\n",
1557  ss.ss_family);
1558  return;
1559  }
1560  if (GNUNET_OK ==
1562  (struct sockaddr *)&ss))
1564 }
1565 
1566 
1573 static void
1575  const struct GNUNET_GNSRECORD_Data *rd)
1576 {
1577  char *cname;
1578  size_t off;
1579 
1580  off = 0;
1581  cname = GNUNET_DNSPARSER_parse_name(rd->data,
1582  rd->data_size,
1583  &off);
1584  if ((NULL == cname) ||
1585  (off != rd->data_size))
1586  {
1587  GNUNET_break_op(0); /* record not well-formed */
1588  GNUNET_free_non_null(cname);
1589  fail_resolution(rh);
1590  return;
1591  }
1593  cname);
1594  GNUNET_free(cname);
1595 }
1596 
1597 
1604 static void
1606  const struct GNUNET_GNSRECORD_Data *rd)
1607 {
1608  struct AuthorityChain *ac;
1609 
1610  /* delegation to another zone */
1611  if (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) !=
1612  rd->data_size)
1613  {
1614  GNUNET_break_op(0);
1615  fail_resolution(rh);
1616  return;
1617  }
1618  /* expand authority chain */
1619  ac = GNUNET_new(struct AuthorityChain);
1620  ac->rh = rh;
1621  ac->gns_authority = GNUNET_YES;
1623  rd->data,
1624  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
1626  /* add AC to tail */
1628  rh->ac_tail,
1629  ac);
1630  /* recurse */
1632  rh);
1633 }
1634 
1635 
1646 static int
1648  unsigned int rd_count,
1649  const struct GNUNET_GNSRECORD_Data *rd)
1650 {
1651  struct AuthorityChain *ac;
1652  const char *tld;
1653  char *ns;
1654 
1655  ns = NULL;
1656  /* expand authority chain */
1657  ac = GNUNET_new(struct AuthorityChain);
1658  ac->rh = rh;
1660 
1661  for (unsigned int i = 0; i < rd_count; i++)
1662  {
1663  char *ip;
1664  char *n;
1665  size_t off;
1666  struct Gns2DnsPending *gp;
1667  struct GNUNET_CRYPTO_EcdsaPublicKey zone;
1668  struct sockaddr_in v4;
1669  struct sockaddr_in6 v6;
1670 
1671  if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1672  continue;
1673  off = 0;
1675  rd[i].data_size,
1676  &off);
1677  ip = GNUNET_DNSPARSER_parse_name(rd[i].data,
1678  rd[i].data_size,
1679  &off);
1680  if ((NULL == n) ||
1681  (NULL == ip) ||
1682  (off != rd[i].data_size))
1683  {
1684  GNUNET_break_op(0);
1687  continue;
1688  }
1689  /* resolve 'ip' to determine the IP(s) of the DNS
1690  resolver to use for lookup of 'ns' */
1691  if (NULL != ns)
1692  {
1693  if (0 != strcasecmp(ns,
1694  n))
1695  {
1696  /* NS values must all be the same for all GNS2DNS records,
1697  anything else leads to insanity */
1698  GNUNET_break_op(0);
1699  GNUNET_free(n);
1700  GNUNET_free(ip);
1701  continue;
1702  }
1703  GNUNET_free(n);
1704  }
1705  else
1706  {
1707  ns = n;
1708  }
1709 
1710  /* check if 'ip' is already an IPv4/IPv6 address */
1711  if ((1 == inet_pton(AF_INET,
1712  ip,
1713  &v4)) ||
1714  (1 == inet_pton(AF_INET6,
1715  ip,
1716  &v6)))
1717  {
1720  ip));
1722  GNUNET_free(ip);
1723  continue;
1724  }
1725  tld = GNS_get_tld(ip);
1726  if (0 != strcmp(tld,
1727  "+"))
1728  {
1729  /* 'ip' is a DNS name */
1730  gp = GNUNET_new(struct Gns2DnsPending);
1731  gp->ac = ac;
1733  ac->authority_info.dns_authority.gp_tail,
1734  gp);
1735  gp->dns_rh = GNUNET_RESOLVER_ip_get(ip,
1736  AF_UNSPEC,
1739  gp);
1740  GNUNET_free(ip);
1741  continue;
1742  }
1743  /* 'ip' should be a GNS name */
1744  gp = GNUNET_new(struct Gns2DnsPending);
1745  gp->ac = ac;
1747  ac->authority_info.dns_authority.gp_tail,
1748  gp);
1749  gp->rh = GNUNET_new(struct GNS_ResolverHandle);
1750  ip = translate_dot_plus(rh,
1751  ip);
1752  tld = GNS_get_tld(ip);
1753  if (GNUNET_OK !=
1755  &zone))
1756  {
1757  GNUNET_break_op(0);
1758  GNUNET_free(ip);
1759  continue;
1760  }
1761  gp->rh->authority_zone = zone;
1763  "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1764  ip,
1765  ns);
1766  gp->rh->name = ip;
1767  gp->rh->name_resolution_pos = strlen(ip) - strlen(tld) - 1;
1768  gp->rh->proc = &handle_gns2dns_result;
1769  gp->rh->proc_cls = gp;
1772  gp->rh->loop_limiter = rh->loop_limiter + 1;
1773  gp->rh->task_id
1775  gp->rh);
1776  } /* end 'for all records' */
1777 
1778  if (NULL == ns)
1779  {
1780  /* not a single GNS2DNS record found */
1781  GNUNET_free(ac);
1782  return GNUNET_SYSERR;
1783  }
1785  strcpy(ac->authority_info.dns_authority.name,
1786  ns);
1787  /* for DNS recursion, the label is the full DNS name,
1788  created from the remainder of the GNS name and the
1789  name in the NS record */
1790  GNUNET_asprintf(&ac->label,
1791  "%.*s%s%s",
1792  (int)rh->name_resolution_pos,
1793  rh->name,
1794  (0 != rh->name_resolution_pos) ? "." : "",
1795  ns);
1796  GNUNET_free(ns);
1798  rh->ac_tail,
1799  ac);
1800  if (strlen(ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1801  {
1803  _("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1804  ac->label);
1805  return GNUNET_SYSERR;
1806  }
1808  return GNUNET_OK;
1809 }
1810 
1811 
1819 static void
1821  unsigned int rd_count,
1822  const struct GNUNET_GNSRECORD_Data *rd)
1823 {
1824  struct GNS_ResolverHandle *rh = cls;
1825  char *cname;
1826  struct VpnContext *vpn_ctx;
1827  const struct GNUNET_TUN_GnsVpnRecord *vpn;
1828  const char *vname;
1829  struct GNUNET_HashCode vhash;
1830  int af;
1831  char scratch[UINT16_MAX];
1832  size_t scratch_off;
1833  size_t scratch_start;
1834  size_t off;
1835  struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1836  unsigned int rd_off;
1837 
1839  "Resolution succeeded for `%s' in zone %s, got %u records\n",
1840  rh->ac_tail->label,
1842  rd_count);
1843  if (0 == rd_count)
1844  {
1846  _("GNS lookup failed (zero records found for `%s')\n"),
1847  rh->name);
1848  fail_resolution(rh);
1849  return;
1850  }
1851 
1852  if (0 == rh->name_resolution_pos)
1853  {
1854  /* top-level match, are we done yet? */
1855  if ((rd_count > 0) &&
1858  {
1859  off = 0;
1860  cname = GNUNET_DNSPARSER_parse_name(rd[0].data,
1861  rd[0].data_size,
1862  &off);
1863  if ((NULL == cname) ||
1864  (off != rd[0].data_size))
1865  {
1866  GNUNET_break_op(0);
1867  GNUNET_free_non_null(cname);
1868  fail_resolution(rh);
1869  return;
1870  }
1872  cname);
1873  GNUNET_free(cname);
1874  return;
1875  }
1876  /* If A/AAAA was requested, but we got a VPN
1877  record, we convert it to A/AAAA using GNUnet VPN */
1878  if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
1880  {
1881  for (unsigned int i = 0; i < rd_count; i++)
1882  {
1883  switch (rd[i].record_type)
1884  {
1886  {
1887  af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET : AF_INET6;
1888  if (sizeof(struct GNUNET_TUN_GnsVpnRecord) >
1889  rd[i].data_size)
1890  {
1891  GNUNET_break_op(0);
1892  fail_resolution(rh);
1893  return;
1894  }
1895  vpn = (const struct GNUNET_TUN_GnsVpnRecord *)rd[i].data;
1896  vname = (const char *)&vpn[1];
1897  if ('\0' != vname[rd[i].data_size - 1 - sizeof(struct GNUNET_TUN_GnsVpnRecord)])
1898  {
1899  GNUNET_break_op(0);
1900  fail_resolution(rh);
1901  return;
1902  }
1904  &vhash);
1906  "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n",
1907  GNUNET_i2s(&vpn->peer),
1908  vname,
1909  (int)af,
1910  (int)ntohs(vpn->proto));
1911  vpn_ctx = GNUNET_new(struct VpnContext);
1912  rh->vpn_ctx = vpn_ctx;
1913  vpn_ctx->rh = rh;
1914  vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size(rd_count,
1915  rd);
1916  if (vpn_ctx->rd_data_size < 0)
1917  {
1918  GNUNET_break_op(0);
1919  GNUNET_free(vpn_ctx);
1920  fail_resolution(rh);
1921  return;
1922  }
1923  vpn_ctx->rd_data = GNUNET_malloc((size_t)vpn_ctx->rd_data_size);
1924  vpn_ctx->rd_count = rd_count;
1925  GNUNET_assert(vpn_ctx->rd_data_size ==
1927  rd,
1928  (size_t)vpn_ctx->rd_data_size,
1929  vpn_ctx->rd_data));
1930  vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer(vpn_handle,
1931  af,
1932  ntohs(vpn->proto),
1933  &vpn->peer,
1934  &vhash,
1937  vpn_ctx);
1938  return;
1939  }
1940 
1942  {
1943  /* delegation to DNS */
1945  "Found GNS2DNS record, delegating to DNS!\n");
1946  if (GNUNET_OK ==
1948  rd_count,
1949  rd))
1950  return;
1951  else
1952  goto fail;
1953  }
1954 
1955  default:
1956  break;
1957  } /* end: switch */
1958  } /* end: for rd */
1959  } /* end: name_resolution_pos */
1960  /* convert relative names in record values to absolute names,
1961  using 'scratch' array for memory allocations */
1962  scratch_off = 0;
1963  rd_off = 0;
1964  for (unsigned int i = 0; i < rd_count; i++)
1965  {
1966  GNUNET_assert(rd_off <= i);
1967  if ((0 != rh->protocol) &&
1968  (0 != rh->service) &&
1970  continue; /* we _only_ care about boxed records */
1971 
1972  GNUNET_assert(rd_off < rd_count);
1973  rd_new[rd_off] = rd[i];
1974  /* Check if the embedded name(s) end in "+", and if so,
1975  replace the "+" with the zone at "ac_tail", changing the name
1976  to a ".ZONEKEY". The name is allocated on the 'scratch' array,
1977  so we can free it afterwards. */
1978  switch (rd[i].record_type)
1979  {
1981  {
1982  char *cname;
1983 
1984  off = 0;
1985  cname = GNUNET_DNSPARSER_parse_name(rd[i].data,
1986  rd[i].data_size,
1987  &off);
1988  if ((NULL == cname) ||
1989  (off != rd[i].data_size))
1990  {
1991  GNUNET_break_op(0); /* record not well-formed */
1992  }
1993  else
1994  {
1995  cname = translate_dot_plus(rh, cname);
1996  GNUNET_break(NULL != cname);
1997  scratch_start = scratch_off;
1998  if (GNUNET_OK !=
2000  sizeof(scratch),
2001  &scratch_off,
2002  cname))
2003  {
2004  GNUNET_break(0);
2005  }
2006  else
2007  {
2008  GNUNET_assert(rd_off < rd_count);
2009  rd_new[rd_off].data = &scratch[scratch_start];
2010  rd_new[rd_off].data_size = scratch_off - scratch_start;
2011  rd_off++;
2012  }
2013  }
2014  GNUNET_free_non_null(cname);
2015  }
2016  break;
2017 
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;
2056 
2058  {
2059  struct GNUNET_DNSPARSER_MxRecord *mx;
2060 
2061  off = 0;
2062  mx = GNUNET_DNSPARSER_parse_mx(rd[i].data,
2063  rd[i].data_size,
2064  &off);
2065  if ((NULL == mx) ||
2066  (off != rd[i].data_size))
2067  {
2068  GNUNET_break_op(0); /* record not well-formed */
2069  }
2070  else
2071  {
2072  mx->mxhost = translate_dot_plus(rh, mx->mxhost);
2073  scratch_start = scratch_off;
2074  if (GNUNET_OK !=
2076  sizeof(scratch),
2077  &scratch_off,
2078  mx))
2079  {
2080  GNUNET_break(0);
2081  }
2082  else
2083  {
2084  GNUNET_assert(rd_off < rd_count);
2085  rd_new[rd_off].data = &scratch[scratch_start];
2086  rd_new[rd_off].data_size = scratch_off - scratch_start;
2087  rd_off++;
2088  }
2089  }
2090  if (NULL != mx)
2092  }
2093  break;
2094 
2096  {
2097  struct GNUNET_DNSPARSER_SrvRecord *srv;
2098 
2099  off = 0;
2100  srv = GNUNET_DNSPARSER_parse_srv(rd[i].data,
2101  rd[i].data_size,
2102  &off);
2103  if ((NULL == srv) ||
2104  (off != rd[i].data_size))
2105  {
2106  GNUNET_break_op(0); /* record not well-formed */
2107  }
2108  else
2109  {
2110  srv->target = translate_dot_plus(rh, srv->target);
2111  scratch_start = scratch_off;
2112  if (GNUNET_OK !=
2114  sizeof(scratch),
2115  &scratch_off,
2116  srv))
2117  {
2118  GNUNET_break(0);
2119  }
2120  else
2121  {
2122  GNUNET_assert(rd_off < rd_count);
2123  rd_new[rd_off].data = &scratch[scratch_start];
2124  rd_new[rd_off].data_size = scratch_off - scratch_start;
2125  rd_off++;
2126  }
2127  }
2128  if (NULL != srv)
2130  }
2131  break;
2132 
2134  {
2135  const char *nick;
2136 
2137  nick = rd[i].data;
2138  if ((rd[i].data_size > 0) &&
2139  (nick[rd[i].data_size - 1] != '\0'))
2140  {
2141  GNUNET_break_op(0);
2142  break;
2143  }
2144  break;
2145  }
2146 
2148  {
2149  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
2150 
2151  if (rd[i].data_size != sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))
2152  {
2153  GNUNET_break_op(0);
2154  break;
2155  }
2156  GNUNET_memcpy(&pub,
2157  rd[i].data,
2158  rd[i].data_size);
2159  rd_off++;
2161  {
2162  /* try to resolve "@" */
2163  struct AuthorityChain *ac;
2164 
2165  ac = GNUNET_new(struct AuthorityChain);
2166  ac->rh = rh;
2167  ac->gns_authority = GNUNET_YES;
2171  rh->ac_tail,
2172  ac);
2174  rh);
2175  return;
2176  }
2177  }
2178  break;
2179 
2181  {
2182  /* delegation to DNS */
2184  {
2185  rd_off++;
2186  break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2187  }
2189  "Found GNS2DNS record, delegating to DNS!\n");
2190  if (GNUNET_OK ==
2192  rd_count,
2193  rd))
2194  return;
2195  else
2196  goto fail;
2197  }
2198 
2200  {
2201  /* unbox SRV/TLSA records if a specific one was requested */
2202  if ((0 != rh->protocol) &&
2203  (0 != rh->service) &&
2204  (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2205  {
2206  const struct GNUNET_GNSRECORD_BoxRecord *box;
2207 
2208  box = rd[i].data;
2209  if ((ntohs(box->protocol) == rh->protocol) &&
2210  (ntohs(box->service) == rh->service))
2211  {
2212  /* Box matches, unbox! */
2213  GNUNET_assert(rd_off < rd_count);
2214  rd_new[rd_off].record_type = ntohl(box->record_type);
2215  rd_new[rd_off].data_size -= sizeof(struct GNUNET_GNSRECORD_BoxRecord);
2216  rd_new[rd_off].data = &box[1];
2217  rd_off++;
2218  }
2219  }
2220  else
2221  {
2222  /* no specific protocol/service specified, preserve all BOX
2223  records (for modern, GNS-enabled applications) */
2224  rd_off++;
2225  }
2226  break;
2227  }
2228 
2229  default:
2230  rd_off++;
2231  break;
2232  } /* end: switch */
2233  } /* end: for rd_count */
2234 
2235  /* yes, we are done, return result */
2237  "Returning GNS response for `%s' with %u answers\n",
2238  rh->ac_tail->label,
2239  rd_off);
2240  rh->proc(rh->proc_cls,
2241  rd_off,
2242  rd_new);
2244  rh);
2245  return;
2246  }
2247 
2248  switch (rd[0].record_type)
2249  {
2251  GNUNET_break_op(1 == rd_count); /* CNAME should be unique */
2253  &rd[0]);
2254  return;
2255 
2257  GNUNET_break_op(1 == rd_count); /* PKEY should be unique */
2259  &rd[0]);
2260  return;
2261 
2262  default:
2263  if (GNUNET_OK ==
2265  rd_count,
2266  rd))
2267  return;
2268  break;
2269  }
2270 fail:
2272  _("GNS lookup recursion failed (no delegation record found)\n"));
2273  fail_resolution(rh);
2274 }
2275 
2276 
2285 static void
2287  int32_t success,
2288  const char *emsg)
2289 {
2290  struct CacheOps *co = cls;
2291 
2292  co->namecache_qe_cache = NULL;
2293  if (GNUNET_OK != success)
2295  _("Failed to cache GNS resolution: %s\n"),
2296  emsg);
2298  co_tail,
2299  co);
2300  GNUNET_free(co);
2301 }
2302 
2303 
2321 static void
2323  struct GNUNET_TIME_Absolute exp,
2324  const struct GNUNET_HashCode *key,
2325  const struct GNUNET_PeerIdentity *get_path,
2326  unsigned int get_path_length,
2327  const struct GNUNET_PeerIdentity *put_path,
2328  unsigned int put_path_length,
2329  enum GNUNET_BLOCK_Type type,
2330  size_t size,
2331  const void *data)
2332 {
2333  struct GNS_ResolverHandle *rh = cls;
2334  struct AuthorityChain *ac = rh->ac_tail;
2335  const struct GNUNET_GNSRECORD_Block *block;
2336  struct CacheOps *co;
2337 
2338  (void)exp;
2339  (void)key;
2340  (void)get_path;
2341  (void)get_path_length;
2342  (void)put_path;
2343  (void)put_path_length;
2344  (void)type;
2346  rh->get_handle = NULL;
2348  rh->dht_heap_node = NULL;
2350  "Handling response from the DHT\n");
2351  if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2352  {
2353  /* how did this pass DHT block validation!? */
2354  GNUNET_break(0);
2355  fail_resolution(rh);
2356  return;
2357  }
2358  block = data;
2359  if (size !=
2360  ntohl(block->purpose.size) +
2361  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) +
2362  sizeof(struct GNUNET_CRYPTO_EcdsaSignature))
2363  {
2364  /* how did this pass DHT block validation!? */
2365  GNUNET_break(0);
2366  fail_resolution(rh);
2367  return;
2368  }
2370  "Decrypting DHT block of size %u for `%s', expires %s\n",
2371  ntohl(block->purpose.size),
2372  rh->name,
2374  if (GNUNET_OK !=
2377  ac->label,
2379  rh))
2380  {
2381  GNUNET_break_op(0); /* block was ill-formed */
2382  fail_resolution(rh);
2383  return;
2384  }
2386  {
2388  "Received expired block from the DHT, will not cache it.\n");
2389  return;
2390  }
2391  if (GNUNET_YES == disable_cache)
2392  return;
2393  /* Cache well-formed blocks */
2395  "Caching response from the DHT in namecache\n");
2396  co = GNUNET_new(struct CacheOps);
2397  co->namecache_qe_cache = GNUNET_NAMECACHE_block_cache(namecache_handle,
2398  block,
2400  co);
2402  co_tail,
2403  co);
2404 }
2405 
2406 
2413 static void
2415  const struct GNUNET_HashCode *query)
2416 {
2417  struct GNS_ResolverHandle *rx;
2418 
2419  GNUNET_assert(NULL == rh->get_handle);
2420  rh->get_handle = GNUNET_DHT_get_start(dht_handle,
2422  query,
2425  NULL, 0,
2426  &handle_dht_response, rh);
2427  rh->dht_heap_node = GNUNET_CONTAINER_heap_insert(dht_lookup_heap,
2428  rh,
2429  GNUNET_TIME_absolute_get().abs_value_us);
2431  {
2432  /* fail longest-standing DHT request */
2433  rx = GNUNET_CONTAINER_heap_remove_root(dht_lookup_heap);
2434  rx->dht_heap_node = NULL;
2435  GNUNET_assert(NULL != rx);
2436  fail_resolution(rx);
2437  }
2438 }
2439 
2440 
2449 static void
2451  unsigned int rd_count,
2452  const struct GNUNET_GNSRECORD_Data *rd)
2453 {
2454  struct GNS_ResolverHandle *rh = cls;
2455 
2456  if (0 == rd_count)
2458  _("GNS namecache returned empty result for `%s'\n"),
2459  rh->name);
2461  rd_count,
2462  rd);
2463 }
2464 
2465 
2472 static void
2474  const struct GNUNET_GNSRECORD_Block *block)
2475 {
2476  struct GNS_ResolverHandle *rh = cls;
2477  struct AuthorityChain *ac = rh->ac_tail;
2478  const char *label = ac->label;
2479  const struct GNUNET_CRYPTO_EcdsaPublicKey *auth = &ac->authority_info.gns_authority;
2480  struct GNUNET_HashCode query;
2481 
2482  GNUNET_assert(NULL != rh->namecache_qe);
2483  rh->namecache_qe = NULL;
2484  if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2485  ((GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2486  (ac != rh->ac_head))) &&
2487  ((NULL == block) ||
2489  {
2490  /* namecache knows nothing; try DHT lookup */
2492  label,
2493  &query);
2495  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2496  ac->label,
2498  GNUNET_h2s(&query));
2499  start_dht_request(rh, &query);
2500  return;
2501  }
2502 
2503  if ((NULL == block) ||
2505  {
2506  /* DHT not permitted and no local result, fail */
2508  "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2509  ac->label,
2511  fail_resolution(rh);
2512  return;
2513  }
2515  "Received result from namecache for label `%s'\n",
2516  ac->label);
2517 
2518  if (GNUNET_OK !=
2520  auth,
2521  label,
2523  rh))
2524  {
2525  GNUNET_break_op(0); /* block was ill-formed */
2526  /* try DHT instead */
2528  label,
2529  &query);
2531  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2532  ac->label,
2534  GNUNET_h2s(&query));
2535  start_dht_request(rh, &query);
2536  return;
2537  }
2538 }
2539 
2540 
2546 static void
2548 {
2549  struct AuthorityChain *ac = rh->ac_tail;
2550  struct GNUNET_HashCode query;
2551 
2553  "Starting GNS resolution for `%s' in zone %s\n",
2554  ac->label,
2557  ac->label,
2558  &query);
2559  if (GNUNET_YES != disable_cache)
2560  {
2561  rh->namecache_qe
2562  = GNUNET_NAMECACHE_lookup_block(namecache_handle,
2563  &query,
2565  rh);
2566  GNUNET_assert(NULL != rh->namecache_qe);
2567  }
2568  else
2569  {
2570  start_dht_request(rh,
2571  &query);
2572  }
2573 }
2574 
2575 
2582 static void
2584  int is_valid)
2585 {
2586  struct GNS_ResolverHandle *rh = cls;
2587  struct AuthorityChain *ac = rh->ac_tail;
2588 
2589  rh->rev_check = NULL;
2590  if (GNUNET_YES != is_valid)
2591  {
2593  _("Zone %s was revoked, resolution fails\n"),
2595  fail_resolution(rh);
2596  return;
2597  }
2599 }
2600 
2601 
2607 static void
2609 {
2610  struct AuthorityChain *ac = rh->ac_tail;
2611 
2613  "Starting revocation check for zone %s\n",
2618  rh);
2619  GNUNET_assert(NULL != rh->rev_check);
2620 }
2621 
2622 
2628 static void
2630 {
2631  struct GNS_ResolverHandle *rh = cls;
2632 
2633  rh->task_id = NULL;
2634  if (MAX_RECURSION < rh->loop_limiter++)
2635  {
2637  "Encountered unbounded recursion resolving `%s'\n",
2638  rh->name);
2639  fail_resolution(rh);
2640  return;
2641  }
2642  if (GNUNET_YES == rh->ac_tail->gns_authority)
2644  else
2646 }
2647 
2648 
2655 static void
2657 {
2658  struct GNS_ResolverHandle *rh = cls;
2659  struct AuthorityChain *ac;
2660  struct in_addr v4;
2661  struct in6_addr v6;
2662 
2663  rh->task_id = NULL;
2664  if (1 == inet_pton(AF_INET,
2665  rh->name,
2666  &v4))
2667  {
2668  /* name is IPv4 address, pretend it's an A record */
2669  struct GNUNET_GNSRECORD_Data rd;
2670 
2671  rd.data = &v4;
2672  rd.data_size = sizeof(v4);
2673  rd.expiration_time = UINT64_MAX;
2675  rd.flags = 0;
2676  rh->proc(rh->proc_cls,
2677  1,
2678  &rd);
2679  GNUNET_assert(NULL == rh->task_id);
2681  rh);
2682  return;
2683  }
2684  if (1 == inet_pton(AF_INET6,
2685  rh->name,
2686  &v6))
2687  {
2688  /* name is IPv6 address, pretend it's an AAAA record */
2689  struct GNUNET_GNSRECORD_Data rd;
2690 
2691  rd.data = &v6;
2692  rd.data_size = sizeof(v6);
2693  rd.expiration_time = UINT64_MAX;
2695  rd.flags = 0;
2696  rh->proc(rh->proc_cls,
2697  1,
2698  &rd);
2699  GNUNET_assert(NULL == rh->task_id);
2701  rh);
2702  return;
2703  }
2704 
2705  ac = GNUNET_new(struct AuthorityChain);
2706  ac->rh = rh;
2708  if (NULL == ac->label)
2709  /* name was just the "TLD", so we default to label
2710  #GNUNET_GNS_EMPTY_LABEL_AT */
2712  ac->gns_authority = GNUNET_YES;
2715  rh->ac_tail,
2716  ac);
2718  rh);
2719 }
2720 
2721 
2734 struct GNS_ResolverHandle *
2736  uint32_t record_type,
2737  const char *name,
2740  void *proc_cls)
2741 {
2742  struct GNS_ResolverHandle *rh;
2743 
2745  "Starting lookup for `%s'\n",
2746  name);
2747  rh = GNUNET_new(struct GNS_ResolverHandle);
2748  GNUNET_CONTAINER_DLL_insert(rlh_head,
2749  rlh_tail,
2750  rh);
2751  rh->authority_zone = *zone;
2752  rh->proc = proc;
2753  rh->proc_cls = proc_cls;
2754  rh->options = options;
2755  rh->record_type = record_type;
2756  rh->name = GNUNET_strdup(name);
2757  rh->name_resolution_pos = strlen(name);
2759  rh);
2760  return rh;
2761 }
2762 
2763 
2769 void
2771 {
2772  struct DnsResult *dr;
2773  struct AuthorityChain *ac;
2774  struct VpnContext *vpn_ctx;
2775 
2776  GNUNET_CONTAINER_DLL_remove(rlh_head,
2777  rlh_tail,
2778  rh);
2779  if (NULL != rh->dns_request)
2780  {
2782  rh->dns_request = NULL;
2783  }
2784  while (NULL != (ac = rh->ac_head))
2785  {
2787  rh->ac_tail,
2788  ac);
2789  if (GNUNET_NO == ac->gns_authority)
2790  {
2791  struct Gns2DnsPending *gp;
2792 
2793  while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2794  {
2796  ac->authority_info.dns_authority.gp_tail,
2797  gp);
2798  if (NULL != gp->rh)
2799  {
2800  /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2801  using GNS_resolver_lookup_cancel here, we need to
2802  add it first... */
2803  GNUNET_CONTAINER_DLL_insert(rlh_head,
2804  rlh_tail,
2805  gp->rh);
2806  GNUNET_assert(NULL == gp->rh->task_id);
2808  gp->rh);
2809  gp->rh = NULL;
2810  }
2811  if (NULL != gp->dns_rh)
2812  {
2814  gp->dns_rh = NULL;
2815  }
2816  GNUNET_free(gp);
2817  }
2819  }
2820  GNUNET_free(ac->label);
2821  GNUNET_free(ac);
2822  }
2823  if (NULL != rh->task_id)
2824  {
2826  rh->task_id = NULL;
2827  }
2828  if (NULL != rh->get_handle)
2829  {
2831  rh->get_handle = NULL;
2832  }
2833  if (NULL != rh->dht_heap_node)
2834  {
2836  rh->dht_heap_node = NULL;
2837  }
2838  if (NULL != (vpn_ctx = rh->vpn_ctx))
2839  {
2841  GNUNET_free(vpn_ctx->rd_data);
2842  GNUNET_free(vpn_ctx);
2843  }
2844  if (NULL != rh->namecache_qe)
2845  {
2847  rh->namecache_qe = NULL;
2848  }
2849  if (NULL != rh->rev_check)
2850  {
2852  rh->rev_check = NULL;
2853  }
2854  if (NULL != rh->std_resolve)
2855  {
2857  "Canceling standard DNS resolution\n");
2859  rh->std_resolve = NULL;
2860  }
2861  while (NULL != (dr = rh->dns_result_head))
2862  {
2864  rh->dns_result_tail,
2865  dr);
2866  GNUNET_free(dr);
2867  }
2869  GNUNET_free(rh->name);
2870  GNUNET_free(rh);
2871 }
2872 
2873 
2874 /* ***************** Resolver initialization ********************* */
2875 
2876 
2885 void
2887  struct GNUNET_DHT_Handle *dht,
2888  const struct GNUNET_CONFIGURATION_Handle *c,
2889  unsigned long long max_bg_queries)
2890 {
2891  cfg = c;
2892  namecache_handle = nc;
2893  dht_handle = dht;
2894  dht_lookup_heap =
2896  max_allowed_background_queries = max_bg_queries;
2898  "namecache",
2899  "DISABLE");
2900  if (GNUNET_YES == disable_cache)
2902  "Namecache disabled\n");
2903  vpn_handle = GNUNET_VPN_connect(cfg);
2904 }
2905 
2906 
2910 void
2912 {
2913  struct GNS_ResolverHandle *rh;
2914  struct CacheOps *co;
2915 
2916  /* abort active resolutions */
2917  while (NULL != (rh = rlh_head))
2918  {
2919  rh->proc(rh->proc_cls,
2920  0,
2921  NULL);
2923  }
2924  while (NULL != (co = co_head))
2925  {
2927  co_tail,
2928  co);
2930  GNUNET_free(co);
2931  }
2932  GNUNET_CONTAINER_heap_destroy(dht_lookup_heap);
2933  dht_lookup_heap = NULL;
2934  GNUNET_VPN_disconnect(vpn_handle);
2935  vpn_handle = NULL;
2936  dht_handle = NULL;
2937  namecache_handle = NULL;
2938 }
2939 
2940 
2941 /* end of gnunet-service-gns_resolver.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void GNUNET_DNSPARSER_free_soa(struct GNUNET_DNSPARSER_SoaRecord *soa)
Free SOA information record.
Definition: dnsparser.c:108
struct GNUNET_DNSPARSER_Record * answers
Array of all answers in the packet, must contain "num_answers" entries.
static struct GNUNET_VPN_Handle * vpn_handle
Our handle to the vpn service.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
Information from SOA records (RFC 1035).
For the rightmost label, only look in the cache (it is our local namestore), for the others...
static struct GNUNET_NAMECACHE_Handle * namecache_handle
Our handle to the namecache service.
struct GNUNET_TIME_AbsoluteNBO expiration_time
Expiration time of the block.
Payload of GNS VPN record.
unsigned int num_results
How many results did we get?
GNUNET_NETWORK_STRUCT_END ssize_t GNUNET_GNSRECORD_records_get_size(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Calculate how many bytes we will need to serialize the given records.
#define memrchr(s, c, n)
Definition: compat.h: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:671
static void vpn_allocation_cb(void *cls, int af, const void *address)
Callback invoked from the VPN service once a redirection is available.
Record type used to box up SRV and TLSA records.
char * GNUNET_DNSPARSER_parse_name(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse name inside of a DNS query or record.
Definition: dnsparser.c:334
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:139
GNUNET_BLOCK_Type
Blocks in the datastore and the datacache must have a unique type.
static void recursive_gns_resolution_revocation(struct GNS_ResolverHandle *rh)
Perform revocation check on tail of our authority chain.
#define GNUNET_DNSPARSER_TYPE_CNAME
#define DHT_GNS_REPLICATION_LEVEL
DHT replication level.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe_cache
Pending Namestore caching task.
struct GNUNET_DHT_GetHandle * get_handle
Handle for DHT lookups.
static void handle_namecache_block_response(void *cls, const struct GNUNET_GNSRECORD_Block *block)
Process a record that was stored in the namecache.
char * mxhost
Name of the mail server.
struct GNUNET_DNSPARSER_SrvRecord * srv
SRV data for SRV records.
ssize_t GNUNET_GNSRECORD_records_serialize(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, size_t dest_size, char *dest)
Serialize the given records to the given destination buffer.
static void handle_dns_result(void *cls, const struct sockaddr *addr, socklen_t addrlen)
We had to do a DNS lookup.
static void GNS_resolver_lookup_cancel_(void *cls)
Wrapper around GNS_resolver_lookup_cancel() as a task.
const char * GNS_get_tld(const char *name)
Obtain the TLD of the given name.
struct GNS_ResolverHandle * next
DLL.
static void timeout_resolution(void *cls)
Function called when a resolution times out.
uint64_t expiration_time
Expiration time for the DNS record, 0 if we didn&#39;t get anything useful (i.e.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
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:687
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:1256
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:588
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:1117
uint16_t id
DNS ID (to match replies to requests).
struct AuthorityChain * prev
This is a DLL.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GNS_LocalOptions
Options for the GNS lookup.
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:853
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:78
struct GNUNET_DNSPARSER_SoaRecord * GNUNET_DNSPARSER_parse_soa(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS SOA record.
Definition: dnsparser.c:391
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get(const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
Convert a string to one or more IP addresses.
Definition: resolver_api.c:933
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:75
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:198
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:181
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:1237
#define GNUNET_DNSPARSER_MAX_NAME_LENGTH
Maximum length of a name in DNS.
#define GNUNET_DNSPARSER_TYPE_SOA
int service
For SRV and TLSA records, the number of the service specified in the name.
char * name
Name of the record that the query is for (0-terminated).
char * hostname
For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
const void * data
Binary value stored in the DNS record.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
struct GNUNET_DNSPARSER_SoaRecord * soa
SOA data for SOA records.
unsigned int num_additional_records
Number of additional records in the packet, should be 0 for queries.
static char * resolver_lookup_get_next_label(struct GNS_ResolverHandle *rh)
Get the next, rightmost label from the name that we are trying to resolve, and update the resolution ...
struct GNUNET_RESOLVER_RequestHandle * std_resolve
Handle for standard DNS resolution, NULL if none is active.
struct GNUNET_DNSPARSER_Packet * GNUNET_DNSPARSER_parse(const char *udp_payload, size_t udp_payload_length)
Parse a UDP payload of a DNS packet in to a nice struct for further processing and manipulation...
Definition: dnsparser.c:656
#define GNUNET_GNSRECORD_TYPE_PKEY
Record type for GNS zone transfer ("PKEY").
struct AuthorityChain * ac_tail
DLL to store the authority chain.
static int recursive_gns2dns_resolution(struct GNS_ResolverHandle *rh, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
We found one or more GNS2DNS records, perform recursive resolution on it.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition: dnsstub.c:561
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:1264
#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:477
void GNUNET_VPN_disconnect(struct GNUNET_VPN_Handle *vh)
Disconnect from the VPN service.
Definition: vpn_api.c:529
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:812
#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:1076
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:121
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:1150
static int res
struct GNUNET_DNSPARSER_MxRecord * GNUNET_DNSPARSER_parse_mx(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS MX record.
Definition: dnsparser.c:436
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
void GNUNET_VPN_cancel_request(struct GNUNET_VPN_RedirectionRequest *rr)
Cancel redirection request with the service.
Definition: vpn_api.c:370
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:501
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:405
#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:76
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:66
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:1000
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:75
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:78
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:507
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:83
Closure for vpn_allocation_cb.
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition: dnsstub.c:537
#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:1062
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:93
struct DnsResult * next
Kept in DLL.
static void handle_revocation_result(void *cls, int is_valid)
Function called with the result from a revocation check.
#define GNUNET_log(kind,...)
static struct GNS_ResolverHandle * rlh_head
Head of resolver lookup list.
Entry in list of pending tasks.
Definition: scheduler.c:131
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:77
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:888
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:741
ssize_t rd_data_size
Number of bytes in rd_data.
UDP socket we are using for sending DNS requests to the Internet.
Definition: dnsstub.c:44
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
static void recursive_dns_resolution(struct GNS_ResolverHandle *rh)
Perform recursive DNS resolution.
char * leho
Legacy Hostname to use if we encountered GNS2DNS record and thus can deduct the LEHO from that transi...
#define GNUNET_DNSPARSER_TYPE_SRV
uint32_t data
The data value.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
struct AuthorityChain * next
This is a DLL.
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:154
#define GNUNET_DNSPARSER_TYPE_A
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
int GNUNET_DNSSTUB_add_dns_sa(struct GNUNET_DNSSTUB_Context *ctx, const struct sockaddr *sa)
Add nameserver for use by the DNSSTUB.
Definition: dnsstub.c:640
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:956