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_CRYPTO_EcdsaPrivateKey *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 ((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:527
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: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:1300
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:1438
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
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:555
uint16_t id
DNS ID (to match replies to requests).
#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
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
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:526
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:1253
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.
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:1280
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:687
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.
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:837
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.
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.
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.
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:76
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 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:85
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.
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:367
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.
#define GNUNET_YES
Definition: gnunet_common.h:77
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.
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:742
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:1230
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:966
Some zones may include authoritative records for other zones, such as foo.com.uk or bar...