aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>2018-04-10 16:34:43 +0200
committerSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>2018-04-10 16:34:43 +0200
commite9a48662fd0c3393a593b762769a3cfd26400a34 (patch)
tree1909062d2174478584fa411409ea78fce2228f30 /src
parent96a9530a14cff303959c2251829100a1e62954ce (diff)
parent2c3ed5fda45b21ce7e3038324d785cb13ffd0edb (diff)
downloadgnunet-e9a48662fd0c3393a593b762769a3cfd26400a34.tar.gz
gnunet-e9a48662fd0c3393a593b762769a3cfd26400a34.zip
Merge branch 'master' of git+ssh://gnunet.org/gnunet
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_namestore_plugin.h2
-rw-r--r--src/namestore/Makefile.am1
-rw-r--r--src/namestore/gnunet-zoneimport.c328
3 files changed, 296 insertions, 35 deletions
diff --git a/src/include/gnunet_namestore_plugin.h b/src/include/gnunet_namestore_plugin.h
index 48965b3b6..11f16b97a 100644
--- a/src/include/gnunet_namestore_plugin.h
+++ b/src/include/gnunet_namestore_plugin.h
@@ -44,7 +44,7 @@ extern "C"
44 44
45 45
46/** 46/**
47 * Function called by for each matching record. 47 * Function called for each matching record.
48 * 48 *
49 * @param cls closure 49 * @param cls closure
50 * @param zone_key private key of the zone 50 * @param zone_key private key of the zone
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index cdfed543d..50b60d020 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -138,6 +138,7 @@ endif
138gnunet_zoneimport_SOURCES = \ 138gnunet_zoneimport_SOURCES = \
139 gnunet-zoneimport.c 139 gnunet-zoneimport.c
140gnunet_zoneimport_LDADD = \ 140gnunet_zoneimport_LDADD = \
141 $(top_builddir)/src/identity/libgnunetidentity.la \
141 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 142 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
142 $(top_builddir)/src/dns/libgnunetdnsparser.la \ 143 $(top_builddir)/src/dns/libgnunetdnsparser.la \
143 $(top_builddir)/src/dns/libgnunetdnsstub.la \ 144 $(top_builddir)/src/dns/libgnunetdnsstub.la \
diff --git a/src/namestore/gnunet-zoneimport.c b/src/namestore/gnunet-zoneimport.c
index 33c20953b..f2e5c7ba8 100644
--- a/src/namestore/gnunet-zoneimport.c
+++ b/src/namestore/gnunet-zoneimport.c
@@ -28,6 +28,7 @@
28#include <gnunet_dnsparser_lib.h> 28#include <gnunet_dnsparser_lib.h>
29#include <gnunet_gnsrecord_lib.h> 29#include <gnunet_gnsrecord_lib.h>
30#include <gnunet_namestore_plugin.h> 30#include <gnunet_namestore_plugin.h>
31#include <gnunet_identity_service.h>
31 32
32 33
33/** 34/**
@@ -91,14 +92,14 @@ struct Request
91 void *raw; 92 void *raw;
92 93
93 /** 94 /**
94 * Number of bytes in @e raw. 95 * Hostname we are resolving.
95 */ 96 */
96 size_t raw_len; 97 char *hostname;
97 98
98 /** 99 /**
99 * Hostname we are resolving. 100 * Label (without TLD) which we are resolving.
100 */ 101 */
101 char *hostname; 102 char *label;
102 103
103 /** 104 /**
104 * Answer we got back and are currently parsing, or NULL 105 * Answer we got back and are currently parsing, or NULL
@@ -111,7 +112,12 @@ struct Request
111 * for this name expire? At this point, we need to re-fetch 112 * for this name expire? At this point, we need to re-fetch
112 * the record. 113 * the record.
113 */ 114 */
114 struct GNUNET_TIME_Absolute expires__; 115 struct GNUNET_TIME_Absolute expires;
116
117 /**
118 * Number of bytes in @e raw.
119 */
120 size_t raw_len;
115 121
116 /** 122 /**
117 * When did we last issue this request? 123 * When did we last issue this request?
@@ -130,6 +136,12 @@ struct Request
130 uint16_t id; 136 uint16_t id;
131}; 137};
132 138
139
140/**
141 * Handle to the identity service.
142 */
143static struct GNUNET_IDENTITY_Handle *id;
144
133/** 145/**
134 * Namestore plugin. 146 * Namestore plugin.
135 */ 147 */
@@ -187,6 +199,21 @@ static char *dns_server;
187 */ 199 */
188static char *db_lib_name; 200static char *db_lib_name;
189 201
202/**
203 * Which zone are we importing into?
204 */
205static struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
206
207/**
208 * Which zone should records be imported into?
209 */
210static char *zone_name;
211
212/**
213 * Did we find #zone_name and initialize #zone?
214 */
215static int zone_found;
216
190 217
191/** 218/**
192 * Maximum number of queries pending at the same time. 219 * Maximum number of queries pending at the same time.
@@ -251,7 +278,35 @@ for_all_records (const struct GNUNET_DNSPARSER_Packet *p,
251 rs); 278 rs);
252 } 279 }
253} 280}
254 281
282
283/**
284 * Insert @a req into DLL sorted by next fetch time.
285 *
286 * @param req request to insert into #req_head / #req_tail DLL
287 */
288static void
289insert_sorted (struct Request *req)
290{
291 struct Request *prev;
292
293 prev = NULL;
294 /* NOTE: this linear-time loop may actually be our
295 main burner of CPU time for large zones, to be
296 revisited if CPU utilization turns out to be an
297 issue! */
298 for (struct Request *pos = req_head;
299 ( (NULL != pos) &&
300 (NULL != pos->next) &&
301 (pos->expires.abs_value_us <= req->expires.abs_value_us) );
302 pos = pos->next)
303 prev = pos;
304 GNUNET_CONTAINER_DLL_insert_after (req_head,
305 req_tail,
306 prev,
307 req);
308}
309
255 310
256/** 311/**
257 * Add record to the GNS record set for @a req. 312 * Add record to the GNS record set for @a req.
@@ -573,7 +628,9 @@ process_result (void *cls,
573 size_t dns_len) 628 size_t dns_len)
574{ 629{
575 struct Request *req = cls; 630 struct Request *req = cls;
631 struct Record *rec;
576 struct GNUNET_DNSPARSER_Packet *p; 632 struct GNUNET_DNSPARSER_Packet *p;
633 unsigned int rd_count;
577 634
578 (void) rs; 635 (void) rs;
579 if (NULL == dns) 636 if (NULL == dns)
@@ -618,26 +675,68 @@ process_result (void *cls,
618 if (req->issue_num > MAX_RETRIES) 675 if (req->issue_num > MAX_RETRIES)
619 { 676 {
620 failures++; 677 failures++;
621 GNUNET_free (req->hostname); 678 insert_sorted (req);
622 GNUNET_free (req->raw);
623 GNUNET_free (req);
624 return; 679 return;
625 } 680 }
626 GNUNET_CONTAINER_DLL_insert_tail (req_head, 681 insert_sorted (req);
627 req_tail,
628 req);
629 return; 682 return;
630 } 683 }
684 /* Free old/legacy records */
685 while (NULL != (rec = req->rec_head))
686 {
687 GNUNET_CONTAINER_DLL_remove (req->rec_head,
688 req->rec_tail,
689 rec);
690 GNUNET_free (rec);
691 }
692 /* import new records */
693 req->issue_num = 0; /* success, reset counter! */
631 req->p = p; 694 req->p = p;
632 for_all_records (p, 695 for_all_records (p,
633 &process_record, 696 &process_record,
634 req); 697 req);
635 req->p = NULL; 698 req->p = NULL;
636 // FIXME: update database!
637 GNUNET_DNSPARSER_free_packet (p); 699 GNUNET_DNSPARSER_free_packet (p);
638 GNUNET_free (req->hostname); 700 /* count records found, determine minimum expiration time */
639 GNUNET_free (req->raw); 701 req->expires = GNUNET_TIME_UNIT_FOREVER_ABS;
640 GNUNET_free (req); 702 rd_count = 0;
703 for (rec = req->rec_head; NULL != rec; rec = rec->next)
704 {
705 struct GNUNET_TIME_Absolute at;
706
707 at.abs_value_us = rec->grd.expiration_time;
708 req->expires = GNUNET_TIME_absolute_min (req->expires,
709 at);
710 rd_count++;
711 }
712 /* Instead of going for SOA, simplified for now to look each
713 day in case we got an empty response */
714 if (0 == rd_count)
715 req->expires
716 = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS);
717 /* convert records to namestore import format */
718 {
719 struct GNUNET_GNSRECORD_Data rd[rd_count];
720 unsigned int off;
721
722 /* convert linked list into array */
723 for (rec = req->rec_head, off = 0;
724 NULL != rec;
725 rec =rec->next, off++)
726 rd[off] = rec->grd;
727 if (GNUNET_OK !=
728 ns->store_records (ns->cls,
729 &zone,
730 req->label,
731 rd_count,
732 rd))
733 {
734 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
735 "Failed to store zone data for `%s'\n",
736 req->hostname);
737 }
738 }
739 insert_sorted (req);
641} 740}
642 741
643 742
@@ -715,6 +814,11 @@ static void
715do_shutdown (void *cls) 814do_shutdown (void *cls)
716{ 815{
717 (void) cls; 816 (void) cls;
817 if (NULL != id)
818 {
819 GNUNET_IDENTITY_disconnect (id);
820 id = NULL;
821 }
718 if (NULL != t) 822 if (NULL != t)
719 { 823 {
720 GNUNET_SCHEDULER_cancel (t); 824 GNUNET_SCHEDULER_cancel (t);
@@ -734,6 +838,43 @@ do_shutdown (void *cls)
734 838
735 839
736/** 840/**
841 * Function called for each matching record.
842 *
843 * @param cls `struct Request *`
844 * @param zone_key private key of the zone
845 * @param label name that is being mapped (at most 255 characters long)
846 * @param rd_count number of entries in @a rd array
847 * @param rd array of records with data to store
848 */
849static void
850import_records (void *cls,
851 const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key,
852 const char *label,
853 unsigned int rd_count,
854 const struct GNUNET_GNSRECORD_Data *rd)
855{
856 struct Request *req = cls;
857
858 GNUNET_break (0 == memcmp (private_key,
859 &zone,
860 sizeof (zone)));
861 GNUNET_break (0 == strcasecmp (label,
862 req->label));
863 for (unsigned int i=0;i<rd_count;i++)
864 {
865 struct GNUNET_TIME_Absolute at;
866
867 at.abs_value_us = rd->expiration_time;
868 add_record (req,
869 rd->record_type,
870 at,
871 rd->data,
872 rd->data_size);
873 }
874}
875
876
877/**
737 * Add @a hostname to the list of requests to be made. 878 * Add @a hostname to the list of requests to be made.
738 * 879 *
739 * @param hostname name to resolve 880 * @param hostname name to resolve
@@ -746,6 +887,7 @@ queue (const char *hostname)
746 struct Request *req; 887 struct Request *req;
747 char *raw; 888 char *raw;
748 size_t raw_size; 889 size_t raw_size;
890 const char *dot;
749 891
750 if (GNUNET_OK != 892 if (GNUNET_OK !=
751 GNUNET_DNSPARSER_check_name (hostname)) 893 GNUNET_DNSPARSER_check_name (hostname))
@@ -755,6 +897,15 @@ queue (const char *hostname)
755 hostname); 897 hostname);
756 return; 898 return;
757 } 899 }
900 dot = strrchr (hostname,
901 (unsigned char) '.');
902 if (NULL == dot)
903 {
904 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
905 "Refusing invalid hostname `%s' (lacks '.')\n",
906 hostname);
907 return;
908 }
758 q.name = (char *) hostname; 909 q.name = (char *) hostname;
759 q.type = GNUNET_DNSPARSER_TYPE_NS; 910 q.type = GNUNET_DNSPARSER_TYPE_NS;
760 q.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET; 911 q.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
@@ -780,16 +931,128 @@ queue (const char *hostname)
780 } 931 }
781 932
782 req = GNUNET_new (struct Request); 933 req = GNUNET_new (struct Request);
783 req->hostname = strdup (hostname); 934 req->hostname = GNUNET_strdup (hostname);
784 req->raw = raw; 935 req->raw = raw;
785 req->raw_len = raw_size; 936 req->raw_len = raw_size;
786 req->id = p.id; 937 req->id = p.id;
787 /* FIXME: import data from namestore! */ 938 req->label = GNUNET_strndup (hostname,
939 dot - hostname);
940 if (NULL != strchr (req->label,
941 (unsigned char) '.'))
942 {
943 GNUNET_free (req->hostname);
944 GNUNET_free (req->label);
945 GNUNET_free (req);
946 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
947 "Label contained a `.', invalid hostname `%s'\n",
948 hostname);
949 return;
950 }
951 if (GNUNET_OK !=
952 ns->lookup_records (ns->cls,
953 &zone,
954 req->label,
955 &import_records,
956 req))
957 {
958 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
959 "Failed to load data from namestore for `%s'\n",
960 req->label);
961 }
962 insert_sorted (req);
963}
964
965
966/**
967 * Begin processing hostnames from stdin.
968 *
969 * @param cls NULL
970 */
971static void
972process_stdin (void *cls)
973{
974 char hn[256];
788 975
789 /* FIXME: insert sorted by record expiration time */ 976 (void) cls;
790 GNUNET_CONTAINER_DLL_insert_tail (req_head, 977 t = NULL;
791 req_tail, 978 GNUNET_IDENTITY_disconnect (id);
792 req); 979 id = NULL;
980 while (NULL !=
981 fgets (hn,
982 sizeof (hn),
983 stdin))
984 {
985 if (strlen(hn) > 0)
986 hn[strlen(hn)-1] = '\0'; /* eat newline */
987 queue (hn);
988 }
989 t = GNUNET_SCHEDULER_add_now (&process_queue,
990 NULL);
991}
992
993
994/**
995 * Method called to inform about the egos of this peer.
996 *
997 * When used with #GNUNET_IDENTITY_connect, this function is
998 * initially called for all egos and then again whenever a
999 * ego's name changes or if it is deleted. At the end of
1000 * the initial pass over all egos, the function is once called
1001 * with 'NULL' for @a ego. That does NOT mean that the callback won't
1002 * be invoked in the future or that there was an error.
1003 *
1004 * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get,
1005 * this function is only called ONCE, and 'NULL' being passed in
1006 * @a ego does indicate an error (i.e. name is taken or no default
1007 * value is known). If @a ego is non-NULL and if '*ctx'
1008 * is set in those callbacks, the value WILL be passed to a subsequent
1009 * call to the identity callback of #GNUNET_IDENTITY_connect (if
1010 * that one was not NULL).
1011 *
1012 * When an identity is renamed, this function is called with the
1013 * (known) @a ego but the NEW @a name.
1014 *
1015 * When an identity is deleted, this function is called with the
1016 * (known) ego and "NULL" for the @a name. In this case,
1017 * the @a ego is henceforth invalid (and the @a ctx should also be
1018 * cleaned up).
1019 *
1020 * @param cls closure
1021 * @param ego ego handle
1022 * @param ctx context for application to store data for this ego
1023 * (during the lifetime of this process, initially NULL)
1024 * @param name name assigned by the user for this ego,
1025 * NULL if the user just deleted the ego and it
1026 * must thus no longer be used
1027 */
1028static void
1029identity_cb (void *cls,
1030 struct GNUNET_IDENTITY_Ego *ego,
1031 void **ctx,
1032 const char *name)
1033{
1034 (void) cls;
1035 (void) ctx;
1036 if (NULL == ego)
1037 {
1038 if (zone_found)
1039 t = GNUNET_SCHEDULER_add_now (&process_stdin,
1040 NULL);
1041 else
1042 {
1043 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1044 "Specified zone not found\n");
1045 GNUNET_SCHEDULER_shutdown ();
1046 return;
1047 }
1048 }
1049 if ( (NULL != name) &&
1050 (0 == strcasecmp (name,
1051 zone_name)) )
1052 {
1053 zone_found = GNUNET_YES;
1054 zone = *GNUNET_IDENTITY_ego_get_private_key (ego);
1055 }
793} 1056}
794 1057
795 1058
@@ -808,7 +1071,6 @@ run (void *cls,
808 const char *cfgfile, 1071 const char *cfgfile,
809 const struct GNUNET_CONFIGURATION_Handle *cfg) 1072 const struct GNUNET_CONFIGURATION_Handle *cfg)
810{ 1073{
811 char hn[256];
812 char *database; 1074 char *database;
813 1075
814 (void) cls; 1076 (void) cls;
@@ -835,19 +1097,11 @@ run (void *cls,
835 ns = GNUNET_PLUGIN_load (db_lib_name, 1097 ns = GNUNET_PLUGIN_load (db_lib_name,
836 (void *) cfg); 1098 (void *) cfg);
837 GNUNET_free (database); 1099 GNUNET_free (database);
838 while (NULL != 1100 id = GNUNET_IDENTITY_connect (cfg,
839 fgets (hn, 1101 &identity_cb,
840 sizeof (hn), 1102 NULL);
841 stdin))
842 {
843 if (strlen(hn) > 0)
844 hn[strlen(hn)-1] = '\0'; /* eat newline */
845 queue (hn);
846 }
847 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, 1103 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
848 NULL); 1104 NULL);
849 t = GNUNET_SCHEDULER_add_now (&process_queue,
850 NULL);
851} 1105}
852 1106
853 1107
@@ -869,6 +1123,12 @@ main (int argc,
869 "IP", 1123 "IP",
870 "which DNS server should be used", 1124 "which DNS server should be used",
871 &dns_server)), 1125 &dns_server)),
1126 GNUNET_GETOPT_option_mandatory
1127 (GNUNET_GETOPT_option_string ('i',
1128 "identity",
1129 "ZONENAME",
1130 "which GNS zone should we import data into",
1131 &zone_name)),
872 GNUNET_GETOPT_OPTION_END 1132 GNUNET_GETOPT_OPTION_END
873 }; 1133 };
874 1134