GNUnet  0.10.x
gnunet-zoneimport.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2018 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
25 #include "platform.h"
26 #include <gnunet_util_lib.h>
27 #include <gnunet_dnsstub_lib.h>
28 #include <gnunet_dnsparser_lib.h>
29 #include <gnunet_gnsrecord_lib.h>
33 
34 
38 #define THRESH 100
39 
44 #define TIME_THRESH 10
45 
49 #define MAX_RETRIES 5
50 
54 #define MAX_SERIES 10
55 
59 #define SERIES_DELAY \
60  GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MICROSECONDS, 10)
61 
66 
71 #define NS_BATCH_SIZE 1024
72 
79 struct Zone {
83  struct Zone *next;
84 
88  struct Zone *prev;
89 
93  char *domain;
94 
99 };
100 
101 
105 struct Record {
109  struct Record *next;
110 
114  struct Record *prev;
115 
120 };
121 
122 
128 struct Request {
133 
137  struct Request *next;
138 
142  struct Request *prev;
143 
148  struct Record *rec_head;
149 
154  struct Record *rec_tail;
155 
159  struct GNUNET_DNSSTUB_RequestSocket *rs;
160 
166  char *hostname;
167 
172 
176  const struct Zone *zone;
177 
183  struct GNUNET_TIME_Absolute expires;
184 
191  struct GNUNET_TIME_Absolute op_start_time;
192 
197  unsigned int issue_num;
198 
202  uint16_t id;
203 };
204 
205 
212 static unsigned int map_size = 1024;
213 
217 static struct GNUNET_IDENTITY_Handle *id;
218 
223 
228 
233 
237 static unsigned int pending;
238 
242 static unsigned int pending_rs;
243 
247 static unsigned int lookups;
248 
252 static unsigned int cached;
253 
257 static unsigned int rejects;
258 
262 static unsigned int failures;
263 
267 static unsigned int records;
268 
272 static unsigned int record_sets;
273 
279 
283 static struct Request *req_head;
284 
288 static struct Request *req_tail;
289 
293 static struct GNUNET_SCHEDULER_Task *t;
294 
301 
306 
310 static struct Zone *zone_head;
311 
315 static struct Zone *zone_tail;
316 
321 static uint64_t ns_iterator_trigger_next;
322 
326 static uint64_t total_dns_latency_cnt;
327 
332 
336 static uint64_t total_reg_proc_dns;
337 
341 static uint64_t total_reg_proc_dns_ns;
342 
347 
352 
357 
358 
365 typedef void (*RecordProcessor) (void *cls,
366  const struct GNUNET_DNSPARSER_Record *rec);
367 
368 
377 static void
380  void *rp_cls)
381 {
382  for (unsigned int i = 0; i < p->num_answers; i++)
383  {
384  struct GNUNET_DNSPARSER_Record *rs = &p->answers[i];
385 
386  rp(rp_cls, rs);
387  }
388  for (unsigned int i = 0; i < p->num_authority_records; i++)
389  {
390  struct GNUNET_DNSPARSER_Record *rs = &p->authority_records[i];
391 
392  rp(rp_cls, rs);
393  }
394  for (unsigned int i = 0; i < p->num_additional_records; i++)
395  {
396  struct GNUNET_DNSPARSER_Record *rs = &p->additional_records[i];
397 
398  rp(rp_cls, rs);
399  }
400 }
401 
402 
410 static const char *
411 get_label(struct Request *req)
412 {
413  static char label[64];
414  const char *dot;
415 
416  dot = strchr(req->hostname, (unsigned char)'.');
417  if (NULL == dot)
418  {
419  GNUNET_break(0);
420  return NULL;
421  }
422  if (((size_t)(dot - req->hostname)) >= sizeof(label))
423  {
424  GNUNET_break(0);
425  return NULL;
426  }
427  GNUNET_memcpy(label, req->hostname, dot - req->hostname);
428  label[dot - req->hostname] = '\0';
429  return label;
430 }
431 
432 
441 static void *
442 build_dns_query(struct Request *req, size_t *raw_size)
443 {
444  static char raw[512];
445  char *rawp;
446  struct GNUNET_DNSPARSER_Packet p;
447  struct GNUNET_DNSPARSER_Query q;
448  int ret;
449 
450  q.name = (char *)req->hostname;
453 
454  memset(&p, 0, sizeof(p));
455  p.num_queries = 1;
456  p.queries = &q;
457  p.id = req->id;
458  ret = GNUNET_DNSPARSER_pack(&p, UINT16_MAX, &rawp, raw_size);
459  if (GNUNET_OK != ret)
460  {
461  if (GNUNET_NO == ret)
462  GNUNET_free(rawp);
464  "Failed to pack query for hostname `%s'\n",
465  req->hostname);
466  rejects++;
467  return NULL;
468  }
469  if (*raw_size > sizeof(raw))
470  {
472  "Failed to pack query for hostname `%s'\n",
473  req->hostname);
474  rejects++;
475  GNUNET_break(0);
476  GNUNET_free(rawp);
477  return NULL;
478  }
479  GNUNET_memcpy(raw, rawp, *raw_size);
480  GNUNET_free(rawp);
481  return raw;
482 }
483 
484 
490 static void
491 free_records(struct Request *req)
492 {
493  struct Record *rec;
494 
495  /* Free records */
496  while (NULL != (rec = req->rec_head))
497  {
499  GNUNET_free(rec);
500  }
501 }
502 
503 
509 static void
510 free_request(struct Request *req)
511 {
512  free_records(req);
513  GNUNET_free(req);
514 }
515 
516 
522 static void
523 process_queue(void *cls);
524 
525 
531 static void
532 insert_sorted(struct Request *req)
533 {
534  req->hn =
536  if (req == GNUNET_CONTAINER_heap_peek(req_heap))
537  {
538  if (NULL != t)
542  }
543 }
544 
545 
555 static void
556 add_record(struct Request *req,
557  uint32_t type,
558  struct GNUNET_TIME_Absolute expiration_time,
559  const void *data,
560  size_t data_len)
561 {
562  struct Record *rec;
563 
564  rec = GNUNET_malloc(sizeof(struct Record) + data_len);
565  rec->grd.data = &rec[1];
566  rec->grd.expiration_time = expiration_time.abs_value_us;
567  rec->grd.data_size = data_len;
568  rec->grd.record_type = type;
570  GNUNET_memcpy(&rec[1], data, data_len);
572 }
573 
574 
578 struct GlueClosure {
582  struct Request *req;
583 
587  const char *ns;
588 
592  int found;
593 };
594 
595 
602 static void
603 check_for_glue(void *cls, const struct GNUNET_DNSPARSER_Record *rec)
604 {
605  struct GlueClosure *gc = cls;
606  char dst[65536];
607  size_t dst_len;
608  size_t off;
609  char ip[INET6_ADDRSTRLEN + 1];
610  socklen_t ip_size = (socklen_t)sizeof(ip);
611  struct GNUNET_TIME_Absolute expiration_time;
612  struct GNUNET_TIME_Relative left;
613 
614  if (0 != strcasecmp(rec->name, gc->ns))
615  return;
616  expiration_time = rec->expiration_time;
617  left = GNUNET_TIME_absolute_get_remaining(expiration_time);
618  if (0 == left.rel_value_us)
619  return; /* ignore expired glue records */
620  /* if expiration window is too short, bump it to configured minimum */
622  expiration_time =
624  dst_len = sizeof(dst);
625  off = 0;
626  switch (rec->type)
627  {
629  if (sizeof(struct in_addr) != rec->data.raw.data_len)
630  {
631  GNUNET_break(0);
632  return;
633  }
634  if (NULL == inet_ntop(AF_INET, rec->data.raw.data, ip, ip_size))
635  {
636  GNUNET_break(0);
637  return;
638  }
640  dst_len,
641  &off,
642  gc->req->hostname)) &&
643  (GNUNET_OK ==
644  GNUNET_DNSPARSER_builder_add_name(dst, dst_len, &off, ip)))
645  {
646  add_record(gc->req,
648  expiration_time,
649  dst,
650  off);
651  gc->found = GNUNET_YES;
652  }
653  break;
654 
656  if (sizeof(struct in6_addr) != rec->data.raw.data_len)
657  {
658  GNUNET_break(0);
659  return;
660  }
661  if (NULL == inet_ntop(AF_INET6, rec->data.raw.data, ip, ip_size))
662  {
663  GNUNET_break(0);
664  return;
665  }
667  dst_len,
668  &off,
669  gc->req->hostname)) &&
670  (GNUNET_OK ==
671  GNUNET_DNSPARSER_builder_add_name(dst, dst_len, &off, ip)))
672  {
673  add_record(gc->req,
675  expiration_time,
676  dst,
677  off);
678  gc->found = GNUNET_YES;
679  }
680  break;
681 
684  dst_len,
685  &off,
686  gc->req->hostname)) &&
688  dst_len,
689  &off,
690  rec->data.hostname)))
691  {
692  add_record(gc->req,
694  expiration_time,
695  dst,
696  off);
697  gc->found = GNUNET_YES;
698  }
699  break;
700 
701  default:
702  /* useless, do nothing */
703  break;
704  }
705 }
706 
707 
717 
721  struct Request *req;
722 };
723 
724 
731 static void
732 process_record(void *cls, const struct GNUNET_DNSPARSER_Record *rec)
733 {
734  struct ProcessRecordContext *prc = cls;
735  struct Request *req = prc->req;
736  char dst[65536];
737  size_t dst_len;
738  size_t off;
739  struct GNUNET_TIME_Absolute expiration_time;
740  struct GNUNET_TIME_Relative left;
741 
742  dst_len = sizeof(dst);
743  off = 0;
744  records++;
745  if (0 != strcasecmp(rec->name, req->hostname))
746  {
747  GNUNET_log(
749  "DNS returned record from zone `%s' of type %u while resolving `%s'\n",
750  rec->name,
751  (unsigned int)rec->type,
752  req->hostname);
753  return; /* does not match hostname, might be glue, but
754  not useful for this pass! */
755  }
756  expiration_time = rec->expiration_time;
757  left = GNUNET_TIME_absolute_get_remaining(expiration_time);
758  if (0 == left.rel_value_us)
759  {
761  "DNS returned expired record for `%s'\n",
762  req->hostname);
764  "# expired records obtained from DNS",
765  1,
766  GNUNET_NO);
767  return; /* record expired */
768  }
769 
771  "DNS returned record that expires at %s for `%s'\n",
773  req->hostname);
774  /* if expiration window is too short, bump it to configured minimum */
776  expiration_time =
778  switch (rec->type)
779  {
781  struct GlueClosure gc;
782 
783  /* check for glue */
784  gc.req = req;
785  gc.ns = rec->data.hostname;
786  gc.found = GNUNET_NO;
787  for_all_records(prc->p, &check_for_glue, &gc);
788  if ((GNUNET_NO == gc.found) &&
790  dst_len,
791  &off,
792  req->hostname)) &&
794  dst_len,
795  &off,
796  rec->data.hostname)))
797  {
798  /* FIXME: actually check if this is out-of-bailiwick,
799  and if not request explicit resolution... */
801  "Converted OOB (`%s') NS record for `%s'\n",
802  rec->data.hostname,
803  rec->name);
804  add_record(req,
806  expiration_time,
807  dst,
808  off);
809  }
810  else
811  {
813  "Converted NS record for `%s' using glue\n",
814  rec->name);
815  }
816  break;
817  }
818 
821  dst_len,
822  &off,
823  rec->data.hostname))
824  {
826  "Converting CNAME (`%s') record for `%s'\n",
827  rec->data.hostname,
828  rec->name);
829  add_record(req, rec->type, expiration_time, dst, off);
830  }
831  break;
832 
834  /* No support for DNAME in GNS yet! FIXME: support later! */
836  "FIXME: not supported: %s DNAME %s\n",
837  rec->name,
838  rec->data.hostname);
839  break;
840 
842  if (GNUNET_OK ==
843  GNUNET_DNSPARSER_builder_add_mx(dst, dst_len, &off, rec->data.mx))
844  {
846  "Converting MX (`%s') record for `%s'\n",
847  rec->data.mx->mxhost,
848  rec->name);
849  add_record(req, rec->type, expiration_time, dst, off);
850  }
851  break;
852 
854  if (GNUNET_OK ==
855  GNUNET_DNSPARSER_builder_add_soa(dst, dst_len, &off, rec->data.soa))
856  {
857  /* NOTE: GNS does not really use SOAs */
859  "Converting SOA record for `%s'\n",
860  rec->name);
861  add_record(req, rec->type, expiration_time, dst, off);
862  }
863  break;
864 
866  if (GNUNET_OK ==
867  GNUNET_DNSPARSER_builder_add_srv(dst, dst_len, &off, rec->data.srv))
868  {
870  "Converting SRV record for `%s'\n",
871  rec->name);
872  add_record(req, rec->type, expiration_time, dst, off);
873  }
874  break;
875 
878  dst_len,
879  &off,
880  rec->data.hostname))
881  {
882  /* !?: what does a PTR record do in a regular TLD??? */
884  "Converting PTR record for `%s' (weird)\n",
885  rec->name);
886  add_record(req, rec->type, expiration_time, dst, off);
887  }
888  break;
889 
891  if (GNUNET_OK ==
892  GNUNET_DNSPARSER_builder_add_cert(dst, dst_len, &off, rec->data.cert))
893  {
895  "Converting CERT record for `%s'\n",
896  rec->name);
897  add_record(req, rec->type, expiration_time, dst, off);
898  }
899  break;
900 
901  /* Rest is 'raw' encoded and just needs to be copied IF
902  the hostname matches the requested name; otherwise we
903  simply cannot use it. */
907  default:
909  "Converting record of type %u for `%s'\n",
910  (unsigned int)rec->type,
911  rec->name);
912  add_record(req,
913  rec->type,
914  expiration_time,
915  rec->data.raw.data,
916  rec->data.raw.data_len);
917  break;
918  }
919 }
920 
921 
932 static void
933 store_completed_cb(void *cls, int32_t success, const char *emsg)
934 {
935  static struct GNUNET_TIME_Absolute last;
936  struct Request *req = cls;
937 
938  req->qe = NULL;
939  if (GNUNET_SYSERR == success)
940  {
942  "Failed to store zone data for `%s': %s\n",
943  req->hostname,
944  emsg);
945  }
946  else
947  {
949  "Stored records under `%s' (%d)\n",
950  req->hostname,
951  success);
952  }
953  total_reg_proc_dns_ns++; /* finished regular processing */
954  pending_rs--;
955  free_records(req);
956  /* compute NAMESTORE statistics */
957  {
958  static uint64_t total_ns_latency_cnt;
959  static struct GNUNET_TIME_Relative total_ns_latency;
960  struct GNUNET_TIME_Relative ns_latency;
961 
963  total_ns_latency = GNUNET_TIME_relative_add(total_ns_latency, ns_latency);
964  if (0 == total_ns_latency_cnt)
965  last = GNUNET_TIME_absolute_get();
966  total_ns_latency_cnt++;
967  if (0 == (total_ns_latency_cnt % 1000))
968  {
969  struct GNUNET_TIME_Relative delta;
970 
971  delta = GNUNET_TIME_absolute_get_duration(last);
972  last = GNUNET_TIME_absolute_get();
973  fprintf(stderr,
974  "Processed 1000 records in %s\n",
976  GNUNET_STATISTICS_set(stats,
977  "# average NAMESTORE PUT latency (μs)",
978  total_ns_latency.rel_value_us /
979  total_ns_latency_cnt,
980  GNUNET_NO);
981  }
982  }
983  /* compute and publish overall velocity */
984  if (0 == (total_reg_proc_dns_ns % 100))
985  {
986  struct GNUNET_TIME_Relative runtime;
987 
989  runtime = GNUNET_TIME_relative_subtract(runtime, idle_time);
990  runtime =
993  GNUNET_STATISTICS_set(stats,
994  "# Regular processing completed without NAMESTORE",
996  GNUNET_NO);
997  GNUNET_STATISTICS_set(stats,
998  "# Regular processing completed with NAMESTORE PUT",
1000  GNUNET_NO);
1001  GNUNET_STATISTICS_set(stats,
1002  "# average request processing latency (μs)",
1003  runtime.rel_value_us,
1004  GNUNET_NO);
1005  GNUNET_STATISTICS_set(stats,
1006  "# total time spent idle (μs)",
1008  GNUNET_NO);
1009  }
1010 
1011  if (NULL == t)
1012  {
1015  }
1016 }
1017 
1018 
1026 static void
1027 process_result(void *cls,
1028  const struct GNUNET_TUN_DnsHeader *dns,
1029  size_t dns_len)
1030 {
1031  struct Request *req = cls;
1032  struct Record *rec;
1033  struct GNUNET_DNSPARSER_Packet *p;
1034  unsigned int rd_count;
1035 
1036  GNUNET_assert(NULL == req->hn);
1037  if (NULL == dns)
1038  {
1039  /* stub gave up */
1040  GNUNET_CONTAINER_DLL_remove(req_head, req_tail, req);
1041  pending--;
1042  if (NULL == t)
1043  {
1046  }
1048  "Stub gave up on DNS reply for `%s'\n",
1049  req->hostname);
1050  GNUNET_STATISTICS_update(stats, "# DNS lookups timed out", 1, GNUNET_NO);
1051  if (req->issue_num > MAX_RETRIES)
1052  {
1053  failures++;
1054  free_request(req);
1055  GNUNET_STATISTICS_update(stats, "# requests given up on", 1, GNUNET_NO);
1056  return;
1057  }
1059  req->rs = NULL;
1060  insert_sorted(req);
1061  return;
1062  }
1063  if (req->id != dns->id)
1064  {
1066  "DNS ID did not match request, ignoring reply\n");
1067  GNUNET_STATISTICS_update(stats, "# DNS ID mismatches", 1, GNUNET_NO);
1068  return;
1069  }
1070  GNUNET_CONTAINER_DLL_remove(req_head, req_tail, req);
1072  req->rs = NULL;
1073  pending--;
1074  p = GNUNET_DNSPARSER_parse((const char *)dns, dns_len);
1075  if (NULL == p)
1076  {
1078  "Failed to parse DNS reply for `%s'\n",
1079  req->hostname);
1080  GNUNET_STATISTICS_update(stats, "# DNS parser errors", 1, GNUNET_NO);
1081  if (NULL == t)
1082  {
1085  }
1086  if (req->issue_num > MAX_RETRIES)
1087  {
1088  failures++;
1089  free_request(req);
1090  GNUNET_STATISTICS_update(stats, "# requests given up on", 1, GNUNET_NO);
1091  return;
1092  }
1093  insert_sorted(req);
1094  return;
1095  }
1096  /* import new records */
1097  req->issue_num = 0; /* success, reset counter! */
1098  {
1099  struct ProcessRecordContext prc = { .req = req, .p = p };
1100 
1101  for_all_records(p, &process_record, &prc);
1102  }
1104  /* count records found, determine minimum expiration time */
1106  {
1107  struct GNUNET_TIME_Relative dns_latency;
1108 
1113  if (0 == (total_dns_latency_cnt % 1000))
1114  {
1115  GNUNET_STATISTICS_set(stats,
1116  "# average DNS lookup latency (μs)",
1119  GNUNET_NO);
1120  }
1121  }
1122  rd_count = 0;
1123  for (rec = req->rec_head; NULL != rec; rec = rec->next)
1124  {
1125  struct GNUNET_TIME_Absolute at;
1126 
1127  at.abs_value_us = rec->grd.expiration_time;
1128  req->expires = GNUNET_TIME_absolute_min(req->expires, at);
1129  rd_count++;
1130  }
1132  "Obtained %u records for `%s'\n",
1133  rd_count,
1134  req->hostname);
1135  /* Instead of going for SOA, simplified for now to look each
1136  day in case we got an empty response */
1137  if (0 == rd_count)
1138  {
1141  "# empty DNS replies (usually NXDOMAIN)",
1142  1,
1143  GNUNET_NO);
1144  }
1145  else
1146  {
1147  record_sets++;
1148  }
1149  /* convert records to namestore import format */
1150  {
1151  struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(rd_count)];
1152  unsigned int off = 0;
1153 
1154  /* convert linked list into array */
1155  for (rec = req->rec_head; NULL != rec; rec = rec->next)
1156  rd[off++] = rec->grd;
1157  pending_rs++;
1160  &req->zone->key,
1161  get_label(req),
1162  rd_count,
1163  rd,
1165  req);
1166  GNUNET_assert(NULL != req->qe);
1167  }
1168  insert_sorted(req);
1169 }
1170 
1171 
1177 static void
1178 process_queue(void *cls)
1179 {
1180  struct Request *req;
1181  unsigned int series;
1182  void *raw;
1183  size_t raw_size;
1184  struct GNUNET_TIME_Relative delay;
1185 
1186  (void)cls;
1189  series = 0;
1190  t = NULL;
1191  while (pending + pending_rs < THRESH)
1192  {
1193  req = GNUNET_CONTAINER_heap_peek(req_heap);
1194  if (NULL == req)
1195  break;
1196  if (NULL != req->qe)
1197  return; /* namestore op still pending */
1198  if (NULL != req->rs)
1199  {
1200  GNUNET_break(0);
1201  return; /* already submitted */
1202  }
1204  break;
1206  req->hn = NULL;
1207  GNUNET_CONTAINER_DLL_insert(req_head, req_tail, req);
1208  GNUNET_assert(NULL == req->rs);
1210  "Requesting resolution for `%s'\n",
1211  req->hostname);
1212  raw = build_dns_query(req, &raw_size);
1213  if (NULL == raw)
1214  {
1215  GNUNET_break(0);
1216  free_request(req);
1217  continue;
1218  }
1220  req->rs = GNUNET_DNSSTUB_resolve(ctx, raw, raw_size, &process_result, req);
1221  GNUNET_assert(NULL != req->rs);
1222  req->issue_num++;
1223  lookups++;
1224  pending++;
1225  series++;
1226  if (series > MAX_SERIES)
1227  break;
1228  }
1229  if (pending + pending_rs >= THRESH)
1230  {
1232  "Stopped processing queue (%u+%u/%u)]\n",
1233  pending,
1234  pending_rs,
1235  THRESH);
1236  return; /* wait for replies */
1237  }
1238  req = GNUNET_CONTAINER_heap_peek(req_heap);
1239  if (NULL == req)
1240  {
1242  "Stopped processing queue: empty queue\n");
1243  return;
1244  }
1246  {
1248  "Waiting until %s for next record (`%s') to expire\n",
1250  req->hostname);
1251  if (NULL != t)
1254  t = GNUNET_SCHEDULER_add_at(req->expires, &process_queue, NULL);
1255  return;
1256  }
1257  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Throttling\n");
1258  if (NULL != t)
1262 }
1263 
1264 
1274 static int
1275 free_request_it(void *cls, const struct GNUNET_HashCode *key, void *value)
1276 {
1277  struct Request *req = value;
1278 
1279  (void)cls;
1280  (void)key;
1281  free_request(req);
1282  return GNUNET_OK;
1283 }
1284 
1285 
1291 static void
1292 do_shutdown(void *cls)
1293 {
1294  struct Request *req;
1295  struct Zone *zone;
1296 
1297  (void)cls;
1298  if (NULL != id)
1299  {
1301  id = NULL;
1302  }
1303  if (NULL != t)
1304  {
1306  t = NULL;
1307  }
1308  while (NULL != (req = req_head))
1309  {
1310  GNUNET_CONTAINER_DLL_remove(req_head, req_tail, req);
1311  if (NULL != req->qe)
1313  free_request(req);
1314  }
1315  while (NULL != (req = GNUNET_CONTAINER_heap_remove_root(req_heap)))
1316  {
1317  req->hn = NULL;
1318  if (NULL != req->qe)
1320  free_request(req);
1321  }
1322  if (NULL != zone_it)
1323  {
1325  zone_it = NULL;
1326  }
1327  if (NULL != ns)
1328  {
1330  ns = NULL;
1331  }
1332  if (NULL != ctx)
1333  {
1334  GNUNET_DNSSTUB_stop(ctx);
1335  ctx = NULL;
1336  }
1337  if (NULL != req_heap)
1338  {
1340  req_heap = NULL;
1341  }
1342  if (NULL != ns_pending)
1343  {
1346  ns_pending = NULL;
1347  }
1348  while (NULL != (zone = zone_head))
1349  {
1350  GNUNET_CONTAINER_DLL_remove(zone_head, zone_tail, zone);
1351  GNUNET_free(zone->domain);
1352  GNUNET_free(zone);
1353  }
1354  if (NULL != stats)
1355  {
1357  stats = NULL;
1358  }
1359 }
1360 
1361 
1368 static void
1369 iterate_zones(void *cls);
1370 
1371 
1378 static void
1380 {
1381  struct Zone *zone = cls;
1382 
1384  "Failed to load data from namestore for zone `%s'\n",
1385  zone->domain);
1386  zone_it = NULL;
1388  iterate_zones(NULL);
1389 }
1390 
1391 
1401 static void
1403  const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
1404  const char *label,
1405  unsigned int rd_count,
1406  const struct GNUNET_GNSRECORD_Data *rd)
1407 {
1408  struct Zone *zone = cls;
1409  struct Request *req;
1410  struct GNUNET_HashCode hc;
1411  char *fqdn;
1412 
1415  "Obtained NAMESTORE reply, %llu left in round\n",
1416  (unsigned long long)ns_iterator_trigger_next);
1417  if (0 == ns_iterator_trigger_next)
1418  {
1419  ns_iterator_trigger_next = NS_BATCH_SIZE;
1421  "# NAMESTORE records requested from cache",
1422  ns_iterator_trigger_next,
1423  GNUNET_NO);
1424  GNUNET_NAMESTORE_zone_iterator_next(zone_it, ns_iterator_trigger_next);
1425  }
1426  GNUNET_asprintf(&fqdn, "%s.%s", label, zone->domain);
1427  GNUNET_CRYPTO_hash(fqdn, strlen(fqdn) + 1, &hc);
1428  GNUNET_free(fqdn);
1429  req = GNUNET_CONTAINER_multihashmap_get(ns_pending, &hc);
1430  if (NULL == req)
1431  {
1433  "Ignoring record `%s' in zone `%s': not on my list!\n",
1434  label,
1435  zone->domain);
1436  return;
1437  }
1439  GNUNET_CONTAINER_multihashmap_remove(ns_pending, &hc, req));
1440  GNUNET_break(0 == GNUNET_memcmp(key, &req->zone->key));
1441  GNUNET_break(0 == strcasecmp(label, get_label(req)));
1442  for (unsigned int i = 0; i < rd_count; i++)
1443  {
1444  struct GNUNET_TIME_Absolute at;
1445 
1447  {
1448  struct GNUNET_TIME_Relative rel;
1449 
1450  rel.rel_value_us = rd->expiration_time;
1452  }
1453  else
1454  {
1455  at.abs_value_us = rd->expiration_time;
1456  }
1457  add_record(req, rd->record_type, at, rd->data, rd->data_size);
1458  }
1459  if (0 == rd_count)
1460  {
1462  "Empty record set in namestore for `%s'\n",
1463  req->hostname);
1464  }
1465  else
1466  {
1467  unsigned int pos = 0;
1468 
1469  cached++;
1471  for (struct Record *rec = req->rec_head; NULL != rec; rec = rec->next)
1472  {
1473  struct GNUNET_TIME_Absolute at;
1474 
1475  at.abs_value_us = rec->grd.expiration_time;
1476  req->expires = GNUNET_TIME_absolute_min(req->expires, at);
1477  pos++;
1478  }
1479  if (0 == pos)
1482  "Hot-start with %u existing records for `%s'\n",
1483  pos,
1484  req->hostname);
1485  }
1486  free_records(req);
1487 
1489  "Adding `%s' to worklist to start at %s\n",
1490  req->hostname,
1492  insert_sorted(req);
1493 }
1494 
1495 
1501 static void
1502 queue(const char *hostname)
1503 {
1504  struct Request *req;
1505  const char *dot;
1506  struct Zone *zone;
1507  size_t hlen;
1508  struct GNUNET_HashCode hc;
1509 
1510  if (GNUNET_OK != GNUNET_DNSPARSER_check_name(hostname))
1511  {
1513  "Refusing invalid hostname `%s'\n",
1514  hostname);
1515  rejects++;
1516  return;
1517  }
1518  dot = strchr(hostname, (unsigned char)'.');
1519  if (NULL == dot)
1520  {
1522  "Refusing invalid hostname `%s' (lacks '.')\n",
1523  hostname);
1524  rejects++;
1525  return;
1526  }
1527  for (zone = zone_head; NULL != zone; zone = zone->next)
1528  if (0 == strcmp(zone->domain, dot + 1))
1529  break;
1530  if (NULL == zone)
1531  {
1532  rejects++;
1534  "Domain name `%s' not in ego list!\n",
1535  dot + 1);
1536  return;
1537  }
1538 
1539  hlen = strlen(hostname) + 1;
1540  req = GNUNET_malloc(sizeof(struct Request) + hlen);
1541  req->zone = zone;
1542  req->hostname = (char *)&req[1];
1543  GNUNET_memcpy(req->hostname, hostname, hlen);
1545  UINT16_MAX);
1546  GNUNET_CRYPTO_hash(req->hostname, hlen, &hc);
1548  ns_pending,
1549  &hc,
1550  req,
1552  {
1554  "Duplicate hostname `%s' ignored\n",
1555  hostname);
1556  GNUNET_free(req);
1557  return;
1558  }
1559 }
1560 
1561 
1573 static int
1574 move_to_queue(void *cls, const struct GNUNET_HashCode *key, void *value)
1575 {
1576  struct Request *req = value;
1577 
1578  (void)cls;
1579  (void)key;
1580  insert_sorted(req);
1581  return GNUNET_OK;
1582 }
1583 
1584 
1591 static void
1592 iterate_zones(void *cls)
1593 {
1594  static struct Zone *last;
1595 
1596  (void)cls;
1597  if (NULL != zone_it)
1598  {
1599  zone_it = NULL;
1601  "Finished iteration over zone `%s'!\n",
1602  last->domain);
1603  /* subtract left-overs from previous iteration */
1605  "# NAMESTORE records requested from cache",
1606  (long long)(-ns_iterator_trigger_next),
1607  GNUNET_NO);
1609  }
1610  GNUNET_assert(NULL != zone_tail);
1611  if (zone_tail == last)
1612  {
1613  /* Done iterating over relevant zones in NAMESTORE, move
1614  rest of hash map to work queue as well. */
1616  "Finished all NAMESTORE iterations!\n");
1617  GNUNET_STATISTICS_set(stats,
1618  "# Domain names without cached reply",
1620  GNUNET_NO);
1623  ns_pending = NULL;
1625  total_reg_proc_dns = 0;
1627  return;
1628  }
1629  if (NULL == last)
1630  last = zone_head;
1631  else
1632  last = last->next;
1634  "Starting iteration over zone `%s'!\n",
1635  last->domain);
1636  /* subtract left-overs from previous iteration */
1638  "# NAMESTORE records requested from cache",
1639  1,
1640  GNUNET_NO);
1642  GNUNET_STATISTICS_update(stats, "# zones iterated", 1, GNUNET_NO);
1644  &last->key,
1646  NULL,
1648  last,
1649  &iterate_zones,
1650  NULL);
1651 }
1652 
1653 
1659 static void
1660 process_stdin(void *cls)
1661 {
1662  static struct GNUNET_TIME_Absolute last;
1663  static uint64_t idot;
1664  char hn[256];
1665 
1666  (void)cls;
1667  t = NULL;
1668  if (NULL != id)
1669  {
1671  id = NULL;
1672  }
1673  while (NULL != fgets(hn, sizeof(hn), stdin))
1674  {
1675  if (strlen(hn) > 0)
1676  hn[strlen(hn) - 1] = '\0'; /* eat newline */
1677  if (0 == idot)
1678  last = GNUNET_TIME_absolute_get();
1679  idot++;
1680  if (0 == idot % 100000)
1681  {
1682  struct GNUNET_TIME_Relative delta;
1683 
1684  delta = GNUNET_TIME_absolute_get_duration(last);
1685  last = GNUNET_TIME_absolute_get();
1686  fprintf(stderr,
1687  "Read 100000 domain names in %s\n",
1689  GNUNET_STATISTICS_set(stats, "# domain names provided", idot, GNUNET_NO);
1690  }
1691  queue(hn);
1692  }
1693  fprintf(stderr,
1694  "Done reading %llu domain names\n",
1695  (unsigned long long)idot);
1696  GNUNET_STATISTICS_set(stats, "# domain names provided", idot, GNUNET_NO);
1697  iterate_zones(NULL);
1698 }
1699 
1700 
1735 static void
1736 identity_cb(void *cls,
1737  struct GNUNET_IDENTITY_Ego *ego,
1738  void **ctx,
1739  const char *name)
1740 {
1741  (void)cls;
1742  (void)ctx;
1743 
1744  if (NULL == ego)
1745  {
1746  /* end of iteration */
1747  if (NULL == zone_head)
1748  {
1749  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No zone found\n");
1751  return;
1752  }
1753  /* zone_head non-null, process hostnames from stdin */
1755  return;
1756  }
1757  if (NULL != name)
1758  {
1759  struct Zone *zone;
1760 
1761  zone = GNUNET_new(struct Zone);
1763  zone->domain = GNUNET_strdup(name);
1764  GNUNET_CONTAINER_DLL_insert(zone_head, zone_tail, zone);
1765  }
1766 }
1767 
1768 
1778 static void
1779 run(void *cls,
1780  char *const *args,
1781  const char *cfgfile,
1782  const struct GNUNET_CONFIGURATION_Handle *cfg)
1783 {
1784  (void)cls;
1785  (void)args;
1786  (void)cfgfile;
1787  stats = GNUNET_STATISTICS_create("zoneimport", cfg);
1790  if (NULL == ns_pending)
1791  {
1792  fprintf(stderr, "Failed to allocate memory for main hash map\n");
1793  return;
1794  }
1795  ctx = GNUNET_DNSSTUB_start(256);
1796  if (NULL == ctx)
1797  {
1798  fprintf(stderr, "Failed to initialize GNUnet DNS STUB\n");
1799  return;
1800  }
1801  if (NULL == args[0])
1802  {
1803  fprintf(stderr,
1804  "You must provide a list of DNS resolvers on the command line\n");
1805  return;
1806  }
1807  for (unsigned int i = 0; NULL != args[i]; i++)
1808  {
1809  if (GNUNET_OK != GNUNET_DNSSTUB_add_dns_ip(ctx, args[i]))
1810  {
1811  fprintf(stderr, "Failed to use `%s' for DNS resolver\n", args[i]);
1812  return;
1813  }
1814  }
1815 
1816 
1818  ns = GNUNET_NAMESTORE_connect(cfg);
1819  if (NULL == ns)
1820  {
1822  return;
1823  }
1824  id = GNUNET_IDENTITY_connect(cfg, &identity_cb, NULL);
1825 }
1826 
1827 
1835 int
1836 main(int argc, char *const *argv)
1837 {
1838  struct GNUNET_GETOPT_CommandLineOption options[] =
1840  "size",
1841  "MAPSIZE",
1842  gettext_noop(
1843  "size to use for the main hash map"),
1844  &map_size),
1846  'm',
1847  "minimum-expiration",
1848  "RELATIVETIME",
1849  gettext_noop("minimum expiration time we assume for imported records"),
1852  int ret;
1853 
1854  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
1855  return 2;
1856  if (GNUNET_OK != (ret = GNUNET_PROGRAM_run(argc,
1857  argv,
1858  "gnunet-zoneimport",
1859  "import DNS zone into namestore",
1860  options,
1861  &run,
1862  NULL)))
1863  return ret;
1864  GNUNET_free((void *)argv);
1865  fprintf(stderr,
1866  "Rejected %u names, had %u cached, did %u lookups, stored %u record sets\n"
1867  "Found %u records, %u lookups failed, %u/%u pending on shutdown\n",
1868  rejects,
1869  cached,
1870  lookups,
1871  record_sets,
1872  records,
1873  failures,
1874  pending,
1875  pending_rs);
1876  return 0;
1877 }
1878 
1879 /* 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:525
static struct GNUNET_TIME_Relative total_dns_latency
Sum of DNS latencies observed.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
char * domain
Domain of the zone (i.e.
struct GNUNET_DNSPARSER_Record * answers
Array of all answers in the packet, must contain "num_answers" entries.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
static struct GNUNET_NAMESTORE_ZoneIterator * zone_it
Current zone iteration handle.
static struct GNUNET_DATASTORE_QueueEntry * qe
Current operation.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct Request * req
Request we are processing.
uint64_t rel_value_us
The actual value.
static void process_record(void *cls, const struct GNUNET_DNSPARSER_Record *rec)
We received rec for req.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
int main(int argc, char *const *argv)
Call with IP address of resolver to query.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
static int raw
raw output
Definition: gnunet-gns.c:55
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
char * hostname
Hostname we are resolving.
static unsigned int pending_rs
The number of NAMESTORE record store operations that are outstanding.
#define GNUNET_DNSPARSER_TYPE_CNAME
char * mxhost
Name of the mail server.
struct GNUNET_DNSPARSER_SrvRecord * srv
SRV data for SRV records.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1284
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:1439
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:687
int GNUNET_DNSPARSER_pack(const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length)
Given a DNS packet p, generate the corresponding UDP payload.
Definition: dnsparser.c:1256
#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:588
int GNUNET_DNSPARSER_builder_add_srv(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SrvRecord *srv)
Add an SRV record to the UDP packet at the given location.
Definition: dnsparser.c:1117
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:553
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.
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:853
#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:517
static int ret
Final status code.
Definition: gnunet-arm.c:89
Handle for the service.
static unsigned int failures
Number of lookups that failed.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_DNSPARSER_TYPE_MX
unsigned int num_answers
Number of answers in the packet, should be 0 for queries.
uint64_t abs_value_us
The actual value.
struct GNUNET_CRYPTO_EcdsaPrivateKey key
Private key of the zone.
uint16_t id
Unique identifier for the request/response.
Internal representation of the hash map.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
void(* RecordProcessor)(void *cls, const struct GNUNET_DNSPARSER_Record *rec)
Callback for for_all_records.
unsigned int issue_num
How often did we issue this query? (And failed, reset to zero once we were successful.)
static uint64_t total_reg_proc_dns_ns
Number of records processed (DNS lookup, with NAMESTORE) in total.
void GNUNET_NAMESTORE_cancel(struct GNUNET_NAMESTORE_QueueEntry *qe)
Cancel a namestore operation.
static void iterate_zones(void *cls)
Iterate over all of the zones we care about and see which records we may need to re-fetch when...
static struct GNUNET_TIME_Absolute start_time_reg_proc
Start time of the regular processing.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_store(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls)
Store an item in the namestore.
#define GNUNET_DNSPARSER_TYPE_PTR
static void free_records(struct Request *req)
Free records associated with req.
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
static char * zone
Name of the zone we manage.
static unsigned int rejects
How many hostnames did we reject (malformed).
void GNUNET_NAMESTORE_disconnect(struct GNUNET_NAMESTORE_Handle *h)
Disconnect from the namestore service (and free associated resources).
static void store_completed_cb(void *cls, int32_t success, const char *emsg)
Continuation called to notify client about result of the operation.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
Handle for a zone iterator operation.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1237
Handle for an ego.
Definition: identity.h:237
#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:561
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
Connection to the NAMESTORE service.
int found
Set to GNUNET_YES if glue was found.
#define GNUNET_DNSPARSER_TYPE_DNAME
Handle for the service.
Definition: identity_api.c:94
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:1264
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:686
Randomness for IVs etc.
int GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
Handle to a node in a heap.
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:835
int GNUNET_DNSPARSER_builder_add_soa(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SoaRecord *soa)
Add an SOA record to the UDP packet at the given location.
Definition: dnsparser.c:1076
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:602
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:121
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:1029
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:501
#define THRESH
Maximum number of queries pending at the same time.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
Node in the heap.
static void process_stdin(void *cls)
Begin processing hostnames from stdin.
static struct Zone * zone_tail
Tail of list of zones we are managing.
static struct Request * req_head
Active requests are kept in a DLL.
struct Record * rec_tail
Tail of records that should be published in GNS for this hostname.
#define MAX_SERIES
How many DNS requests do we at most issue in rapid series?
There must only be one value per key; storing a value should fail if a value under the same key alrea...
static void identity_cb(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name)
Method called to inform about the egos of this peer.
#define GNUNET_SYSERR
Definition: gnunet_common.h: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:1000
struct GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namestore service.
static int free_request_it(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator called during do_shutdown() to free requests in the ns_pending map.
int issue_num
How often did we issue this query?
#define GNUNET_DNSPARSER_TYPE_TXT
static uint64_t total_reg_proc_dns
Number of records processed (DNS lookup, no NAMESTORE) in total.
const char * name
int GNUNET_DNSPARSER_check_name(const char *name)
Check if a hostname in UTF-8 format can be coded into valid IDNA.
Definition: dnsparser.c: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:577
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:83
struct Record * prev
Kept in a DLL.
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition: dnsstub.c:537
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition: time.c:302
static void process_result(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
Function called with the result of a DNS resolution.
#define GNUNET_DNSPARSER_TYPE_NS
struct Zone * next
Kept in a DLL.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:373
Easy-to-process, parsed version of a DNS packet.
static void check_for_glue(void *cls, const struct GNUNET_DNSPARSER_Record *rec)
Try to find glue records for a given NS record.
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
static void add_record(struct Request *req, uint32_t type, struct GNUNET_TIME_Absolute expiration_time, const void *data, size_t data_len)
Add record to the GNS record set for req.
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:131
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:525
Time for absolute times used by GNUnet, in microseconds.
static struct GNUNET_TIME_Relative minimum_expiration_time
How long do DNS records have to last at least after being imported?
static unsigned int records
Number of records we found.
#define GNUNET_YES
Definition: gnunet_common.h: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.
union GNUNET_DNSPARSER_Record::@27 data
Payload of the record (which one of these is valid depends on the &#39;type&#39;).
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_uint(char shortName, const char *name, const char *argumentHelp, const char *description, unsigned int *val)
Allow user to specify an unsigned int.
int GNUNET_DNSPARSER_builder_add_name(char *dst, size_t dst_len, size_t *off, const char *name)
Add a DNS name to the UDP packet at the given location, converting the name to IDNA notation as neces...
Definition: dnsparser.c:888
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:741
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:1214
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:956
Some zones may include authoritative records for other zones, such as foo.com.uk or bar...