GNUnet  0.11.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 {
84  struct Zone *next;
85 
89  struct Zone *prev;
90 
94  char *domain;
95 
100 };
101 
102 
106 struct Record
107 {
111  struct Record *next;
112 
116  struct Record *prev;
117 
122 };
123 
124 
130 struct Request
131 {
136 
140  struct Request *next;
141 
145  struct Request *prev;
146 
151  struct Record *rec_head;
152 
157  struct Record *rec_tail;
158 
162  struct GNUNET_DNSSTUB_RequestSocket *rs;
163 
169  char *hostname;
170 
175 
179  const struct Zone *zone;
180 
186  struct GNUNET_TIME_Absolute expires;
187 
194  struct GNUNET_TIME_Absolute op_start_time;
195 
200  unsigned int issue_num;
201 
205  uint16_t id;
206 };
207 
208 
215 static unsigned int map_size = 1024;
216 
220 static struct GNUNET_IDENTITY_Handle *id;
221 
226 
231 
236 
240 static unsigned int pending;
241 
245 static unsigned int pending_rs;
246 
250 static unsigned int lookups;
251 
255 static unsigned int cached;
256 
260 static unsigned int rejects;
261 
265 static unsigned int failures;
266 
270 static unsigned int records;
271 
275 static unsigned int record_sets;
276 
282 
286 static struct Request *req_head;
287 
291 static struct Request *req_tail;
292 
296 static struct GNUNET_SCHEDULER_Task *t;
297 
304 
309 
313 static struct Zone *zone_head;
314 
318 static struct Zone *zone_tail;
319 
324 static uint64_t ns_iterator_trigger_next;
325 
329 static uint64_t total_dns_latency_cnt;
330 
335 
339 static uint64_t total_reg_proc_dns;
340 
344 static uint64_t total_reg_proc_dns_ns;
345 
350 
355 
360 
361 
368 typedef void (*RecordProcessor) (void *cls,
369  const struct GNUNET_DNSPARSER_Record *rec);
370 
371 
380 static void
383  void *rp_cls)
384 {
385  for (unsigned int i = 0; i < p->num_answers; i++)
386  {
387  struct GNUNET_DNSPARSER_Record *rs = &p->answers[i];
388 
389  rp (rp_cls, rs);
390  }
391  for (unsigned int i = 0; i < p->num_authority_records; i++)
392  {
393  struct GNUNET_DNSPARSER_Record *rs = &p->authority_records[i];
394 
395  rp (rp_cls, rs);
396  }
397  for (unsigned int i = 0; i < p->num_additional_records; i++)
398  {
399  struct GNUNET_DNSPARSER_Record *rs = &p->additional_records[i];
400 
401  rp (rp_cls, rs);
402  }
403 }
404 
405 
413 static const char *
414 get_label (struct Request *req)
415 {
416  static char label[64];
417  const char *dot;
418 
419  dot = strchr (req->hostname, (unsigned char) '.');
420  if (NULL == dot)
421  {
422  GNUNET_break (0);
423  return NULL;
424  }
425  if (((size_t) (dot - req->hostname)) >= sizeof(label))
426  {
427  GNUNET_break (0);
428  return NULL;
429  }
430  GNUNET_memcpy (label, req->hostname, dot - req->hostname);
431  label[dot - req->hostname] = '\0';
432  return label;
433 }
434 
435 
444 static void *
445 build_dns_query (struct Request *req, size_t *raw_size)
446 {
447  static char raw[512];
448  char *rawp;
449  struct GNUNET_DNSPARSER_Packet p;
450  struct GNUNET_DNSPARSER_Query q;
451  int ret;
452 
453  q.name = (char *) req->hostname;
456 
457  memset (&p, 0, sizeof(p));
458  p.num_queries = 1;
459  p.queries = &q;
460  p.id = req->id;
461  ret = GNUNET_DNSPARSER_pack (&p, UINT16_MAX, &rawp, raw_size);
462  if (GNUNET_OK != ret)
463  {
464  if (GNUNET_NO == ret)
465  GNUNET_free (rawp);
467  "Failed to pack query for hostname `%s'\n",
468  req->hostname);
469  rejects++;
470  return NULL;
471  }
472  if (*raw_size > sizeof(raw))
473  {
475  "Failed to pack query for hostname `%s'\n",
476  req->hostname);
477  rejects++;
478  GNUNET_break (0);
479  GNUNET_free (rawp);
480  return NULL;
481  }
482  GNUNET_memcpy (raw, rawp, *raw_size);
483  GNUNET_free (rawp);
484  return raw;
485 }
486 
487 
493 static void
494 free_records (struct Request *req)
495 {
496  struct Record *rec;
497 
498  /* Free records */
499  while (NULL != (rec = req->rec_head))
500  {
502  GNUNET_free (rec);
503  }
504 }
505 
506 
512 static void
513 free_request (struct Request *req)
514 {
515  free_records (req);
516  GNUNET_free (req);
517 }
518 
519 
525 static void
526 process_queue (void *cls);
527 
528 
534 static void
535 insert_sorted (struct Request *req)
536 {
537  req->hn =
538  GNUNET_CONTAINER_heap_insert (req_heap, req, req->expires.abs_value_us);
539  if (req == GNUNET_CONTAINER_heap_peek (req_heap))
540  {
541  if (NULL != t)
544  t = GNUNET_SCHEDULER_add_at (req->expires, &process_queue, NULL);
545  }
546 }
547 
548 
558 static void
559 add_record (struct Request *req,
560  uint32_t type,
561  struct GNUNET_TIME_Absolute expiration_time,
562  const void *data,
563  size_t data_len)
564 {
565  struct Record *rec;
566 
567  rec = GNUNET_malloc (sizeof(struct Record) + data_len);
568  rec->grd.data = &rec[1];
569  rec->grd.expiration_time = expiration_time.abs_value_us;
570  rec->grd.data_size = data_len;
571  rec->grd.record_type = type;
573  GNUNET_memcpy (&rec[1], data, data_len);
575 }
576 
577 
582 {
586  struct Request *req;
587 
591  const char *ns;
592 
596  int found;
597 };
598 
599 
606 static void
607 check_for_glue (void *cls, const struct GNUNET_DNSPARSER_Record *rec)
608 {
609  struct GlueClosure *gc = cls;
610  char dst[65536];
611  size_t dst_len;
612  size_t off;
613  char ip[INET6_ADDRSTRLEN + 1];
614  socklen_t ip_size = (socklen_t) sizeof(ip);
615  struct GNUNET_TIME_Absolute expiration_time;
616  struct GNUNET_TIME_Relative left;
617 
618  if (0 != strcasecmp (rec->name, gc->ns))
619  return;
620  expiration_time = rec->expiration_time;
621  left = GNUNET_TIME_absolute_get_remaining (expiration_time);
622  if (0 == left.rel_value_us)
623  return; /* ignore expired glue records */
624  /* if expiration window is too short, bump it to configured minimum */
626  expiration_time =
628  dst_len = sizeof(dst);
629  off = 0;
630  switch (rec->type)
631  {
633  if (sizeof(struct in_addr) != rec->data.raw.data_len)
634  {
635  GNUNET_break (0);
636  return;
637  }
638  if (NULL == inet_ntop (AF_INET, rec->data.raw.data, ip, ip_size))
639  {
640  GNUNET_break (0);
641  return;
642  }
644  dst_len,
645  &off,
646  gc->req->hostname)) &&
647  (GNUNET_OK ==
648  GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &off, ip)))
649  {
650  add_record (gc->req,
652  expiration_time,
653  dst,
654  off);
655  gc->found = GNUNET_YES;
656  }
657  break;
658 
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;
685 
688  dst_len,
689  &off,
690  gc->req->hostname)) &&
692  dst_len,
693  &off,
694  rec->data.hostname)))
695  {
696  add_record (gc->req,
698  expiration_time,
699  dst,
700  off);
701  gc->found = GNUNET_YES;
702  }
703  break;
704 
705  default:
706  /* useless, do nothing */
707  break;
708  }
709 }
710 
711 
716 {
722 
726  struct Request *req;
727 };
728 
729 
736 static void
737 process_record (void *cls, const struct GNUNET_DNSPARSER_Record *rec)
738 {
739  struct ProcessRecordContext *prc = cls;
740  struct Request *req = prc->req;
741  char dst[65536];
742  size_t dst_len;
743  size_t off;
744  struct GNUNET_TIME_Absolute expiration_time;
745  struct GNUNET_TIME_Relative left;
746 
747  dst_len = sizeof(dst);
748  off = 0;
749  records++;
750  if (0 != strcasecmp (rec->name, req->hostname))
751  {
752  GNUNET_log (
754  "DNS returned record from zone `%s' of type %u while resolving `%s'\n",
755  rec->name,
756  (unsigned int) rec->type,
757  req->hostname);
758  return; /* does not match hostname, might be glue, but
759  not useful for this pass! */
760  }
761  expiration_time = rec->expiration_time;
762  left = GNUNET_TIME_absolute_get_remaining (expiration_time);
763  if (0 == left.rel_value_us)
764  {
766  "DNS returned expired record for `%s'\n",
767  req->hostname);
769  "# expired records obtained from DNS",
770  1,
771  GNUNET_NO);
772  return; /* record expired */
773  }
774 
776  "DNS returned record that expires at %s for `%s'\n",
777  GNUNET_STRINGS_absolute_time_to_string (expiration_time),
778  req->hostname);
779  /* if expiration window is too short, bump it to configured minimum */
781  expiration_time =
783  switch (rec->type)
784  {
786  struct GlueClosure gc;
787 
788  /* check for glue */
789  gc.req = req;
790  gc.ns = rec->data.hostname;
791  gc.found = GNUNET_NO;
792  for_all_records (prc->p, &check_for_glue, &gc);
793  if ((GNUNET_NO == gc.found) &&
795  dst_len,
796  &off,
797  req->hostname)) &&
799  dst_len,
800  &off,
801  rec->data.hostname)))
802  {
803  /* FIXME: actually check if this is out-of-bailiwick,
804  and if not request explicit resolution... */
806  "Converted OOB (`%s') NS record for `%s'\n",
807  rec->data.hostname,
808  rec->name);
809  add_record (req,
811  expiration_time,
812  dst,
813  off);
814  }
815  else
816  {
818  "Converted NS record for `%s' using glue\n",
819  rec->name);
820  }
821  break;
822  }
823 
826  dst_len,
827  &off,
828  rec->data.hostname))
829  {
831  "Converting CNAME (`%s') record for `%s'\n",
832  rec->data.hostname,
833  rec->name);
834  add_record (req, rec->type, expiration_time, dst, off);
835  }
836  break;
837 
839  /* No support for DNAME in GNS yet! FIXME: support later! */
841  "FIXME: not supported: %s DNAME %s\n",
842  rec->name,
843  rec->data.hostname);
844  break;
845 
847  if (GNUNET_OK ==
848  GNUNET_DNSPARSER_builder_add_mx (dst, dst_len, &off, rec->data.mx))
849  {
851  "Converting MX (`%s') record for `%s'\n",
852  rec->data.mx->mxhost,
853  rec->name);
854  add_record (req, rec->type, expiration_time, dst, off);
855  }
856  break;
857 
859  if (GNUNET_OK ==
860  GNUNET_DNSPARSER_builder_add_soa (dst, dst_len, &off, rec->data.soa))
861  {
862  /* NOTE: GNS does not really use SOAs */
864  "Converting SOA record for `%s'\n",
865  rec->name);
866  add_record (req, rec->type, expiration_time, dst, off);
867  }
868  break;
869 
871  if (GNUNET_OK ==
872  GNUNET_DNSPARSER_builder_add_srv (dst, dst_len, &off, rec->data.srv))
873  {
875  "Converting SRV record for `%s'\n",
876  rec->name);
877  add_record (req, rec->type, expiration_time, dst, off);
878  }
879  break;
880 
883  dst_len,
884  &off,
885  rec->data.hostname))
886  {
887  /* !?: what does a PTR record do in a regular TLD??? */
889  "Converting PTR record for `%s' (weird)\n",
890  rec->name);
891  add_record (req, rec->type, expiration_time, dst, off);
892  }
893  break;
894 
896  if (GNUNET_OK ==
897  GNUNET_DNSPARSER_builder_add_cert (dst, dst_len, &off, rec->data.cert))
898  {
900  "Converting CERT record for `%s'\n",
901  rec->name);
902  add_record (req, rec->type, expiration_time, dst, off);
903  }
904  break;
905 
906  /* Rest is 'raw' encoded and just needs to be copied IF
907  the hostname matches the requested name; otherwise we
908  simply cannot use it. */
912  default:
914  "Converting record of type %u for `%s'\n",
915  (unsigned int) rec->type,
916  rec->name);
917  add_record (req,
918  rec->type,
919  expiration_time,
920  rec->data.raw.data,
921  rec->data.raw.data_len);
922  break;
923  }
924 }
925 
926 
937 static void
938 store_completed_cb (void *cls, int32_t success, const char *emsg)
939 {
940  static struct GNUNET_TIME_Absolute last;
941  struct Request *req = cls;
942 
943  req->qe = NULL;
944  if (GNUNET_SYSERR == success)
945  {
947  "Failed to store zone data for `%s': %s\n",
948  req->hostname,
949  emsg);
950  }
951  else
952  {
954  "Stored records under `%s' (%d)\n",
955  req->hostname,
956  success);
957  }
958  total_reg_proc_dns_ns++; /* finished regular processing */
959  pending_rs--;
960  free_records (req);
961  /* compute NAMESTORE statistics */
962  {
963  static uint64_t total_ns_latency_cnt;
964  static struct GNUNET_TIME_Relative total_ns_latency;
965  struct GNUNET_TIME_Relative ns_latency;
966 
968  total_ns_latency = GNUNET_TIME_relative_add (total_ns_latency, ns_latency);
969  if (0 == total_ns_latency_cnt)
970  last = GNUNET_TIME_absolute_get ();
971  total_ns_latency_cnt++;
972  if (0 == (total_ns_latency_cnt % 1000))
973  {
974  struct GNUNET_TIME_Relative delta;
975 
976  delta = GNUNET_TIME_absolute_get_duration (last);
977  last = GNUNET_TIME_absolute_get ();
978  fprintf (stderr,
979  "Processed 1000 records in %s\n",
981  GNUNET_STATISTICS_set (stats,
982  "# average NAMESTORE PUT latency (μs)",
983  total_ns_latency.rel_value_us
984  / total_ns_latency_cnt,
985  GNUNET_NO);
986  }
987  }
988  /* compute and publish overall velocity */
989  if (0 == (total_reg_proc_dns_ns % 100))
990  {
991  struct GNUNET_TIME_Relative runtime;
992 
994  runtime = GNUNET_TIME_relative_subtract (runtime, idle_time);
995  runtime =
998  GNUNET_STATISTICS_set (stats,
999  "# Regular processing completed without NAMESTORE",
1001  GNUNET_NO);
1002  GNUNET_STATISTICS_set (stats,
1003  "# Regular processing completed with NAMESTORE PUT",
1005  GNUNET_NO);
1006  GNUNET_STATISTICS_set (stats,
1007  "# average request processing latency (μs)",
1008  runtime.rel_value_us,
1009  GNUNET_NO);
1010  GNUNET_STATISTICS_set (stats,
1011  "# total time spent idle (μs)",
1013  GNUNET_NO);
1014  }
1015 
1016  if (NULL == t)
1017  {
1020  }
1021 }
1022 
1023 
1031 static void
1032 process_result (void *cls,
1033  const struct GNUNET_TUN_DnsHeader *dns,
1034  size_t dns_len)
1035 {
1036  struct Request *req = cls;
1037  struct Record *rec;
1038  struct GNUNET_DNSPARSER_Packet *p;
1039  unsigned int rd_count;
1040 
1041  GNUNET_assert (NULL == req->hn);
1042  if (NULL == dns)
1043  {
1044  /* stub gave up */
1045  GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req);
1046  pending--;
1047  if (NULL == t)
1048  {
1051  }
1053  "Stub gave up on DNS reply for `%s'\n",
1054  req->hostname);
1055  GNUNET_STATISTICS_update (stats, "# DNS lookups timed out", 1, GNUNET_NO);
1056  if (req->issue_num > MAX_RETRIES)
1057  {
1058  failures++;
1059  free_request (req);
1060  GNUNET_STATISTICS_update (stats, "# requests given up on", 1, GNUNET_NO);
1061  return;
1062  }
1064  req->rs = NULL;
1065  insert_sorted (req);
1066  return;
1067  }
1068  if (req->id != dns->id)
1069  {
1071  "DNS ID did not match request, ignoring reply\n");
1072  GNUNET_STATISTICS_update (stats, "# DNS ID mismatches", 1, GNUNET_NO);
1073  return;
1074  }
1075  GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req);
1077  req->rs = NULL;
1078  pending--;
1079  p = GNUNET_DNSPARSER_parse ((const char *) dns, dns_len);
1080  if (NULL == p)
1081  {
1083  "Failed to parse DNS reply for `%s'\n",
1084  req->hostname);
1085  GNUNET_STATISTICS_update (stats, "# DNS parser errors", 1, GNUNET_NO);
1086  if (NULL == t)
1087  {
1090  }
1091  if (req->issue_num > MAX_RETRIES)
1092  {
1093  failures++;
1094  free_request (req);
1095  GNUNET_STATISTICS_update (stats, "# requests given up on", 1, GNUNET_NO);
1096  return;
1097  }
1098  insert_sorted (req);
1099  return;
1100  }
1101  /* import new records */
1102  req->issue_num = 0; /* success, reset counter! */
1103  {
1104  struct ProcessRecordContext prc = { .req = req, .p = p };
1105 
1106  for_all_records (p, &process_record, &prc);
1107  }
1109  /* count records found, determine minimum expiration time */
1111  {
1112  struct GNUNET_TIME_Relative dns_latency;
1113 
1114  dns_latency = GNUNET_TIME_absolute_get_duration (req->op_start_time);
1118  if (0 == (total_dns_latency_cnt % 1000))
1119  {
1120  GNUNET_STATISTICS_set (stats,
1121  "# average DNS lookup latency (μs)",
1124  GNUNET_NO);
1125  }
1126  }
1127  rd_count = 0;
1128  for (rec = req->rec_head; NULL != rec; rec = rec->next)
1129  {
1130  struct GNUNET_TIME_Absolute at;
1131 
1132  at.abs_value_us = rec->grd.expiration_time;
1133  req->expires = GNUNET_TIME_absolute_min (req->expires, at);
1134  rd_count++;
1135  }
1137  "Obtained %u records for `%s'\n",
1138  rd_count,
1139  req->hostname);
1140  /* Instead of going for SOA, simplified for now to look each
1141  day in case we got an empty response */
1142  if (0 == rd_count)
1143  {
1145  GNUNET_STATISTICS_update (stats,
1146  "# empty DNS replies (usually NXDOMAIN)",
1147  1,
1148  GNUNET_NO);
1149  }
1150  else
1151  {
1152  record_sets++;
1153  }
1154  /* convert records to namestore import format */
1155  {
1156  struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1157  unsigned int off = 0;
1158 
1159  /* convert linked list into array */
1160  for (rec = req->rec_head; NULL != rec; rec = rec->next)
1161  rd[off++] = rec->grd;
1162  pending_rs++;
1165  &req->zone->key,
1166  get_label (req),
1167  rd_count,
1168  rd,
1170  req);
1171  GNUNET_assert (NULL != req->qe);
1172  }
1173  insert_sorted (req);
1174 }
1175 
1176 
1182 static void
1183 process_queue (void *cls)
1184 {
1185  struct Request *req;
1186  unsigned int series;
1187  void *raw;
1188  size_t raw_size;
1189  struct GNUNET_TIME_Relative delay;
1190 
1191  (void) cls;
1194  series = 0;
1195  t = NULL;
1196  while (pending + pending_rs < THRESH)
1197  {
1198  req = GNUNET_CONTAINER_heap_peek (req_heap);
1199  if (NULL == req)
1200  break;
1201  if (NULL != req->qe)
1202  return; /* namestore op still pending */
1203  if (NULL != req->rs)
1204  {
1205  GNUNET_break (0);
1206  return; /* already submitted */
1207  }
1209  break;
1211  req->hn = NULL;
1212  GNUNET_CONTAINER_DLL_insert (req_head, req_tail, req);
1213  GNUNET_assert (NULL == req->rs);
1215  "Requesting resolution for `%s'\n",
1216  req->hostname);
1217  raw = build_dns_query (req, &raw_size);
1218  if (NULL == raw)
1219  {
1220  GNUNET_break (0);
1221  free_request (req);
1222  continue;
1223  }
1225  req->rs = GNUNET_DNSSTUB_resolve (ctx, raw, raw_size, &process_result, req);
1226  GNUNET_assert (NULL != req->rs);
1227  req->issue_num++;
1228  lookups++;
1229  pending++;
1230  series++;
1231  if (series > MAX_SERIES)
1232  break;
1233  }
1234  if (pending + pending_rs >= THRESH)
1235  {
1237  "Stopped processing queue (%u+%u/%u)]\n",
1238  pending,
1239  pending_rs,
1240  THRESH);
1241  return; /* wait for replies */
1242  }
1243  req = GNUNET_CONTAINER_heap_peek (req_heap);
1244  if (NULL == req)
1245  {
1247  "Stopped processing queue: empty queue\n");
1248  return;
1249  }
1251  {
1253  "Waiting until %s for next record (`%s') to expire\n",
1255  req->hostname);
1256  if (NULL != t)
1259  t = GNUNET_SCHEDULER_add_at (req->expires, &process_queue, NULL);
1260  return;
1261  }
1262  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Throttling\n");
1263  if (NULL != t)
1267 }
1268 
1269 
1279 static int
1280 free_request_it (void *cls, const struct GNUNET_HashCode *key, void *value)
1281 {
1282  struct Request *req = value;
1283 
1284  (void) cls;
1285  (void) key;
1286  free_request (req);
1287  return GNUNET_OK;
1288 }
1289 
1290 
1296 static void
1297 do_shutdown (void *cls)
1298 {
1299  struct Request *req;
1300  struct Zone *zone;
1301 
1302  (void) cls;
1303  if (NULL != id)
1304  {
1306  id = NULL;
1307  }
1308  if (NULL != t)
1309  {
1311  t = NULL;
1312  }
1313  while (NULL != (req = req_head))
1314  {
1315  GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req);
1316  if (NULL != req->qe)
1317  GNUNET_NAMESTORE_cancel (req->qe);
1318  free_request (req);
1319  }
1320  while (NULL != (req = GNUNET_CONTAINER_heap_remove_root (req_heap)))
1321  {
1322  req->hn = NULL;
1323  if (NULL != req->qe)
1324  GNUNET_NAMESTORE_cancel (req->qe);
1325  free_request (req);
1326  }
1327  if (NULL != zone_it)
1328  {
1330  zone_it = NULL;
1331  }
1332  if (NULL != ns)
1333  {
1335  ns = NULL;
1336  }
1337  if (NULL != ctx)
1338  {
1339  GNUNET_DNSSTUB_stop (ctx);
1340  ctx = NULL;
1341  }
1342  if (NULL != req_heap)
1343  {
1344  GNUNET_CONTAINER_heap_destroy (req_heap);
1345  req_heap = NULL;
1346  }
1347  if (NULL != ns_pending)
1348  {
1351  ns_pending = NULL;
1352  }
1353  while (NULL != (zone = zone_head))
1354  {
1355  GNUNET_CONTAINER_DLL_remove (zone_head, zone_tail, zone);
1356  GNUNET_free (zone->domain);
1357  GNUNET_free (zone);
1358  }
1359  if (NULL != stats)
1360  {
1362  stats = NULL;
1363  }
1364 }
1365 
1366 
1373 static void
1374 iterate_zones (void *cls);
1375 
1376 
1383 static void
1385 {
1386  struct Zone *zone = cls;
1387 
1389  "Failed to load data from namestore for zone `%s'\n",
1390  zone->domain);
1391  zone_it = NULL;
1393  iterate_zones (NULL);
1394 }
1395 
1396 
1406 static void
1408  const struct GNUNET_IDENTITY_PrivateKey *key,
1409  const char *label,
1410  unsigned int rd_count,
1411  const struct GNUNET_GNSRECORD_Data *rd)
1412 {
1413  struct Zone *zone = cls;
1414  struct Request *req;
1415  struct GNUNET_HashCode hc;
1416  char *fqdn;
1417 
1420  "Obtained NAMESTORE reply, %llu left in round\n",
1421  (unsigned long long) ns_iterator_trigger_next);
1422  if (0 == ns_iterator_trigger_next)
1423  {
1424  ns_iterator_trigger_next = NS_BATCH_SIZE;
1425  GNUNET_STATISTICS_update (stats,
1426  "# NAMESTORE records requested from cache",
1427  ns_iterator_trigger_next,
1428  GNUNET_NO);
1429  GNUNET_NAMESTORE_zone_iterator_next (zone_it, ns_iterator_trigger_next);
1430  }
1431  GNUNET_asprintf (&fqdn, "%s.%s", label, zone->domain);
1432  GNUNET_CRYPTO_hash (fqdn, strlen (fqdn) + 1, &hc);
1433  GNUNET_free (fqdn);
1434  req = GNUNET_CONTAINER_multihashmap_get (ns_pending, &hc);
1435  if (NULL == req)
1436  {
1438  "Ignoring record `%s' in zone `%s': not on my list!\n",
1439  label,
1440  zone->domain);
1441  return;
1442  }
1444  GNUNET_CONTAINER_multihashmap_remove (ns_pending, &hc, req));
1445  GNUNET_break (0 == GNUNET_memcmp (key, &req->zone->key));
1446  GNUNET_break (0 == strcasecmp (label, get_label (req)));
1447  for (unsigned int i = 0; i < rd_count; i++)
1448  {
1449  struct GNUNET_TIME_Absolute at;
1450 
1452  {
1453  struct GNUNET_TIME_Relative rel;
1454 
1455  rel.rel_value_us = rd->expiration_time;
1457  }
1458  else
1459  {
1460  at.abs_value_us = rd->expiration_time;
1461  }
1462  add_record (req, rd->record_type, at, rd->data, rd->data_size);
1463  }
1464  if (0 == rd_count)
1465  {
1467  "Empty record set in namestore for `%s'\n",
1468  req->hostname);
1469  }
1470  else
1471  {
1472  unsigned int pos = 0;
1473 
1474  cached++;
1476  for (struct Record *rec = req->rec_head; NULL != rec; rec = rec->next)
1477  {
1478  struct GNUNET_TIME_Absolute at;
1479 
1480  at.abs_value_us = rec->grd.expiration_time;
1481  req->expires = GNUNET_TIME_absolute_min (req->expires, at);
1482  pos++;
1483  }
1484  if (0 == pos)
1487  "Hot-start with %u existing records for `%s'\n",
1488  pos,
1489  req->hostname);
1490  }
1491  free_records (req);
1492 
1494  "Adding `%s' to worklist to start at %s\n",
1495  req->hostname,
1497  insert_sorted (req);
1498 }
1499 
1500 
1506 static void
1507 queue (const char *hostname)
1508 {
1509  struct Request *req;
1510  const char *dot;
1511  struct Zone *zone;
1512  size_t hlen;
1513  struct GNUNET_HashCode hc;
1514 
1515  if (GNUNET_OK != GNUNET_DNSPARSER_check_name (hostname))
1516  {
1518  "Refusing invalid hostname `%s'\n",
1519  hostname);
1520  rejects++;
1521  return;
1522  }
1523  dot = strchr (hostname, (unsigned char) '.');
1524  if (NULL == dot)
1525  {
1527  "Refusing invalid hostname `%s' (lacks '.')\n",
1528  hostname);
1529  rejects++;
1530  return;
1531  }
1532  for (zone = zone_head; NULL != zone; zone = zone->next)
1533  if (0 == strcmp (zone->domain, dot + 1))
1534  break;
1535  if (NULL == zone)
1536  {
1537  rejects++;
1539  "Domain name `%s' not in ego list!\n",
1540  dot + 1);
1541  return;
1542  }
1543 
1544  hlen = strlen (hostname) + 1;
1545  req = GNUNET_malloc (sizeof(struct Request) + hlen);
1546  req->zone = zone;
1547  req->hostname = (char *) &req[1];
1548  GNUNET_memcpy (req->hostname, hostname, hlen);
1550  UINT16_MAX);
1551  GNUNET_CRYPTO_hash (req->hostname, hlen, &hc);
1553  ns_pending,
1554  &hc,
1555  req,
1557  {
1559  "Duplicate hostname `%s' ignored\n",
1560  hostname);
1561  GNUNET_free (req);
1562  return;
1563  }
1564 }
1565 
1566 
1578 static int
1579 move_to_queue (void *cls, const struct GNUNET_HashCode *key, void *value)
1580 {
1581  struct Request *req = value;
1582 
1583  (void) cls;
1584  (void) key;
1585  insert_sorted (req);
1586  return GNUNET_OK;
1587 }
1588 
1589 
1596 static void
1597 iterate_zones (void *cls)
1598 {
1599  static struct Zone *last;
1600 
1601  (void) cls;
1602  if (NULL != zone_it)
1603  {
1604  zone_it = NULL;
1606  "Finished iteration over zone `%s'!\n",
1607  last->domain);
1608  /* subtract left-overs from previous iteration */
1609  GNUNET_STATISTICS_update (stats,
1610  "# NAMESTORE records requested from cache",
1611  (long long) (-ns_iterator_trigger_next),
1612  GNUNET_NO);
1614  }
1615  GNUNET_assert (NULL != zone_tail);
1616  if (zone_tail == last)
1617  {
1618  /* Done iterating over relevant zones in NAMESTORE, move
1619  rest of hash map to work queue as well. */
1621  "Finished all NAMESTORE iterations!\n");
1622  GNUNET_STATISTICS_set (stats,
1623  "# Domain names without cached reply",
1625  GNUNET_NO);
1628  ns_pending = NULL;
1630  total_reg_proc_dns = 0;
1632  return;
1633  }
1634  if (NULL == last)
1635  last = zone_head;
1636  else
1637  last = last->next;
1639  "Starting iteration over zone `%s'!\n",
1640  last->domain);
1641  /* subtract left-overs from previous iteration */
1642  GNUNET_STATISTICS_update (stats,
1643  "# NAMESTORE records requested from cache",
1644  1,
1645  GNUNET_NO);
1647  GNUNET_STATISTICS_update (stats, "# zones iterated", 1, GNUNET_NO);
1649  &last->key,
1651  NULL,
1653  last,
1654  &iterate_zones,
1655  NULL);
1656 }
1657 
1658 
1664 static void
1665 process_stdin (void *cls)
1666 {
1667  static struct GNUNET_TIME_Absolute last;
1668  static uint64_t idot;
1669  char hn[256];
1670 
1671  (void) cls;
1672  t = NULL;
1673  if (NULL != id)
1674  {
1676  id = NULL;
1677  }
1678  while (NULL != fgets (hn, sizeof(hn), stdin))
1679  {
1680  if (strlen (hn) > 0)
1681  hn[strlen (hn) - 1] = '\0'; /* eat newline */
1682  if (0 == idot)
1683  last = GNUNET_TIME_absolute_get ();
1684  idot++;
1685  if (0 == idot % 100000)
1686  {
1687  struct GNUNET_TIME_Relative delta;
1688 
1689  delta = GNUNET_TIME_absolute_get_duration (last);
1690  last = GNUNET_TIME_absolute_get ();
1691  fprintf (stderr,
1692  "Read 100000 domain names in %s\n",
1694  GNUNET_STATISTICS_set (stats, "# domain names provided", idot, GNUNET_NO);
1695  }
1696  queue (hn);
1697  }
1698  fprintf (stderr,
1699  "Done reading %llu domain names\n",
1700  (unsigned long long) idot);
1701  GNUNET_STATISTICS_set (stats, "# domain names provided", idot, GNUNET_NO);
1702  iterate_zones (NULL);
1703 }
1704 
1705 
1740 static void
1741 identity_cb (void *cls,
1742  struct GNUNET_IDENTITY_Ego *ego,
1743  void **ctx,
1744  const char *name)
1745 {
1746  (void) cls;
1747  (void) ctx;
1748 
1749  if (NULL == ego)
1750  {
1751  /* end of iteration */
1752  if (NULL == zone_head)
1753  {
1754  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No zone found\n");
1756  return;
1757  }
1758  /* zone_head non-null, process hostnames from stdin */
1760  return;
1761  }
1762  if (NULL != name)
1763  {
1764  struct Zone *zone;
1765 
1766  zone = GNUNET_new (struct Zone);
1768  zone->domain = GNUNET_strdup (name);
1769  GNUNET_CONTAINER_DLL_insert (zone_head, zone_tail, zone);
1770  }
1771 }
1772 
1773 
1783 static void
1784 run (void *cls,
1785  char *const *args,
1786  const char *cfgfile,
1787  const struct GNUNET_CONFIGURATION_Handle *cfg)
1788 {
1789  (void) cls;
1790  (void) args;
1791  (void) cfgfile;
1792  stats = GNUNET_STATISTICS_create ("zoneimport", cfg);
1795  if (NULL == ns_pending)
1796  {
1797  fprintf (stderr, "Failed to allocate memory for main hash map\n");
1798  return;
1799  }
1800  ctx = GNUNET_DNSSTUB_start (256);
1801  if (NULL == ctx)
1802  {
1803  fprintf (stderr, "Failed to initialize GNUnet DNS STUB\n");
1804  return;
1805  }
1806  if (NULL == args[0])
1807  {
1808  fprintf (stderr,
1809  "You must provide a list of DNS resolvers on the command line\n");
1810  return;
1811  }
1812  for (unsigned int i = 0; NULL != args[i]; i++)
1813  {
1814  if (GNUNET_OK != GNUNET_DNSSTUB_add_dns_ip (ctx, args[i]))
1815  {
1816  fprintf (stderr, "Failed to use `%s' for DNS resolver\n", args[i]);
1817  return;
1818  }
1819  }
1820 
1821 
1823  ns = GNUNET_NAMESTORE_connect (cfg);
1824  if (NULL == ns)
1825  {
1827  return;
1828  }
1829  id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL);
1830 }
1831 
1832 
1840 int
1841 main (int argc, char *const *argv)
1842 {
1843  struct GNUNET_GETOPT_CommandLineOption options[] =
1845  "size",
1846  "MAPSIZE",
1847  gettext_noop (
1848  "size to use for the main hash map"),
1849  &map_size),
1851  'm',
1852  "minimum-expiration",
1853  "RELATIVETIME",
1854  gettext_noop ("minimum expiration time we assume for imported records"),
1857  int ret;
1858 
1859  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1860  return 2;
1861  if (GNUNET_OK != (ret = GNUNET_PROGRAM_run (argc,
1862  argv,
1863  "gnunet-zoneimport",
1864  "import DNS zone into namestore",
1865  options,
1866  &run,
1867  NULL)))
1868  return ret;
1869  GNUNET_free_nz ((void *) argv);
1870  fprintf (stderr,
1871  "Rejected %u names, had %u cached, did %u lookups, stored %u record sets\n"
1872  "Found %u records, %u lookups failed, %u/%u pending on shutdown\n",
1873  rejects,
1874  cached,
1875  lookups,
1876  record_sets,
1877  records,
1878  failures,
1879  pending,
1880  pending_rs);
1881  return 0;
1882 }
1883 
1884 
1885 /* 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:610
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.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
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:79
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:1331
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:1459
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.
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:690
int GNUNET_DNSPARSER_pack(const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length)
Given a DNS packet p, generate the corresponding UDP payload.
Definition: dnsparser.c:1257
#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:591
int GNUNET_DNSPARSER_builder_add_srv(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SrvRecord *srv)
Add an SRV record to the UDP packet at the given location.
Definition: dnsparser.c:1118
uint16_t id
DNS ID (to match replies to requests).
A private key for an identity as per LSD0001.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static struct GNUNET_NAMESTORE_Handle * ns
Namestore handle.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:854
size_t data_size
Number of bytes in data.
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_store(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *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_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...
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:531
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.
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.
#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.
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:1269
Handle for an ego.
Definition: identity.h:36
#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.
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:656
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:564
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
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:95
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:1296
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:702
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.
struct GNUNET_IDENTITY_PrivateKey key
Private key of the zone.
union GNUNET_DNSPARSER_Record::@24 data
Payload of the record (which one of these is valid depends on the &#39;type&#39;).
Handle to a node in a heap.
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:921
int GNUNET_DNSPARSER_builder_add_soa(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SoaRecord *soa)
Add an SOA record to the UDP packet at the given location.
Definition: dnsparser.c:1077
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:604
A DNS response record.
Heap with the minimum cost at the root.
struct GNUNET_NAMESTORE_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *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 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:123
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:1030
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve(struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls)
Perform DNS resolution using our default IP from init.
Definition: dnsstub.c:504
#define THRESH
Maximum number of queries pending at the same time.
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.
#define GNUNET_free_nz(ptr)
Wrapper around free.
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.
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:1001
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.
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:79
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 void ns_lookup_result_cb(void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process a record that was stored in the namestore.
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:579
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:84
struct Record * prev
Kept in a DLL.
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition: dnsstub.c:540
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
const char * name
struct Zone * next
Kept in a DLL.
const struct GNUNET_IDENTITY_PrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:639
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:375
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:372
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:527
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.
static unsigned int lookups
Number of lookups we performed overall.
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
This expiration time of the record is a relative time (not an absolute time).
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:758
UDP socket we are using for sending DNS requests to the Internet.
Definition: dnsstub.c:44
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:1246
static void process_queue(void *cls)
Process as many requests as possible from the queue.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
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:972
Some zones may include authoritative records for other zones, such as foo.com.uk or bar...