GNUnet  0.10.x
gnunet-zoneimport.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2018 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 */
25 #include "platform.h"
26 #include <gnunet_util_lib.h>
27 #include <gnunet_dnsstub_lib.h>
28 #include <gnunet_dnsparser_lib.h>
29 #include <gnunet_gnsrecord_lib.h>
33 
34 
38 #define THRESH 100
39 
44 #define TIME_THRESH 10
45 
49 #define MAX_RETRIES 5
50 
54 #define MAX_SERIES 10
55 
59 #define SERIES_DELAY \
60  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, 10)
61 
66 
71 #define NS_BATCH_SIZE 1024
72 
79 struct Zone
80 {
81 
85  struct Zone *next;
86 
90  struct Zone *prev;
91 
95  char *domain;
96 
101 };
102 
103 
107 struct Record
108 {
112  struct Record *next;
113 
117  struct Record *prev;
118 
123 };
124 
125 
131 struct Request
132 {
137 
141  struct Request *next;
142 
146  struct Request *prev;
147 
152  struct Record *rec_head;
153 
158  struct Record *rec_tail;
159 
163  struct GNUNET_DNSSTUB_RequestSocket *rs;
164 
170  char *hostname;
171 
176 
180  const struct Zone *zone;
181 
187  struct GNUNET_TIME_Absolute expires;
188 
195  struct GNUNET_TIME_Absolute op_start_time;
196 
201  unsigned int issue_num;
202 
206  uint16_t id;
207 };
208 
209 
216 static unsigned int map_size = 1024;
217 
221 static struct GNUNET_IDENTITY_Handle *id;
222 
227 
232 
237 
241 static unsigned int pending;
242 
246 static unsigned int pending_rs;
247 
251 static unsigned int lookups;
252 
256 static unsigned int cached;
257 
261 static unsigned int rejects;
262 
266 static unsigned int failures;
267 
271 static unsigned int records;
272 
276 static unsigned int record_sets;
277 
283 
287 static struct Request *req_head;
288 
292 static struct Request *req_tail;
293 
297 static struct GNUNET_SCHEDULER_Task *t;
298 
305 
310 
314 static struct Zone *zone_head;
315 
319 static struct Zone *zone_tail;
320 
325 static uint64_t ns_iterator_trigger_next;
326 
330 static uint64_t total_dns_latency_cnt;
331 
336 
340 static uint64_t total_reg_proc_dns;
341 
345 static uint64_t total_reg_proc_dns_ns;
346 
351 
356 
361 
362 
369 typedef void (*RecordProcessor) (void *cls,
370  const struct GNUNET_DNSPARSER_Record *rec);
371 
372 
381 static void
384  void *rp_cls)
385 {
386  for (unsigned int i = 0; i < p->num_answers; i++)
387  {
388  struct GNUNET_DNSPARSER_Record *rs = &p->answers[i];
389 
390  rp (rp_cls, rs);
391  }
392  for (unsigned int i = 0; i < p->num_authority_records; i++)
393  {
394  struct GNUNET_DNSPARSER_Record *rs = &p->authority_records[i];
395 
396  rp (rp_cls, rs);
397  }
398  for (unsigned int i = 0; i < p->num_additional_records; i++)
399  {
400  struct GNUNET_DNSPARSER_Record *rs = &p->additional_records[i];
401 
402  rp (rp_cls, rs);
403  }
404 }
405 
406 
414 static const char *
415 get_label (struct Request *req)
416 {
417  static char label[64];
418  const char *dot;
419 
420  dot = strchr (req->hostname, (unsigned char) '.');
421  if (NULL == dot)
422  {
423  GNUNET_break (0);
424  return NULL;
425  }
426  if (((size_t) (dot - req->hostname)) >= sizeof (label))
427  {
428  GNUNET_break (0);
429  return NULL;
430  }
431  GNUNET_memcpy (label, req->hostname, dot - req->hostname);
432  label[dot - req->hostname] = '\0';
433  return label;
434 }
435 
436 
445 static void *
446 build_dns_query (struct Request *req, size_t *raw_size)
447 {
448  static char raw[512];
449  char *rawp;
450  struct GNUNET_DNSPARSER_Packet p;
451  struct GNUNET_DNSPARSER_Query q;
452  int ret;
453 
454  q.name = (char *) req->hostname;
457 
458  memset (&p, 0, sizeof (p));
459  p.num_queries = 1;
460  p.queries = &q;
461  p.id = req->id;
462  ret = GNUNET_DNSPARSER_pack (&p, UINT16_MAX, &rawp, raw_size);
463  if (GNUNET_OK != ret)
464  {
465  if (GNUNET_NO == ret)
466  GNUNET_free (rawp);
468  "Failed to pack query for hostname `%s'\n",
469  req->hostname);
470  rejects++;
471  return NULL;
472  }
473  if (*raw_size > sizeof (raw))
474  {
476  "Failed to pack query for hostname `%s'\n",
477  req->hostname);
478  rejects++;
479  GNUNET_break (0);
480  GNUNET_free (rawp);
481  return NULL;
482  }
483  GNUNET_memcpy (raw, rawp, *raw_size);
484  GNUNET_free (rawp);
485  return raw;
486 }
487 
488 
494 static void
495 free_records (struct Request *req)
496 {
497  struct Record *rec;
498 
499  /* Free records */
500  while (NULL != (rec = req->rec_head))
501  {
503  GNUNET_free (rec);
504  }
505 }
506 
507 
513 static void
514 free_request (struct Request *req)
515 {
516  free_records (req);
517  GNUNET_free (req);
518 }
519 
520 
526 static void
527 process_queue (void *cls);
528 
529 
535 static void
536 insert_sorted (struct Request *req)
537 {
538  req->hn =
539  GNUNET_CONTAINER_heap_insert (req_heap, req, req->expires.abs_value_us);
540  if (req == GNUNET_CONTAINER_heap_peek (req_heap))
541  {
542  if (NULL != t)
545  t = GNUNET_SCHEDULER_add_at (req->expires, &process_queue, NULL);
546  }
547 }
548 
549 
559 static void
560 add_record (struct Request *req,
561  uint32_t type,
562  struct GNUNET_TIME_Absolute expiration_time,
563  const void *data,
564  size_t data_len)
565 {
566  struct Record *rec;
567 
568  rec = GNUNET_malloc (sizeof (struct Record) + data_len);
569  rec->grd.data = &rec[1];
570  rec->grd.expiration_time = expiration_time.abs_value_us;
571  rec->grd.data_size = data_len;
572  rec->grd.record_type = type;
574  GNUNET_memcpy (&rec[1], data, data_len);
576 }
577 
578 
583 {
587  struct Request *req;
588 
592  const char *ns;
593 
597  int found;
598 };
599 
600 
607 static void
608 check_for_glue (void *cls, const struct GNUNET_DNSPARSER_Record *rec)
609 {
610  struct GlueClosure *gc = cls;
611  char dst[65536];
612  size_t dst_len;
613  size_t off;
614  char ip[INET6_ADDRSTRLEN + 1];
615  socklen_t ip_size = (socklen_t) sizeof (ip);
616  struct GNUNET_TIME_Absolute expiration_time;
617  struct GNUNET_TIME_Relative left;
618 
619  if (0 != strcasecmp (rec->name, gc->ns))
620  return;
621  expiration_time = rec->expiration_time;
622  left = GNUNET_TIME_absolute_get_remaining (expiration_time);
623  if (0 == left.rel_value_us)
624  return; /* ignore expired glue records */
625  /* if expiration window is too short, bump it to configured minimum */
627  expiration_time =
629  dst_len = sizeof (dst);
630  off = 0;
631  switch (rec->type)
632  {
634  if (sizeof (struct in_addr) != rec->data.raw.data_len)
635  {
636  GNUNET_break (0);
637  return;
638  }
639  if (NULL == inet_ntop (AF_INET, rec->data.raw.data, ip, ip_size))
640  {
641  GNUNET_break (0);
642  return;
643  }
645  dst_len,
646  &off,
647  gc->req->hostname)) &&
648  (GNUNET_OK ==
649  GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &off, ip)))
650  {
651  add_record (gc->req,
653  expiration_time,
654  dst,
655  off);
656  gc->found = GNUNET_YES;
657  }
658  break;
660  if (sizeof (struct in6_addr) != rec->data.raw.data_len)
661  {
662  GNUNET_break (0);
663  return;
664  }
665  if (NULL == inet_ntop (AF_INET6, rec->data.raw.data, ip, ip_size))
666  {
667  GNUNET_break (0);
668  return;
669  }
671  dst_len,
672  &off,
673  gc->req->hostname)) &&
674  (GNUNET_OK ==
675  GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &off, ip)))
676  {
677  add_record (gc->req,
679  expiration_time,
680  dst,
681  off);
682  gc->found = GNUNET_YES;
683  }
684  break;
687  dst_len,
688  &off,
689  gc->req->hostname)) &&
691  dst_len,
692  &off,
693  rec->data.hostname)))
694  {
695  add_record (gc->req,
697  expiration_time,
698  dst,
699  off);
700  gc->found = GNUNET_YES;
701  }
702  break;
703  default:
704  /* useless, do nothing */
705  break;
706  }
707 }
708 
709 
714 {
720 
724  struct Request *req;
725 };
726 
727 
734 static void
735 process_record (void *cls, const struct GNUNET_DNSPARSER_Record *rec)
736 {
737  struct ProcessRecordContext *prc = cls;
738  struct Request *req = prc->req;
739  char dst[65536];
740  size_t dst_len;
741  size_t off;
742  struct GNUNET_TIME_Absolute expiration_time;
743  struct GNUNET_TIME_Relative left;
744 
745  dst_len = sizeof (dst);
746  off = 0;
747  records++;
748  if (0 != strcasecmp (rec->name, req->hostname))
749  {
750  GNUNET_log (
752  "DNS returned record from zone `%s' of type %u while resolving `%s'\n",
753  rec->name,
754  (unsigned int) rec->type,
755  req->hostname);
756  return; /* does not match hostname, might be glue, but
757  not useful for this pass! */
758  }
759  expiration_time = rec->expiration_time;
760  left = GNUNET_TIME_absolute_get_remaining (expiration_time);
761  if (0 == left.rel_value_us)
762  {
764  "DNS returned expired record for `%s'\n",
765  req->hostname);
767  "# expired records obtained from DNS",
768  1,
769  GNUNET_NO);
770  return; /* record expired */
771  }
772 
774  "DNS returned record that expires at %s for `%s'\n",
775  GNUNET_STRINGS_absolute_time_to_string (expiration_time),
776  req->hostname);
777  /* if expiration window is too short, bump it to configured minimum */
779  expiration_time =
781  switch (rec->type)
782  {
784  struct GlueClosure gc;
785 
786  /* check for glue */
787  gc.req = req;
788  gc.ns = rec->data.hostname;
789  gc.found = GNUNET_NO;
790  for_all_records (prc->p, &check_for_glue, &gc);
791  if ((GNUNET_NO == gc.found) &&
793  dst_len,
794  &off,
795  req->hostname)) &&
797  dst_len,
798  &off,
799  rec->data.hostname)))
800  {
801  /* FIXME: actually check if this is out-of-bailiwick,
802  and if not request explicit resolution... */
804  "Converted OOB (`%s') NS record for `%s'\n",
805  rec->data.hostname,
806  rec->name);
807  add_record (req,
809  expiration_time,
810  dst,
811  off);
812  }
813  else
814  {
816  "Converted NS record for `%s' using glue\n",
817  rec->name);
818  }
819  break;
820  }
823  dst_len,
824  &off,
825  rec->data.hostname))
826  {
828  "Converting CNAME (`%s') record for `%s'\n",
829  rec->data.hostname,
830  rec->name);
831  add_record (req, rec->type, expiration_time, dst, off);
832  }
833  break;
835  /* No support for DNAME in GNS yet! FIXME: support later! */
837  "FIXME: not supported: %s DNAME %s\n",
838  rec->name,
839  rec->data.hostname);
840  break;
842  if (GNUNET_OK ==
843  GNUNET_DNSPARSER_builder_add_mx (dst, dst_len, &off, rec->data.mx))
844  {
846  "Converting MX (`%s') record for `%s'\n",
847  rec->data.mx->mxhost,
848  rec->name);
849  add_record (req, rec->type, expiration_time, dst, off);
850  }
851  break;
853  if (GNUNET_OK ==
854  GNUNET_DNSPARSER_builder_add_soa (dst, dst_len, &off, rec->data.soa))
855  {
856  /* NOTE: GNS does not really use SOAs */
858  "Converting SOA record for `%s'\n",
859  rec->name);
860  add_record (req, rec->type, expiration_time, dst, off);
861  }
862  break;
864  if (GNUNET_OK ==
865  GNUNET_DNSPARSER_builder_add_srv (dst, dst_len, &off, rec->data.srv))
866  {
868  "Converting SRV record for `%s'\n",
869  rec->name);
870  add_record (req, rec->type, expiration_time, dst, off);
871  }
872  break;
875  dst_len,
876  &off,
877  rec->data.hostname))
878  {
879  /* !?: what does a PTR record do in a regular TLD??? */
881  "Converting PTR record for `%s' (weird)\n",
882  rec->name);
883  add_record (req, rec->type, expiration_time, dst, off);
884  }
885  break;
887  if (GNUNET_OK ==
888  GNUNET_DNSPARSER_builder_add_cert (dst, dst_len, &off, rec->data.cert))
889  {
891  "Converting CERT record for `%s'\n",
892  rec->name);
893  add_record (req, rec->type, expiration_time, dst, off);
894  }
895  break;
896  /* Rest is 'raw' encoded and just needs to be copied IF
897  the hostname matches the requested name; otherwise we
898  simply cannot use it. */
902  default:
904  "Converting record of type %u for `%s'\n",
905  (unsigned int) rec->type,
906  rec->name);
907  add_record (req,
908  rec->type,
909  expiration_time,
910  rec->data.raw.data,
911  rec->data.raw.data_len);
912  break;
913  }
914 }
915 
916 
927 static void
928 store_completed_cb (void *cls, int32_t success, const char *emsg)
929 {
930  static struct GNUNET_TIME_Absolute last;
931  struct Request *req = cls;
932 
933  req->qe = NULL;
934  if (GNUNET_SYSERR == success)
935  {
937  "Failed to store zone data for `%s': %s\n",
938  req->hostname,
939  emsg);
940  }
941  else
942  {
944  "Stored records under `%s' (%d)\n",
945  req->hostname,
946  success);
947  }
948  total_reg_proc_dns_ns++; /* finished regular processing */
949  pending_rs--;
950  free_records (req);
951  /* compute NAMESTORE statistics */
952  {
953  static uint64_t total_ns_latency_cnt;
954  static struct GNUNET_TIME_Relative total_ns_latency;
955  struct GNUNET_TIME_Relative ns_latency;
956 
958  total_ns_latency = GNUNET_TIME_relative_add (total_ns_latency, ns_latency);
959  if (0 == total_ns_latency_cnt)
960  last = GNUNET_TIME_absolute_get ();
961  total_ns_latency_cnt++;
962  if (0 == (total_ns_latency_cnt % 1000))
963  {
964  struct GNUNET_TIME_Relative delta;
965 
966  delta = GNUNET_TIME_absolute_get_duration (last);
967  last = GNUNET_TIME_absolute_get ();
968  fprintf (stderr,
969  "Processed 1000 records in %s\n",
971  GNUNET_STATISTICS_set (stats,
972  "# average NAMESTORE PUT latency (μs)",
973  total_ns_latency.rel_value_us /
974  total_ns_latency_cnt,
975  GNUNET_NO);
976  }
977  }
978  /* compute and publish overall velocity */
979  if (0 == (total_reg_proc_dns_ns % 100))
980  {
981  struct GNUNET_TIME_Relative runtime;
982 
984  runtime = GNUNET_TIME_relative_subtract (runtime, idle_time);
985  runtime =
988  GNUNET_STATISTICS_set (stats,
989  "# Regular processing completed without NAMESTORE",
991  GNUNET_NO);
992  GNUNET_STATISTICS_set (stats,
993  "# Regular processing completed with NAMESTORE PUT",
995  GNUNET_NO);
996  GNUNET_STATISTICS_set (stats,
997  "# average request processing latency (μs)",
998  runtime.rel_value_us,
999  GNUNET_NO);
1000  GNUNET_STATISTICS_set (stats,
1001  "# total time spent idle (μs)",
1003  GNUNET_NO);
1004  }
1005 
1006  if (NULL == t)
1007  {
1010  }
1011 }
1012 
1013 
1021 static void
1022 process_result (void *cls,
1023  const struct GNUNET_TUN_DnsHeader *dns,
1024  size_t dns_len)
1025 {
1026  struct Request *req = cls;
1027  struct Record *rec;
1028  struct GNUNET_DNSPARSER_Packet *p;
1029  unsigned int rd_count;
1030 
1031  GNUNET_assert (NULL == req->hn);
1032  if (NULL == dns)
1033  {
1034  /* stub gave up */
1035  GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req);
1036  pending--;
1037  if (NULL == t)
1038  {
1041  }
1043  "Stub gave up on DNS reply for `%s'\n",
1044  req->hostname);
1045  GNUNET_STATISTICS_update (stats, "# DNS lookups timed out", 1, GNUNET_NO);
1046  if (req->issue_num > MAX_RETRIES)
1047  {
1048  failures++;
1049  free_request (req);
1050  GNUNET_STATISTICS_update (stats, "# requests given up on", 1, GNUNET_NO);
1051  return;
1052  }
1054  req->rs = NULL;
1055  insert_sorted (req);
1056  return;
1057  }
1058  if (req->id != dns->id)
1059  {
1061  "DNS ID did not match request, ignoring reply\n");
1062  GNUNET_STATISTICS_update (stats, "# DNS ID mismatches", 1, GNUNET_NO);
1063  return;
1064  }
1065  GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req);
1067  req->rs = NULL;
1068  pending--;
1069  p = GNUNET_DNSPARSER_parse ((const char *) dns, dns_len);
1070  if (NULL == p)
1071  {
1073  "Failed to parse DNS reply for `%s'\n",
1074  req->hostname);
1075  GNUNET_STATISTICS_update (stats, "# DNS parser errors", 1, GNUNET_NO);
1076  if (NULL == t)
1077  {
1080  }
1081  if (req->issue_num > MAX_RETRIES)
1082  {
1083  failures++;
1084  free_request (req);
1085  GNUNET_STATISTICS_update (stats, "# requests given up on", 1, GNUNET_NO);
1086  return;
1087  }
1088  insert_sorted (req);
1089  return;
1090  }
1091  /* import new records */
1092  req->issue_num = 0; /* success, reset counter! */
1093  {
1094  struct ProcessRecordContext prc = {.req = req, .p = p};
1095 
1096  for_all_records (p, &process_record, &prc);
1097  }
1099  /* count records found, determine minimum expiration time */
1101  {
1102  struct GNUNET_TIME_Relative dns_latency;
1103 
1104  dns_latency = GNUNET_TIME_absolute_get_duration (req->op_start_time);
1108  if (0 == (total_dns_latency_cnt % 1000))
1109  {
1110  GNUNET_STATISTICS_set (stats,
1111  "# average DNS lookup latency (μs)",
1114  GNUNET_NO);
1115  }
1116  }
1117  rd_count = 0;
1118  for (rec = req->rec_head; NULL != rec; rec = rec->next)
1119  {
1120  struct GNUNET_TIME_Absolute at;
1121 
1122  at.abs_value_us = rec->grd.expiration_time;
1123  req->expires = GNUNET_TIME_absolute_min (req->expires, at);
1124  rd_count++;
1125  }
1127  "Obtained %u records for `%s'\n",
1128  rd_count,
1129  req->hostname);
1130  /* Instead of going for SOA, simplified for now to look each
1131  day in case we got an empty response */
1132  if (0 == rd_count)
1133  {
1135  GNUNET_STATISTICS_update (stats,
1136  "# empty DNS replies (usually NXDOMAIN)",
1137  1,
1138  GNUNET_NO);
1139  }
1140  else
1141  {
1142  record_sets++;
1143  }
1144  /* convert records to namestore import format */
1145  {
1146  struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1147  unsigned int off = 0;
1148 
1149  /* convert linked list into array */
1150  for (rec = req->rec_head; NULL != rec; rec = rec->next)
1151  rd[off++] = rec->grd;
1152  pending_rs++;
1155  &req->zone->key,
1156  get_label (req),
1157  rd_count,
1158  rd,
1160  req);
1161  GNUNET_assert (NULL != req->qe);
1162  }
1163  insert_sorted (req);
1164 }
1165 
1166 
1172 static void
1173 process_queue (void *cls)
1174 {
1175  struct Request *req;
1176  unsigned int series;
1177  void *raw;
1178  size_t raw_size;
1179  struct GNUNET_TIME_Relative delay;
1180 
1181  (void) cls;
1184  series = 0;
1185  t = NULL;
1186  while (pending + pending_rs < THRESH)
1187  {
1188  req = GNUNET_CONTAINER_heap_peek (req_heap);
1189  if (NULL == req)
1190  break;
1191  if (NULL != req->qe)
1192  return; /* namestore op still pending */
1193  if (NULL != req->rs)
1194  {
1195  GNUNET_break (0);
1196  return; /* already submitted */
1197  }
1199  break;
1201  req->hn = NULL;
1202  GNUNET_CONTAINER_DLL_insert (req_head, req_tail, req);
1203  GNUNET_assert (NULL == req->rs);
1205  "Requesting resolution for `%s'\n",
1206  req->hostname);
1207  raw = build_dns_query (req, &raw_size);
1208  if (NULL == raw)
1209  {
1210  GNUNET_break (0);
1211  free_request (req);
1212  continue;
1213  }
1215  req->rs = GNUNET_DNSSTUB_resolve (ctx, raw, raw_size, &process_result, req);
1216  GNUNET_assert (NULL != req->rs);
1217  req->issue_num++;
1218  lookups++;
1219  pending++;
1220  series++;
1221  if (series > MAX_SERIES)
1222  break;
1223  }
1224  if (pending + pending_rs >= THRESH)
1225  {
1227  "Stopped processing queue (%u+%u/%u)]\n",
1228  pending,
1229  pending_rs,
1230  THRESH);
1231  return; /* wait for replies */
1232  }
1233  req = GNUNET_CONTAINER_heap_peek (req_heap);
1234  if (NULL == req)
1235  {
1237  "Stopped processing queue: empty queue\n");
1238  return;
1239  }
1241  {
1243  "Waiting until %s for next record (`%s') to expire\n",
1245  req->hostname);
1246  if (NULL != t)
1249  t = GNUNET_SCHEDULER_add_at (req->expires, &process_queue, NULL);
1250  return;
1251  }
1252  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Throttling\n");
1253  if (NULL != t)
1257 }
1258 
1259 
1269 static int
1270 free_request_it (void *cls, const struct GNUNET_HashCode *key, void *value)
1271 {
1272  struct Request *req = value;
1273 
1274  (void) cls;
1275  (void) key;
1276  free_request (req);
1277  return GNUNET_OK;
1278 }
1279 
1280 
1286 static void
1287 do_shutdown (void *cls)
1288 {
1289  struct Request *req;
1290  struct Zone *zone;
1291 
1292  (void) cls;
1293  if (NULL != id)
1294  {
1296  id = NULL;
1297  }
1298  if (NULL != t)
1299  {
1301  t = NULL;
1302  }
1303  while (NULL != (req = req_head))
1304  {
1305  GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req);
1306  if (NULL != req->qe)
1307  GNUNET_NAMESTORE_cancel (req->qe);
1308  free_request (req);
1309  }
1310  while (NULL != (req = GNUNET_CONTAINER_heap_remove_root (req_heap)))
1311  {
1312  req->hn = NULL;
1313  if (NULL != req->qe)
1314  GNUNET_NAMESTORE_cancel (req->qe);
1315  free_request (req);
1316  }
1317  if (NULL != zone_it)
1318  {
1320  zone_it = NULL;
1321  }
1322  if (NULL != ns)
1323  {
1325  ns = NULL;
1326  }
1327  if (NULL != ctx)
1328  {
1329  GNUNET_DNSSTUB_stop (ctx);
1330  ctx = NULL;
1331  }
1332  if (NULL != req_heap)
1333  {
1334  GNUNET_CONTAINER_heap_destroy (req_heap);
1335  req_heap = NULL;
1336  }
1337  if (NULL != ns_pending)
1338  {
1341  ns_pending = NULL;
1342  }
1343  while (NULL != (zone = zone_head))
1344  {
1345  GNUNET_CONTAINER_DLL_remove (zone_head, zone_tail, zone);
1346  GNUNET_free (zone->domain);
1347  GNUNET_free (zone);
1348  }
1349  if (NULL != stats)
1350  {
1352  stats = NULL;
1353  }
1354 }
1355 
1356 
1363 static void
1364 iterate_zones (void *cls);
1365 
1366 
1373 static void
1375 {
1376  struct Zone *zone = cls;
1377 
1379  "Failed to load data from namestore for zone `%s'\n",
1380  zone->domain);
1381  zone_it = NULL;
1383  iterate_zones (NULL);
1384 }
1385 
1386 
1396 static void
1398  const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
1399  const char *label,
1400  unsigned int rd_count,
1401  const struct GNUNET_GNSRECORD_Data *rd)
1402 {
1403  struct Zone *zone = cls;
1404  struct Request *req;
1405  struct GNUNET_HashCode hc;
1406  char *fqdn;
1407 
1410  "Obtained NAMESTORE reply, %llu left in round\n",
1411  (unsigned long long) ns_iterator_trigger_next);
1412  if (0 == ns_iterator_trigger_next)
1413  {
1414  ns_iterator_trigger_next = NS_BATCH_SIZE;
1415  GNUNET_STATISTICS_update (stats,
1416  "# NAMESTORE records requested from cache",
1417  ns_iterator_trigger_next,
1418  GNUNET_NO);
1419  GNUNET_NAMESTORE_zone_iterator_next (zone_it, ns_iterator_trigger_next);
1420  }
1421  GNUNET_asprintf (&fqdn, "%s.%s", label, zone->domain);
1422  GNUNET_CRYPTO_hash (fqdn, strlen (fqdn) + 1, &hc);
1423  GNUNET_free (fqdn);
1424  req = GNUNET_CONTAINER_multihashmap_get (ns_pending, &hc);
1425  if (NULL == req)
1426  {
1428  "Ignoring record `%s' in zone `%s': not on my list!\n",
1429  label,
1430  zone->domain);
1431  return;
1432  }
1434  GNUNET_CONTAINER_multihashmap_remove (ns_pending, &hc, req));
1435  GNUNET_break (0 == GNUNET_memcmp (key, &req->zone->key));
1436  GNUNET_break (0 == strcasecmp (label, get_label (req)));
1437  for (unsigned int i = 0; i < rd_count; i++)
1438  {
1439  struct GNUNET_TIME_Absolute at;
1440 
1442  {
1443  struct GNUNET_TIME_Relative rel;
1444 
1445  rel.rel_value_us = rd->expiration_time;
1447  }
1448  else
1449  {
1450  at.abs_value_us = rd->expiration_time;
1451  }
1452  add_record (req, rd->record_type, at, rd->data, rd->data_size);
1453  }
1454  if (0 == rd_count)
1455  {
1457  "Empty record set in namestore for `%s'\n",
1458  req->hostname);
1459  }
1460  else
1461  {
1462  unsigned int pos = 0;
1463 
1464  cached++;
1466  for (struct Record *rec = req->rec_head; NULL != rec; rec = rec->next)
1467  {
1468  struct GNUNET_TIME_Absolute at;
1469 
1470  at.abs_value_us = rec->grd.expiration_time;
1471  req->expires = GNUNET_TIME_absolute_min (req->expires, at);
1472  pos++;
1473  }
1474  if (0 == pos)
1477  "Hot-start with %u existing records for `%s'\n",
1478  pos,
1479  req->hostname);
1480  }
1481  free_records (req);
1482 
1484  "Adding `%s' to worklist to start at %s\n",
1485  req->hostname,
1487  insert_sorted (req);
1488 }
1489 
1490 
1496 static void
1497 queue (const char *hostname)
1498 {
1499  struct Request *req;
1500  const char *dot;
1501  struct Zone *zone;
1502  size_t hlen;
1503  struct GNUNET_HashCode hc;
1504 
1505  if (GNUNET_OK != GNUNET_DNSPARSER_check_name (hostname))
1506  {
1508  "Refusing invalid hostname `%s'\n",
1509  hostname);
1510  rejects++;
1511  return;
1512  }
1513  dot = strchr (hostname, (unsigned char) '.');
1514  if (NULL == dot)
1515  {
1517  "Refusing invalid hostname `%s' (lacks '.')\n",
1518  hostname);
1519  rejects++;
1520  return;
1521  }
1522  for (zone = zone_head; NULL != zone; zone = zone->next)
1523  if (0 == strcmp (zone->domain, dot + 1))
1524  break;
1525  if (NULL == zone)
1526  {
1527  rejects++;
1529  "Domain name `%s' not in ego list!\n",
1530  dot + 1);
1531  return;
1532  }
1533 
1534  hlen = strlen (hostname) + 1;
1535  req = GNUNET_malloc (sizeof (struct Request) + hlen);
1536  req->zone = zone;
1537  req->hostname = (char *) &req[1];
1538  GNUNET_memcpy (req->hostname, hostname, hlen);
1540  UINT16_MAX);
1541  GNUNET_CRYPTO_hash (req->hostname, hlen, &hc);
1543  ns_pending,
1544  &hc,
1545  req,
1547  {
1549  "Duplicate hostname `%s' ignored\n",
1550  hostname);
1551  GNUNET_free (req);
1552  return;
1553  }
1554 }
1555 
1556 
1568 static int
1569 move_to_queue (void *cls, const struct GNUNET_HashCode *key, void *value)
1570 {
1571  struct Request *req = value;
1572 
1573  (void) cls;
1574  (void) key;
1575  insert_sorted (req);
1576  return GNUNET_OK;
1577 }
1578 
1579 
1586 static void
1587 iterate_zones (void *cls)
1588 {
1589  static struct Zone *last;
1590 
1591  (void) cls;
1592  if (NULL != zone_it)
1593  {
1594  zone_it = NULL;
1596  "Finished iteration over zone `%s'!\n",
1597  last->domain);
1598  /* subtract left-overs from previous iteration */
1599  GNUNET_STATISTICS_update (stats,
1600  "# NAMESTORE records requested from cache",
1601  (long long) (-ns_iterator_trigger_next),
1602  GNUNET_NO);
1604  }
1605  GNUNET_assert (NULL != zone_tail);
1606  if (zone_tail == last)
1607  {
1608  /* Done iterating over relevant zones in NAMESTORE, move
1609  rest of hash map to work queue as well. */
1611  "Finished all NAMESTORE iterations!\n");
1612  GNUNET_STATISTICS_set (stats,
1613  "# Domain names without cached reply",
1615  GNUNET_NO);
1618  ns_pending = NULL;
1620  total_reg_proc_dns = 0;
1622  return;
1623  }
1624  if (NULL == last)
1625  last = zone_head;
1626  else
1627  last = last->next;
1629  "Starting iteration over zone `%s'!\n",
1630  last->domain);
1631  /* subtract left-overs from previous iteration */
1632  GNUNET_STATISTICS_update (stats,
1633  "# NAMESTORE records requested from cache",
1634  1,
1635  GNUNET_NO);
1637  GNUNET_STATISTICS_update (stats, "# zones iterated", 1, GNUNET_NO);
1639  &last->key,
1641  NULL,
1643  last,
1644  &iterate_zones,
1645  NULL);
1646 }
1647 
1648 
1654 static void
1655 process_stdin (void *cls)
1656 {
1657  static struct GNUNET_TIME_Absolute last;
1658  static uint64_t idot;
1659  char hn[256];
1660 
1661  (void) cls;
1662  t = NULL;
1663  if (NULL != id)
1664  {
1666  id = NULL;
1667  }
1668  while (NULL != fgets (hn, sizeof (hn), stdin))
1669  {
1670  if (strlen (hn) > 0)
1671  hn[strlen (hn) - 1] = '\0'; /* eat newline */
1672  if (0 == idot)
1673  last = GNUNET_TIME_absolute_get ();
1674  idot++;
1675  if (0 == idot % 100000)
1676  {
1677  struct GNUNET_TIME_Relative delta;
1678 
1679  delta = GNUNET_TIME_absolute_get_duration (last);
1680  last = GNUNET_TIME_absolute_get ();
1681  fprintf (stderr,
1682  "Read 100000 domain names in %s\n",
1684  GNUNET_STATISTICS_set (stats, "# domain names provided", idot, GNUNET_NO);
1685  }
1686  queue (hn);
1687  }
1688  fprintf (stderr,
1689  "Done reading %llu domain names\n",
1690  (unsigned long long) idot);
1691  GNUNET_STATISTICS_set (stats, "# domain names provided", idot, GNUNET_NO);
1692  iterate_zones (NULL);
1693 }
1694 
1695 
1730 static void
1731 identity_cb (void *cls,
1732  struct GNUNET_IDENTITY_Ego *ego,
1733  void **ctx,
1734  const char *name)
1735 {
1736  (void) cls;
1737  (void) ctx;
1738 
1739  if (NULL == ego)
1740  {
1741  /* end of iteration */
1742  if (NULL == zone_head)
1743  {
1744  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No zone found\n");
1746  return;
1747  }
1748  /* zone_head non-null, process hostnames from stdin */
1750  return;
1751  }
1752  if (NULL != name)
1753  {
1754  struct Zone *zone;
1755 
1756  zone = GNUNET_new (struct Zone);
1758  zone->domain = GNUNET_strdup (name);
1759  GNUNET_CONTAINER_DLL_insert (zone_head, zone_tail, zone);
1760  }
1761 }
1762 
1763 
1773 static void
1774 run (void *cls,
1775  char *const *args,
1776  const char *cfgfile,
1777  const struct GNUNET_CONFIGURATION_Handle *cfg)
1778 {
1779  (void) cls;
1780  (void) args;
1781  (void) cfgfile;
1782  stats = GNUNET_STATISTICS_create ("zoneimport", cfg);
1785  if (NULL == ns_pending)
1786  {
1787  fprintf (stderr, "Failed to allocate memory for main hash map\n");
1788  return;
1789  }
1790  ctx = GNUNET_DNSSTUB_start (256);
1791  if (NULL == ctx)
1792  {
1793  fprintf (stderr, "Failed to initialize GNUnet DNS STUB\n");
1794  return;
1795  }
1796  if (NULL == args[0])
1797  {
1798  fprintf (stderr,
1799  "You must provide a list of DNS resolvers on the command line\n");
1800  return;
1801  }
1802  for (unsigned int i = 0; NULL != args[i]; i++)
1803  {
1804  if (GNUNET_OK != GNUNET_DNSSTUB_add_dns_ip (ctx, args[i]))
1805  {
1806  fprintf (stderr, "Failed to use `%s' for DNS resolver\n", args[i]);
1807  return;
1808  }
1809  }
1810 
1811 
1813  ns = GNUNET_NAMESTORE_connect (cfg);
1814  if (NULL == ns)
1815  {
1817  return;
1818  }
1819  id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL);
1820 }
1821 
1822 
1830 int
1831 main (int argc, char *const *argv)
1832 {
1833  struct GNUNET_GETOPT_CommandLineOption options[] =
1835  "size",
1836  "MAPSIZE",
1837  gettext_noop (
1838  "size to use for the main hash map"),
1839  &map_size),
1841  'm',
1842  "minimum-expiration",
1843  "RELATIVETIME",
1844  gettext_noop ("minimum expiration time we assume for imported records"),
1847  int ret;
1848 
1849  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1850  return 2;
1851  if (GNUNET_OK != (ret = GNUNET_PROGRAM_run (argc,
1852  argv,
1853  "gnunet-zoneimport",
1854  "import DNS zone into namestore",
1855  options,
1856  &run,
1857  NULL)))
1858  return ret;
1859  GNUNET_free ((void *) argv);
1860  fprintf (stderr,
1861  "Rejected %u names, had %u cached, did %u lookups, stored %u record sets\n"
1862  "Found %u records, %u lookups failed, %u/%u pending on shutdown\n",
1863  rejects,
1864  cached,
1865  lookups,
1866  record_sets,
1867  records,
1868  failures,
1869  pending,
1870  pending_rs);
1871  return 0;
1872 }
1873 
1874 /* end of gnunet-zoneimport.c */
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_relative_time(char shortName, const char *name, const char *argumentHelp, const char *description, struct GNUNET_TIME_Relative *val)
Allow user to specify a struct GNUNET_TIME_Relative (using human-readable "fancy" time)...
struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls)
Connect to the identity service.
Definition: identity_api.c:528
static struct GNUNET_TIME_Relative total_dns_latency
Sum of DNS latencies observed.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
char * domain
Domain of the zone (i.e.
struct GNUNET_DNSPARSER_Record * answers
Array of all answers in the packet, must contain "num_answers" entries.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
static struct GNUNET_NAMESTORE_ZoneIterator * zone_it
Current zone iteration handle.
static struct GNUNET_DATASTORE_QueueEntry * qe
Current operation.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct Request * req
Request we are processing.
uint64_t rel_value_us
The actual value.
static void process_record(void *cls, const struct GNUNET_DNSPARSER_Record *rec)
We received rec for req.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
int main(int argc, char *const *argv)
Call with IP address of resolver to query.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
static int raw
raw output
Definition: gnunet-gns.c:55
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.
char * hostname
Hostname we are resolving.
static unsigned int pending_rs
The number of NAMESTORE record store operations that are outstanding.
#define GNUNET_DNSPARSER_TYPE_CNAME
char * mxhost
Name of the mail server.
struct GNUNET_DNSPARSER_SrvRecord * srv
SRV data for SRV records.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1293
struct GNUNET_NAMESTORE_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
Starts a new zone iteration (used to periodically PUT all of our records into our DHT)...
static uint64_t total_dns_latency_cnt
Number of DNS requests counted in latency total.
static struct Request * req_tail
Active requests are kept in a DLL.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1521
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.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Process requests from the queue, then if the queue is not empty, try again.
#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
#define MAX_RETRIES
How often do we retry a query before giving up for good?
uint16_t id
random 16-bit DNS query identifier.
static void for_all_records(const struct GNUNET_DNSPARSER_Packet *p, RecordProcessor rp, void *rp_cls)
Call rp for each record in p, regardless of what response section it is in.
static void do_shutdown(void *cls)
Clean up and terminate the process.
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
const struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:556
uint16_t id
DNS ID (to match replies to requests).
static struct GNUNET_NAMESTORE_Handle * ns
Namestore handle.
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:854
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_HashMapIterator it, void *it_cls)
Iterate over all entries in the map.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
size_t data_size
Number of bytes in data.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Definition of a command line option.
void GNUNET_NAMESTORE_zone_iterator_next(struct GNUNET_NAMESTORE_ZoneIterator *it, uint64_t limit)
Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start for the next record...
Private ECC key encoded for transmission.
struct GNUNET_DNSPARSER_Record * additional_records
Array of all additional answers in the packet, must contain "num_additional_records" entries...
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:524
static int ret
Final status code.
Definition: gnunet-arm.c:89
Handle for the service.
static unsigned int failures
Number of lookups that failed.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_DNSPARSER_TYPE_MX
unsigned int num_answers
Number of answers in the packet, should be 0 for queries.
uint64_t abs_value_us
The actual value.
struct GNUNET_CRYPTO_EcdsaPrivateKey key
Private key of the zone.
uint16_t id
Unique identifier for the request/response.
Internal representation of the hash map.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
void(* RecordProcessor)(void *cls, const struct GNUNET_DNSPARSER_Record *rec)
Callback for for_all_records.
unsigned int issue_num
How often did we issue this query? (And failed, reset to zero once we were successful.)
static uint64_t total_reg_proc_dns_ns
Number of records processed (DNS lookup, with NAMESTORE) in total.
void GNUNET_NAMESTORE_cancel(struct GNUNET_NAMESTORE_QueueEntry *qe)
Cancel a namestore operation.
static void iterate_zones(void *cls)
Iterate over all of the zones we care about and see which records we may need to re-fetch when...
static struct GNUNET_TIME_Absolute start_time_reg_proc
Start time of the regular processing.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_store(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls)
Store an item in the namestore.
#define GNUNET_DNSPARSER_TYPE_PTR
static void free_records(struct Request *req)
Free records associated with req.
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
static char * zone
Name of the zone we manage.
static unsigned int rejects
How many hostnames did we reject (malformed).
void GNUNET_NAMESTORE_disconnect(struct GNUNET_NAMESTORE_Handle *h)
Disconnect from the namestore service (and free associated resources).
static void store_completed_cb(void *cls, int32_t success, const char *emsg)
Continuation called to notify client about result of the operation.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
Handle for a zone iterator operation.
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
Handle for an ego.
Definition: identity.h:245
#define GNUNET_DNSPARSER_TYPE_SOA
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
Closure for process_record().
static struct GNUNET_IDENTITY_Handle * id
Handle to the identity service.
static char * value
Value of the record to add/remove.
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 void ns_lookup_error_cb(void *cls)
Function called if GNUNET_NAMESTORE_records_lookup() failed.
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
struct Record * rec_head
Head of records that should be published in GNS for this hostname.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition: dnsstub.c:595
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
Connection to the NAMESTORE service.
int found
Set to GNUNET_YES if glue was found.
#define GNUNET_DNSPARSER_TYPE_DNAME
Handle for the service.
Definition: identity_api.c:96
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
uint64_t expiration_time
Expiration time for the DNS record.
static struct GNUNET_CONTAINER_MultiHashMap * ns_pending
Hash map of requests for which we may still get a response from the namestore.
static unsigned int map_size
Command-line argument specifying desired size of the hash map with all of our pending names...
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
struct GNUNET_CONTAINER_HeapNode * hn
Requests are kept in a heap while waiting to be resolved.
struct Record * next
Kept in a DLL.
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Record type for delegation to DNS.
void * GNUNET_CONTAINER_heap_peek(const struct GNUNET_CONTAINER_Heap *heap)
Get element stored at the root of heap.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:727
Randomness for IVs etc.
int GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
Handle to a node in a heap.
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:838
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
struct GNUNET_TIME_Absolute expires
At what time does the (earliest) of the returned records for this name expire? At this point...
struct GNUNET_TIME_Relative GNUNET_TIME_relative_subtract(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Subtract relative timestamp from the other.
Definition: time.c:601
A DNS response record.
Heap with the minimum cost at the root.
static unsigned int pending
The number of DNS queries that are outstanding.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
struct GNUNET_DNSPARSER_Record * authority_records
Array of all authority records in the packet, must contain "num_authority_records" entries...
void GNUNET_NAMESTORE_zone_iteration_stop(struct GNUNET_NAMESTORE_ZoneIterator *it)
Stops iteration and releases the namestore handle for further calls.
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
static struct GNUNET_TIME_Relative idle_time
Time we slept just waiting for work.
struct GNUNET_DNSPARSER_Query * queries
Array of all queries in the packet, must contain "num_queries" entries.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
const char * ns
NS name we are looking for glue for.
static unsigned int record_sets
Number of record sets given to namestore.
static struct GNUNET_CONTAINER_Heap * req_heap
Heap of all requests to perform, sorted by the time we should next do the request (i...
static const char * get_label(struct Request *req)
Return just the label of the hostname in req.
int GNUNET_DNSPARSER_builder_add_cert(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_CertRecord *cert)
Add CERT record to the UDP packet at the given location.
Definition: dnsparser.c:1037
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
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
#define THRESH
Maximum number of queries pending at the same time.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
Node in the heap.
static void process_stdin(void *cls)
Begin processing hostnames from stdin.
static struct Zone * zone_tail
Tail of list of zones we are managing.
static struct Request * req_head
Active requests are kept in a DLL.
struct Record * rec_tail
Tail of records that should be published in GNS for this hostname.
#define MAX_SERIES
How many DNS requests do we at most issue in rapid series?
There must only be one value per key; storing a value should fail if a value under the same key alrea...
static void identity_cb(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name)
Method called to inform about the egos of this peer.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
size_t data_len
Number of bytes in data.
An QueueEntry used to store information for a pending NAMESTORE record operation. ...
Definition: namestore_api.c:53
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 GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namestore service.
static int free_request_it(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator called during do_shutdown() to free requests in the ns_pending map.
int issue_num
How often did we issue this query?
#define GNUNET_DNSPARSER_TYPE_TXT
static uint64_t total_reg_proc_dns
Number of records processed (DNS lookup, no NAMESTORE) in total.
const char * name
int GNUNET_DNSPARSER_check_name(const char *name)
Check if a hostname in UTF-8 format can be coded into valid IDNA.
Definition: dnsparser.c:86
unsigned int num_authority_records
Number of authoritative answers in the packet, should be 0 for queries.
struct Request * req
Overall request we are processing.
static int move_to_queue(void *cls, const struct GNUNET_HashCode *key, void *value)
We have completed the initial iteration over the namestore&#39;s database.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
#define SERIES_DELAY
How long do we wait at least between series of requests?
#define GNUNET_TIME_UNIT_DAYS
One day.
#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...
Record for the request to be stored by GNS.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
static struct Zone * zone_head
Head of list of zones we are managing.
struct GNUNET_NAMESTORE_QueueEntry * qe
Active request with the namestore.
#define NS_BATCH_SIZE
How many requests do we request from NAMESTORE in one batch during our initial iteration?
struct GNUNET_TIME_Absolute expiration_time
When does the record expire?
static void insert_sorted(struct Request *req)
Insert req into DLL sorted by next fetch time.
Request we should make.
struct GNUNET_DNSSTUB_RequestSocket * rs
Socket used to make the request, NULL if not active.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition: time.c:576
static unsigned int cached
Number of records we had cached.
struct GNUNET_TIME_Absolute op_start_time
While we are fetching the record, the value is set to the starting time of the GNS operation...
static char * hostname
Our hostname; we give this to all the peers we start.
static void queue(const char *hostname)
Add hostname to the list of requests to be made.
struct GNUNET_DNSPARSER_MxRecord * mx
MX data for MX records.
uint32_t record_type
Type of the GNS/DNS record.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
#define GNUNET_DNSPARSER_TYPE_AAAA
configuration data
Definition: configuration.c:85
struct Record * prev
Kept in a DLL.
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition: dnsstub.c:571
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition: time.c:302
static void process_result(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
Function called with the result of a DNS resolution.
#define GNUNET_DNSPARSER_TYPE_NS
struct Zone * next
Kept in a DLL.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:373
Easy-to-process, parsed version of a DNS packet.
static void check_for_glue(void *cls, const struct GNUNET_DNSPARSER_Record *rec)
Try to find glue records for a given NS record.
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
static void add_record(struct Request *req, uint32_t type, struct GNUNET_TIME_Absolute expiration_time, const void *data, size_t data_len)
Add record to the GNS record set for req.
#define GNUNET_log(kind,...)
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 GNUNET_SCHEDULER_Task * t
Main task.
static uint64_t ns_iterator_trigger_next
After how many more results must ns_lookup_result_cb() ask the namestore for more?
static struct GNUNET_TIME_Absolute sleep_time_reg_proc
Last time we worked before going idle.
const struct Zone * zone
Zone responsible for this request.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
static char * rp
Relying party.
int GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration, parse options).
Definition: program.c:361
char * name
Name of the record that the query is for (0-terminated).
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
unsigned int num_queries
Number of queries in the packet.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
static void free_request(struct Request *req)
Free req and data structures reachable from it.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:525
Time for absolute times used by GNUnet, in microseconds.
static struct GNUNET_TIME_Relative minimum_expiration_time
How long do DNS records have to last at least after being imported?
static unsigned int records
Number of records we found.
#define GNUNET_YES
Definition: gnunet_common.h:80
static void ns_lookup_result_cb(void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process a record that was stored in the namestore.
static unsigned int lookups
Number of lookups we performed overall.
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_GETOPT_CommandLineOption GNUNET_GETOPT_option_uint(char shortName, const char *name, const char *argumentHelp, const char *description, unsigned int *val)
Allow user to specify an unsigned int.
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
UDP socket we are using for sending DNS requests to the Internet.
Definition: dnsstub.c:43
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition: scheduler.c:1223
static void process_queue(void *cls)
Process as many requests as possible from the queue.
struct Zone * prev
Kept in a DLL.
static void * build_dns_query(struct Request *req, size_t *raw_size)
Build DNS query for hostname.
#define GNUNET_DNSPARSER_TYPE_SRV
uint32_t data
The data value.
struct GNUNET_GNSRECORD_Data grd
GNS record.
struct GNUNET_DNSPARSER_Packet * p
Answer we got back and are currently parsing, or NULL if not active.
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
#define GNUNET_DNSPARSER_TYPE_A
Closure for check_for_glue.
#define GNUNET_DNSPARSER_TYPE_CERT
#define GNUNET_malloc(size)
Wrapper around malloc.
struct GNUNET_DNSPARSER_CertRecord * cert
CERT data for CERT records.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
#define gettext_noop(String)
Definition: gettext.h:69
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Some zones may include authoritative records for other zones, such as foo.com.uk or bar...