aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authort3sserakt <t3ss@posteo.de>2022-03-17 15:12:06 +0100
committert3sserakt <t3ss@posteo.de>2022-03-17 15:12:06 +0100
commit8d41efc36bec5bc5ec29278a365d5a63d7349084 (patch)
tree99177b1b5400df5ae7180c2af1f47408cace1034 /src
parent95a1edacccd9b3bf769a144a12d41946d0ac25dc (diff)
parentea4a5dd6ca3d62f852b5c2de94071b7fc8f0544c (diff)
downloadgnunet-8d41efc36bec5bc5ec29278a365d5a63d7349084.tar.gz
gnunet-8d41efc36bec5bc5ec29278a365d5a63d7349084.zip
Merge branch 'master' of ssh://git.gnunet.org/gnunet
Diffstat (limited to 'src')
-rw-r--r--src/ats/ats.conf.in12
-rw-r--r--src/ats/gnunet-ats-solver-eval.c5
-rw-r--r--src/block/bg_bf.c4
-rw-r--r--src/block/block.c33
-rw-r--r--src/block/plugin_block_template.c82
-rw-r--r--src/block/plugin_block_test.c120
-rw-r--r--src/consensus/plugin_block_consensus.c61
-rw-r--r--src/consensus/test_consensus.conf2
-rw-r--r--src/datacache/datacache.c86
-rw-r--r--src/datacache/plugin_datacache_heap.c70
-rw-r--r--src/datacache/plugin_datacache_postgres.c23
-rw-r--r--src/datacache/plugin_datacache_sqlite.c62
-rw-r--r--src/datacache/plugin_datacache_template.c2
-rw-r--r--src/dht/.gitignore1
-rw-r--r--src/dht/Makefile.am23
-rw-r--r--src/dht/dht_api.c251
-rwxr-xr-xsrc/dht/dhtu_testbed_connect.sh31
-rw-r--r--src/dht/dhtu_testbed_deploy.conf26
-rwxr-xr-xsrc/dht/dhtu_testbed_deploy.sh84
-rw-r--r--src/dht/gnunet-dht-get.c24
-rw-r--r--src/dht/gnunet-dht-hello.c178
-rw-r--r--src/dht/gnunet-service-dht.c467
-rw-r--r--src/dht/gnunet-service-dht.h93
-rw-r--r--src/dht/gnunet-service-dht_clients.c177
-rw-r--r--src/dht/gnunet-service-dht_datacache.c139
-rw-r--r--src/dht/gnunet-service-dht_datacache.h13
-rw-r--r--src/dht/gnunet-service-dht_hello.c154
-rw-r--r--src/dht/gnunet-service-dht_hello.h55
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c1761
-rw-r--r--src/dht/gnunet-service-dht_neighbours.h84
-rw-r--r--src/dht/gnunet-service-dht_nse.c121
-rw-r--r--src/dht/gnunet-service-dht_nse.h52
-rw-r--r--src/dht/gnunet-service-dht_routing.c36
-rw-r--r--src/dht/plugin_block_dht.c388
-rw-r--r--src/dht/test_dht_topo.c28
-rw-r--r--src/dhtu/Makefile.am7
-rw-r--r--src/dhtu/dhtu.conf7
-rw-r--r--src/dhtu/plugin_dhtu_gnunet.c63
-rw-r--r--src/dhtu/plugin_dhtu_ip.c434
-rw-r--r--src/dns/plugin_block_dns.c128
-rw-r--r--src/fs/fs_file_information.c2
-rw-r--r--src/fs/fs_uri.c26
-rw-r--r--src/fs/gnunet-search.c599
-rw-r--r--src/fs/gnunet-service-fs_pr.c74
-rw-r--r--src/fs/plugin_block_fs.c117
-rw-r--r--src/gns/Makefile.am26
-rw-r--r--src/gns/gnunet-bcd.c2
-rw-r--r--src/gns/gnunet-dns2gns.c209
-rw-r--r--src/gns/gnunet-service-gns.c8
-rw-r--r--src/gns/gnunet-service-gns_resolver.c348
-rw-r--r--src/gns/plugin_block_gns.c132
-rw-r--r--src/gns/plugin_gnsrecord_gns.c40
-rwxr-xr-xsrc/gns/test_gns_cname_lookup.sh99
-rwxr-xr-xsrc/gns/test_gns_gns2dns_cname_lookup.sh9
-rwxr-xr-xsrc/gns/test_gns_gns2dns_lookup.sh14
-rwxr-xr-xsrc/gns/test_gns_gns2dns_zkey_lookup.sh14
-rwxr-xr-xsrc/gns/test_gns_redirect_lookup.sh100
-rw-r--r--src/gnsrecord/Makefile.am18
-rw-r--r--src/gnsrecord/gnsrecord.c21
-rw-r--r--src/gnsrecord/gnsrecord_crypto.c58
-rw-r--r--src/gnsrecord/gnsrecord_misc.c250
-rw-r--r--src/gnsrecord/gnunet-gnsrecord-tvg.c226
-rw-r--r--src/gnsrecord/perf_gnsrecord_crypto.c6
-rw-r--r--src/gnsrecord/plugin_gnsrecord_dns.c7
-rw-r--r--src/gnsrecord/test_gnsrecord_block_expiration.c6
-rw-r--r--src/gnsrecord/test_gnsrecord_testvectors.c33
-rw-r--r--src/hello/.gitignore2
-rw-r--r--src/hello/Makefile.am19
-rw-r--r--src/hello/hello-uri.c891
-rw-r--r--src/hello/test_hello-ng.c23
-rw-r--r--src/hello/test_hello-uri.c212
-rw-r--r--src/hostlist/gnunet-daemon-hostlist_client.c6
-rw-r--r--src/identity/Makefile.am3
-rw-r--r--src/identity/gnunet-service-identity.c3
-rw-r--r--src/include/Makefile.am1
-rw-r--r--src/include/gnunet_block_group_lib.h2
-rw-r--r--src/include/gnunet_block_lib.h144
-rw-r--r--src/include/gnunet_block_plugin.h61
-rw-r--r--src/include/gnunet_common.h27
-rw-r--r--src/include/gnunet_crypto_lib.h55
-rw-r--r--src/include/gnunet_datacache_lib.h2
-rw-r--r--src/include/gnunet_datacache_plugin.h13
-rw-r--r--src/include/gnunet_dht_service.h81
-rw-r--r--src/include/gnunet_dhtu_plugin.h26
-rw-r--r--src/include/gnunet_fs_service.h2
-rw-r--r--src/include/gnunet_gns_service.h6
-rw-r--r--src/include/gnunet_gnsrecord_lib.h98
-rw-r--r--src/include/gnunet_gnsrecord_plugin.h17
-rw-r--r--src/include/gnunet_hello_uri_lib.h248
-rw-r--r--src/include/gnunet_json_lib.h8
-rw-r--r--src/include/gnunet_namestore_service.h88
-rw-r--r--src/include/gnunet_protocols.h24
-rw-r--r--src/include/gnunet_strings_lib.h16
-rw-r--r--src/include/gnunet_time_lib.h13
-rw-r--r--src/json/json_pack.c6
-rw-r--r--src/messenger/gnunet-service-messenger.c4
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.c8
-rw-r--r--src/messenger/gnunet-service-messenger_room.c28
-rw-r--r--src/messenger/gnunet-service-messenger_room.h15
-rw-r--r--src/messenger/gnunet-service-messenger_service.c8
-rw-r--r--src/messenger/messenger.conf.in6
-rw-r--r--src/messenger/messenger_api_message.c12
-rw-r--r--src/namecache/test_namecache_api_cache_block.c7
-rw-r--r--src/namestore/Makefile.am11
-rw-r--r--src/namestore/gnunet-namestore.c105
-rw-r--r--src/namestore/gnunet-service-namestore.c396
-rw-r--r--src/namestore/namestore.h28
-rw-r--r--src/namestore/namestore_api.c173
-rw-r--r--src/namestore/plugin_namestore_sqlite.c10
-rw-r--r--src/namestore/test_namestore_api_lookup_nick.c4
-rw-r--r--src/namestore/test_namestore_api_lookup_public.c2
-rw-r--r--src/namestore/test_namestore_api_lookup_shadow.c2
-rw-r--r--src/namestore/test_namestore_api_lookup_shadow_filter.c2
-rw-r--r--src/namestore/test_namestore_api_remove.c2
-rw-r--r--src/namestore/test_namestore_api_remove_not_existing_record.c2
-rw-r--r--src/namestore/test_namestore_api_zone_to_name.c10
-rwxr-xr-xsrc/namestore/test_namestore_delete.sh10
-rwxr-xr-xsrc/namestore/test_plugin_rest_namestore.sh10
-rw-r--r--src/reclaim/reclaim_api.c1
-rw-r--r--src/reclaim/test_reclaim.conf2
-rwxr-xr-xsrc/reclaim/test_reclaim_consume.sh14
-rw-r--r--src/regex/plugin_block_regex.c287
-rw-r--r--src/revocation/gnunet-revocation-tvg.c1
-rw-r--r--src/revocation/plugin_block_revocation.c74
-rw-r--r--src/revocation/revocation_api.c2
-rw-r--r--src/set/plugin_block_set_test.c44
-rw-r--r--src/seti/plugin_block_seti_test.c72
-rw-r--r--src/setu/plugin_block_setu_test.c76
-rw-r--r--src/transport/Makefile.am8
-rw-r--r--src/transport/gnunet-communicator-tcp.c16
-rw-r--r--src/transport/gnunet-service-tng.c20
-rw-r--r--src/transport/gnunet-service-transport.c4
-rwxr-xr-xsrc/transport/test_transport_simple_send.sh7
-rwxr-xr-xsrc/transport/test_transport_simple_send_broadcast.sh8
-rwxr-xr-xsrc/transport/test_transport_simple_send_dv.sh8
-rwxr-xr-xsrc/transport/test_transport_simple_send_dv_circle.sh9
-rwxr-xr-xsrc/transport/test_transport_simple_send_string.sh8
-rwxr-xr-xsrc/transport/test_transport_udp_backchannel.sh9
-rw-r--r--src/util/common_logging.c25
-rw-r--r--src/util/crypto_cs.c214
-rw-r--r--src/util/crypto_hash.c3
-rw-r--r--src/util/dnsstub.c42
-rw-r--r--src/util/getopt_helpers.c3
-rw-r--r--src/util/gnunet-crypto-tvg.c24
-rw-r--r--src/util/network.c3
-rw-r--r--src/util/plugin.c4
-rw-r--r--src/util/strings.c41
-rw-r--r--src/util/test_crypto_cs.c334
-rw-r--r--src/util/test_strings.c7
-rw-r--r--src/util/time.c7
-rw-r--r--src/zonemaster/gnunet-service-zonemaster-monitor.c65
-rw-r--r--src/zonemaster/gnunet-service-zonemaster.c103
152 files changed, 7779 insertions, 4549 deletions
diff --git a/src/ats/ats.conf.in b/src/ats/ats.conf.in
index 4abddd99c..2c65869dd 100644
--- a/src/ats/ats.conf.in
+++ b/src/ats/ats.conf.in
@@ -15,8 +15,8 @@ MODE = proportional
15# IMPORTANT: Do not lower those quotas below 10 MiB 15# IMPORTANT: Do not lower those quotas below 10 MiB
16# Or your peer may not bootstrap correctly. 16# Or your peer may not bootstrap correctly.
17# Network specific inbound/outbound quotas 17# Network specific inbound/outbound quotas
18UNSPECIFIED_QUOTA_IN = 10 MiB 18UNSPECIFIED_QUOTA_IN = unlimited
19UNSPECIFIED_QUOTA_OUT = 10 MiB 19UNSPECIFIED_QUOTA_OUT = unlimited
20# LOOPBACK 20# LOOPBACK
21LOOPBACK_QUOTA_IN = unlimited 21LOOPBACK_QUOTA_IN = unlimited
22LOOPBACK_QUOTA_OUT = unlimited 22LOOPBACK_QUOTA_OUT = unlimited
@@ -27,8 +27,8 @@ LAN_QUOTA_OUT = unlimited
27WAN_QUOTA_IN = 10 MiB 27WAN_QUOTA_IN = 10 MiB
28WAN_QUOTA_OUT = 10 MiB 28WAN_QUOTA_OUT = 10 MiB
29# WLAN 29# WLAN
30WLAN_QUOTA_IN = 10 MiB 30WLAN_QUOTA_IN = unlimited
31WLAN_QUOTA_OUT = 10 MiB 31WLAN_QUOTA_OUT = unlimited
32# BLUETOOTH 32# BLUETOOTH
33BLUETOOTH_QUOTA_IN = 10 MiB 33BLUETOOTH_QUOTA_IN = 10 MiB
34BLUETOOTH_QUOTA_OUT = 10 MiB 34BLUETOOTH_QUOTA_OUT = 10 MiB
@@ -38,7 +38,7 @@ BLUETOOTH_QUOTA_OUT = 10 MiB
38# How proportional to preferences is bandwidth distribution in a network 38# How proportional to preferences is bandwidth distribution in a network
39# 1.0: Fair with respect to addresses without preferences 39# 1.0: Fair with respect to addresses without preferences
40# > 1.0: The bigger, the more respect is paid to preferences 40# > 1.0: The bigger, the more respect is paid to preferences
41PROP_PROPORTIONALITY_FACTOR = 2.00 41PROP_PROPORTIONALITY_FACTOR = 10.00
42# Should we stick to existing connections are prefer to switch? 42# Should we stick to existing connections or prefer to switch?
43# [1.0...2.0], lower value prefers to switch, bigger value is more tolerant 43# [1.0...2.0], lower value prefers to switch, bigger value is more tolerant
44PROP_STABILITY_FACTOR = 1.25 44PROP_STABILITY_FACTOR = 1.25
diff --git a/src/ats/gnunet-ats-solver-eval.c b/src/ats/gnunet-ats-solver-eval.c
index 25b963532..ba7994686 100644
--- a/src/ats/gnunet-ats-solver-eval.c
+++ b/src/ats/gnunet-ats-solver-eval.c
@@ -442,7 +442,7 @@ GNUNET_ATS_solver_logging_write_to_disk (struct LoggingHandle *l, int
442 } 442 }
443 } 443 }
444 444
445cleanup: 445 cleanup:
446 next = lf_head; 446 next = lf_head;
447 for (cur = next; NULL != cur; cur = next) 447 for (cur = next; NULL != cur; cur = next)
448 { 448 {
@@ -1414,7 +1414,8 @@ load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
1414 } 1414 }
1415 else 1415 else
1416 { 1416 {
1417 GNUNET_STRINGS_utf8_toupper (op_network, op_network); 1417 GNUNET_break (GNUNET_OK == GNUNET_STRINGS_utf8_toupper (op_network,
1418 op_network));
1418 if (0 == strcmp (op_network, "UNSPECIFIED")) 1419 if (0 == strcmp (op_network, "UNSPECIFIED"))
1419 { 1420 {
1420 o->address_network = GNUNET_NT_UNSPECIFIED; 1421 o->address_network = GNUNET_NT_UNSPECIFIED;
diff --git a/src/block/bg_bf.c b/src/block/bg_bf.c
index ae8ee0e51..601f605a2 100644
--- a/src/block/bg_bf.c
+++ b/src/block/bg_bf.c
@@ -61,7 +61,7 @@ struct BfGroupInternals
61 * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not 61 * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not
62 * supported, #GNUNET_SYSERR on error 62 * supported, #GNUNET_SYSERR on error
63 */ 63 */
64static int 64static enum GNUNET_GenericReturnValue
65bf_group_serialize_cb (struct GNUNET_BLOCK_Group *bg, 65bf_group_serialize_cb (struct GNUNET_BLOCK_Group *bg,
66 uint32_t *nonce, 66 uint32_t *nonce,
67 void **raw_data, 67 void **raw_data,
@@ -124,7 +124,7 @@ bf_group_mark_seen_cb (struct GNUNET_BLOCK_Group *bg,
124 * @return #GNUNET_OK on success, #GNUNET_NO if the nonces were different and thus 124 * @return #GNUNET_OK on success, #GNUNET_NO if the nonces were different and thus
125 * we failed. 125 * we failed.
126 */ 126 */
127static int 127static enum GNUNET_GenericReturnValue
128bf_group_merge_cb (struct GNUNET_BLOCK_Group *bg1, 128bf_group_merge_cb (struct GNUNET_BLOCK_Group *bg1,
129 const struct GNUNET_BLOCK_Group *bg2) 129 const struct GNUNET_BLOCK_Group *bg2)
130{ 130{
diff --git a/src/block/block.c b/src/block/block.c
index 5824946f7..2e3c1dc70 100644
--- a/src/block/block.c
+++ b/src/block/block.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2010, 2017, 2021 GNUnet e.V. 3 Copyright (C) 2010, 2017, 2021, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -255,35 +255,6 @@ GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
255} 255}
256 256
257 257
258enum GNUNET_BLOCK_EvaluationResult
259GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx,
260 enum GNUNET_BLOCK_Type type,
261 struct GNUNET_BLOCK_Group *group,
262 enum GNUNET_BLOCK_EvaluationOptions eo,
263 const struct GNUNET_HashCode *query,
264 const void *xquery,
265 size_t xquery_size,
266 const void *reply_block,
267 size_t reply_block_size)
268{
269 struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
270 type);
271
272 if (NULL == plugin)
273 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
274 return plugin->evaluate (plugin->cls,
275 ctx,
276 type,
277 group,
278 eo,
279 query,
280 xquery,
281 xquery_size,
282 reply_block,
283 reply_block_size);
284}
285
286
287enum GNUNET_GenericReturnValue 258enum GNUNET_GenericReturnValue
288GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx, 259GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
289 enum GNUNET_BLOCK_Type type, 260 enum GNUNET_BLOCK_Type type,
@@ -327,7 +298,6 @@ GNUNET_BLOCK_check_query (struct GNUNET_BLOCK_Context *ctx,
327enum GNUNET_GenericReturnValue 298enum GNUNET_GenericReturnValue
328GNUNET_BLOCK_check_block (struct GNUNET_BLOCK_Context *ctx, 299GNUNET_BLOCK_check_block (struct GNUNET_BLOCK_Context *ctx,
329 enum GNUNET_BLOCK_Type type, 300 enum GNUNET_BLOCK_Type type,
330 const struct GNUNET_HashCode *query,
331 const void *block, 301 const void *block,
332 size_t block_size) 302 size_t block_size)
333{ 303{
@@ -338,7 +308,6 @@ GNUNET_BLOCK_check_block (struct GNUNET_BLOCK_Context *ctx,
338 return GNUNET_SYSERR; 308 return GNUNET_SYSERR;
339 return plugin->check_block (plugin->cls, 309 return plugin->check_block (plugin->cls,
340 type, 310 type,
341 query,
342 block, 311 block,
343 block_size); 312 block_size);
344} 313}
diff --git a/src/block/plugin_block_template.c b/src/block/plugin_block_template.c
index 13d9adfda..dcaf1afaa 100644
--- a/src/block/plugin_block_template.c
+++ b/src/block/plugin_block_template.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2010 GNUnet e.V. 3 Copyright (C) 2010, 2021, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -92,49 +92,6 @@ block_plugin_template_create_group (void *cls,
92 92
93 93
94/** 94/**
95 * Function called to validate a reply or a request. For
96 * request evaluation, simply pass "NULL" for the reply_block.
97 *
98 * @param cls closure
99 * @param ctx context
100 * @param type block type
101 * @param group block group to use
102 * @param eo control flags
103 * @param query original query (hash)
104 * @param xquery extrended query data (can be NULL, depending on type)
105 * @param xquery_size number of bytes in xquery
106 * @param reply_block response to validate
107 * @param reply_block_size number of bytes in reply block
108 * @return characterization of result
109 */
110static enum GNUNET_BLOCK_EvaluationResult
111block_plugin_template_evaluate (void *cls,
112 struct GNUNET_BLOCK_Context *ctx,
113 enum GNUNET_BLOCK_Type type,
114 struct GNUNET_BLOCK_Group *group,
115 enum GNUNET_BLOCK_EvaluationOptions eo,
116 const struct GNUNET_HashCode *query,
117 const void *xquery,
118 size_t xquery_size,
119 const void *reply_block,
120 size_t reply_block_size)
121{
122 struct GNUNET_HashCode chash;
123
124 if (NULL == reply_block)
125 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
126 GNUNET_CRYPTO_hash (reply_block,
127 reply_block_size,
128 &chash);
129 if (GNUNET_YES ==
130 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
131 &chash))
132 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
133 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
134}
135
136
137/**
138 * Function called to validate a query. 95 * Function called to validate a query.
139 * 96 *
140 * @param cls closure 97 * @param cls closure
@@ -143,16 +100,16 @@ block_plugin_template_evaluate (void *cls,
143 * @param query original query (hash) 100 * @param query original query (hash)
144 * @param xquery extrended query data (can be NULL, depending on type) 101 * @param xquery extrended query data (can be NULL, depending on type)
145 * @param xquery_size number of bytes in @a xquery 102 * @param xquery_size number of bytes in @a xquery
146 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not 103 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not, #GNUNET_SYSERR if not supported
147 */ 104 */
148static enum GNUNET_GenericReturnValue 105static enum GNUNET_GenericReturnValue
149block_plugin_template_check_query (void *cls, 106block_plugin_template_check_query (void *cls,
150 enum GNUNET_BLOCK_Type type, 107 enum GNUNET_BLOCK_Type type,
151 const struct GNUNET_HashCode *query, 108 const struct GNUNET_HashCode *query,
152 const void *xquery, 109 const void *xquery,
153 size_t xquery_size) 110 size_t xquery_size)
154{ 111{
155 return GNUNET_OK; 112 return GNUNET_SYSERR;
156} 113}
157 114
158 115
@@ -161,19 +118,17 @@ block_plugin_template_check_query (void *cls,
161 * 118 *
162 * @param cls closure 119 * @param cls closure
163 * @param type block type 120 * @param type block type
164 * @param query key for the block (hash), must match exactly
165 * @param block block data to validate 121 * @param block block data to validate
166 * @param block_size number of bytes in @a block 122 * @param block_size number of bytes in @a block
167 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 123 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not, #GNUNET_SYSERR if not supported
168 */ 124 */
169static enum GNUNET_GenericReturnValue 125static enum GNUNET_GenericReturnValue
170block_plugin_template_check_block (void *cls, 126block_plugin_template_check_block (void *cls,
171 enum GNUNET_BLOCK_Type type, 127 enum GNUNET_BLOCK_Type type,
172 const struct GNUNET_HashCode *query,
173 const void *block, 128 const void *block,
174 size_t block_size) 129 size_t block_size)
175{ 130{
176 return GNUNET_OK; 131 return GNUNET_SYSERR;
177} 132}
178 133
179 134
@@ -195,16 +150,16 @@ block_plugin_template_check_block (void *cls,
195 */ 150 */
196static enum GNUNET_BLOCK_ReplyEvaluationResult 151static enum GNUNET_BLOCK_ReplyEvaluationResult
197block_plugin_template_check_reply ( 152block_plugin_template_check_reply (
198 void *cls, 153 void *cls,
199 enum GNUNET_BLOCK_Type type, 154 enum GNUNET_BLOCK_Type type,
200 struct GNUNET_BLOCK_Group *group, 155 struct GNUNET_BLOCK_Group *group,
201 const struct GNUNET_HashCode *query, 156 const struct GNUNET_HashCode *query,
202 const void *xquery, 157 const void *xquery,
203 size_t xquery_size, 158 size_t xquery_size,
204 const void *reply_block, 159 const void *reply_block,
205 size_t reply_block_size) 160 size_t reply_block_size)
206{ 161{
207 return GNUNET_BLOCK_REPLY_OK_MORE; 162 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
208} 163}
209 164
210 165
@@ -245,7 +200,6 @@ libgnunet_plugin_block_template_init (void *cls)
245 struct GNUNET_BLOCK_PluginFunctions *api; 200 struct GNUNET_BLOCK_PluginFunctions *api;
246 201
247 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 202 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
248 api->evaluate = &block_plugin_template_evaluate;
249 api->get_key = &block_plugin_template_get_key; 203 api->get_key = &block_plugin_template_get_key;
250 api->check_query = &block_plugin_template_check_query; 204 api->check_query = &block_plugin_template_check_query;
251 api->check_block = &block_plugin_template_check_block; 205 api->check_block = &block_plugin_template_check_block;
diff --git a/src/block/plugin_block_test.c b/src/block/plugin_block_test.c
index fd643c4dc..05d379387 100644
--- a/src/block/plugin_block_test.c
+++ b/src/block/plugin_block_test.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2010 GNUnet e.V. 3 Copyright (C) 2010, 2021, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -90,59 +90,6 @@ block_plugin_test_create_group (void *cls,
90 90
91 91
92/** 92/**
93 * Function called to validate a reply or a request. For
94 * request evaluation, simply pass "NULL" for the reply_block.
95 *
96 * @param cls closure
97 * @param ctx block context
98 * @param type block type
99 * @param group group to check against
100 * @param eo control flags
101 * @param query original query (hash)
102 * @param xquery extrended query data (can be NULL, depending on type)
103 * @param xquery_size number of bytes in @a xquery
104 * @param reply_block response to validate
105 * @param reply_block_size number of bytes in @a reply_block
106 * @return characterization of result
107 */
108static enum GNUNET_BLOCK_EvaluationResult
109block_plugin_test_evaluate (void *cls,
110 struct GNUNET_BLOCK_Context *ctx,
111 enum GNUNET_BLOCK_Type type,
112 struct GNUNET_BLOCK_Group *group,
113 enum GNUNET_BLOCK_EvaluationOptions eo,
114 const struct GNUNET_HashCode *query,
115 const void *xquery,
116 size_t xquery_size,
117 const void *reply_block,
118 size_t reply_block_size)
119{
120 struct GNUNET_HashCode chash;
121
122 if (GNUNET_BLOCK_TYPE_TEST != type)
123 {
124 GNUNET_break (0);
125 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
126 }
127 if (0 != xquery_size)
128 {
129 GNUNET_break_op (0);
130 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
131 }
132 if (NULL == reply_block)
133 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
134 GNUNET_CRYPTO_hash (reply_block,
135 reply_block_size,
136 &chash);
137 if (GNUNET_YES ==
138 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
139 &chash))
140 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
141 return GNUNET_BLOCK_EVALUATION_OK_MORE;
142}
143
144
145/**
146 * Function called to validate a query. 93 * Function called to validate a query.
147 * 94 *
148 * @param cls closure 95 * @param cls closure
@@ -151,15 +98,18 @@ block_plugin_test_evaluate (void *cls,
151 * @param query original query (hash) 98 * @param query original query (hash)
152 * @param xquery extrended query data (can be NULL, depending on type) 99 * @param xquery extrended query data (can be NULL, depending on type)
153 * @param xquery_size number of bytes in @a xquery 100 * @param xquery_size number of bytes in @a xquery
154 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not 101 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not, #GNUNET_SYSERR if @a type is not supported
155 */ 102 */
156static enum GNUNET_GenericReturnValue 103static enum GNUNET_GenericReturnValue
157block_plugin_test_check_query (void *cls, 104block_plugin_test_check_query (void *cls,
158 enum GNUNET_BLOCK_Type type, 105 enum GNUNET_BLOCK_Type type,
159 const struct GNUNET_HashCode *query, 106 const struct GNUNET_HashCode *query,
160 const void *xquery, 107 const void *xquery,
161 size_t xquery_size) 108 size_t xquery_size)
162{ 109{
110 (void) cls;
111 (void) query;
112 (void) xquery;
163 if (GNUNET_BLOCK_TYPE_TEST != type) 113 if (GNUNET_BLOCK_TYPE_TEST != type)
164 { 114 {
165 GNUNET_break (0); 115 GNUNET_break (0);
@@ -168,9 +118,9 @@ block_plugin_test_check_query (void *cls,
168 if (0 != xquery_size) 118 if (0 != xquery_size)
169 { 119 {
170 GNUNET_break_op (0); 120 GNUNET_break_op (0);
171 return GNUNET_SYSERR; 121 return GNUNET_NO;
172 } 122 }
173 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; 123 return GNUNET_OK;
174} 124}
175 125
176 126
@@ -179,18 +129,19 @@ block_plugin_test_check_query (void *cls,
179 * 129 *
180 * @param cls closure 130 * @param cls closure
181 * @param type block type 131 * @param type block type
182 * @param query key for the block (hash), must match exactly
183 * @param block block data to validate 132 * @param block block data to validate
184 * @param block_size number of bytes in @a block 133 * @param block_size number of bytes in @a block
185 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 134 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not, #GNUNET_SYSERR if @a type is not supported
186 */ 135 */
187static enum GNUNET_GenericReturnValue 136static enum GNUNET_GenericReturnValue
188block_plugin_test_check_block (void *cls, 137block_plugin_test_check_block (void *cls,
189 enum GNUNET_BLOCK_Type type, 138 enum GNUNET_BLOCK_Type type,
190 const struct GNUNET_HashCode *query, 139 const void *block,
191 const void *block, 140 size_t block_size)
192 size_t block_size)
193{ 141{
142 (void) cls;
143 (void) block;
144 (void) block_size;
194 if (GNUNET_BLOCK_TYPE_TEST != type) 145 if (GNUNET_BLOCK_TYPE_TEST != type)
195 { 146 {
196 GNUNET_break (0); 147 GNUNET_break (0);
@@ -218,16 +169,20 @@ block_plugin_test_check_block (void *cls,
218 */ 169 */
219static enum GNUNET_BLOCK_ReplyEvaluationResult 170static enum GNUNET_BLOCK_ReplyEvaluationResult
220block_plugin_test_check_reply (void *cls, 171block_plugin_test_check_reply (void *cls,
221 enum GNUNET_BLOCK_Type type, 172 enum GNUNET_BLOCK_Type type,
222 struct GNUNET_BLOCK_Group *group, 173 struct GNUNET_BLOCK_Group *group,
223 const struct GNUNET_HashCode *query, 174 const struct GNUNET_HashCode *query,
224 const void *xquery, 175 const void *xquery,
225 size_t xquery_size, 176 size_t xquery_size,
226 const void *reply_block, 177 const void *reply_block,
227 size_t reply_block_size) 178 size_t reply_block_size)
228{ 179{
229 struct GNUNET_HashCode chash; 180 struct GNUNET_HashCode chash;
230 181
182 (void) cls;
183 (void) query;
184 (void) xquery;
185 (void) xquery_size;
231 if (GNUNET_BLOCK_TYPE_TEST != type) 186 if (GNUNET_BLOCK_TYPE_TEST != type)
232 { 187 {
233 GNUNET_break (0); 188 GNUNET_break (0);
@@ -252,8 +207,7 @@ block_plugin_test_check_reply (void *cls,
252 * @param block block to get the key for 207 * @param block block to get the key for
253 * @param block_size number of bytes in @a block 208 * @param block_size number of bytes in @a block
254 * @param key set to the key (query) for the given block 209 * @param key set to the key (query) for the given block
255 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 210 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported, #GNUNET_NO if extracting a key from a block of this type does not work
256 * (or if extracting a key from a block of this type does not work)
257 */ 211 */
258static enum GNUNET_GenericReturnValue 212static enum GNUNET_GenericReturnValue
259block_plugin_test_get_key (void *cls, 213block_plugin_test_get_key (void *cls,
@@ -262,9 +216,16 @@ block_plugin_test_get_key (void *cls,
262 size_t block_size, 216 size_t block_size,
263 struct GNUNET_HashCode *key) 217 struct GNUNET_HashCode *key)
264{ 218{
265 /* always fails since there is no fixed relationship between 219 (void) cls;
266 * keys and values for test values */ 220 (void) block;
267 return GNUNET_SYSERR; 221 (void) block_size;
222 (void) key;
223 if (GNUNET_BLOCK_TYPE_TEST != type)
224 {
225 GNUNET_break (0);
226 return GNUNET_SYSERR;
227 }
228 return GNUNET_NO;
268} 229}
269 230
270 231
@@ -284,7 +245,6 @@ libgnunet_plugin_block_test_init (void *cls)
284 struct GNUNET_BLOCK_PluginFunctions *api; 245 struct GNUNET_BLOCK_PluginFunctions *api;
285 246
286 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 247 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
287 api->evaluate = &block_plugin_test_evaluate;
288 api->get_key = &block_plugin_test_get_key; 248 api->get_key = &block_plugin_test_get_key;
289 api->check_query = &block_plugin_test_check_query; 249 api->check_query = &block_plugin_test_check_query;
290 api->check_block = &block_plugin_test_check_block; 250 api->check_block = &block_plugin_test_check_block;
diff --git a/src/consensus/plugin_block_consensus.c b/src/consensus/plugin_block_consensus.c
index 430a2c0cb..f30b9b0d7 100644
--- a/src/consensus/plugin_block_consensus.c
+++ b/src/consensus/plugin_block_consensus.c
@@ -47,57 +47,6 @@ struct BlockContext
47}; 47};
48 48
49 49
50/**
51 * Function called to validate a reply or a request. For
52 * request evaluation, simply pass "NULL" for the reply_block.
53 *
54 * @param cls closure
55 * @param ctx context
56 * @param type block type
57 * @param group block group to use
58 * @param eo control flags
59 * @param query original query (hash)
60 * @param xquery extrended query data (can be NULL, depending on type)
61 * @param xquery_size number of bytes in xquery
62 * @param reply_block response to validate
63 * @param reply_block_size number of bytes in reply block
64 * @return characterization of result
65 */
66static enum GNUNET_BLOCK_EvaluationResult
67block_plugin_consensus_evaluate (void *cls,
68 struct GNUNET_BLOCK_Context *ctx,
69 enum GNUNET_BLOCK_Type type,
70 struct GNUNET_BLOCK_Group *group,
71 enum GNUNET_BLOCK_EvaluationOptions eo,
72 const struct GNUNET_HashCode *query,
73 const void *xquery,
74 size_t xquery_size,
75 const void *reply_block,
76 size_t reply_block_size)
77{
78 struct BlockContext *bctx = cls;
79 const struct ConsensusElement *ce = reply_block;
80
81 if (reply_block_size < sizeof(struct ConsensusElement))
82 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
83 if ( (0 != ce->marker) ||
84 (0 == ce->payload_type) )
85 return GNUNET_BLOCK_EVALUATION_OK_MORE;
86
87 if (NULL == bctx->bc)
88 bctx->bc = GNUNET_BLOCK_context_create (bctx->cfg);
89 return GNUNET_BLOCK_evaluate (bctx->bc,
90 type,
91 group,
92 eo,
93 query,
94 xquery,
95 xquery_size,
96 &ce[1],
97 reply_block_size
98 - sizeof(struct ConsensusElement));
99}
100
101 50
102/** 51/**
103 * Function called to validate a query. 52 * Function called to validate a query.
@@ -128,7 +77,6 @@ block_plugin_consensus_check_query (void *cls,
128 * 77 *
129 * @param cls closure 78 * @param cls closure
130 * @param type block type 79 * @param type block type
131 * @param query key for the block (hash), must match exactly
132 * @param block block data to validate 80 * @param block block data to validate
133 * @param block_size number of bytes in @a block 81 * @param block_size number of bytes in @a block
134 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 82 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
@@ -136,7 +84,6 @@ block_plugin_consensus_check_query (void *cls,
136static enum GNUNET_GenericReturnValue 84static enum GNUNET_GenericReturnValue
137block_plugin_consensus_check_block (void *cls, 85block_plugin_consensus_check_block (void *cls,
138 enum GNUNET_BLOCK_Type type, 86 enum GNUNET_BLOCK_Type type,
139 const struct GNUNET_HashCode *query,
140 const void *block, 87 const void *block,
141 size_t block_size) 88 size_t block_size)
142{ 89{
@@ -144,7 +91,10 @@ block_plugin_consensus_check_block (void *cls,
144 const struct ConsensusElement *ce = block; 91 const struct ConsensusElement *ce = block;
145 92
146 if (block_size < sizeof(*ce)) 93 if (block_size < sizeof(*ce))
94 {
95 GNUNET_break_op (0);
147 return GNUNET_NO; 96 return GNUNET_NO;
97 }
148 if ( (0 != ce->marker) || 98 if ( (0 != ce->marker) ||
149 (0 == ce->payload_type) ) 99 (0 == ce->payload_type) )
150 return GNUNET_OK; 100 return GNUNET_OK;
@@ -152,7 +102,6 @@ block_plugin_consensus_check_block (void *cls,
152 ctx->bc = GNUNET_BLOCK_context_create (ctx->cfg); 102 ctx->bc = GNUNET_BLOCK_context_create (ctx->cfg);
153 return GNUNET_BLOCK_check_block (ctx->bc, 103 return GNUNET_BLOCK_check_block (ctx->bc,
154 ntohl (ce->payload_type), 104 ntohl (ce->payload_type),
155 query,
156 &ce[1], 105 &ce[1],
157 block_size - sizeof(*ce)); 106 block_size - sizeof(*ce));
158} 107}
@@ -188,8 +137,7 @@ block_plugin_consensus_check_reply (
188 struct BlockContext *ctx = cls; 137 struct BlockContext *ctx = cls;
189 const struct ConsensusElement *ce = reply_block; 138 const struct ConsensusElement *ce = reply_block;
190 139
191 if (reply_block_size < sizeof(struct ConsensusElement)) 140 GNUNET_assert (reply_block_size >= sizeof(struct ConsensusElement));
192 return GNUNET_NO;
193 if ( (0 != ce->marker) || 141 if ( (0 != ce->marker) ||
194 (0 == ce->payload_type) ) 142 (0 == ce->payload_type) )
195 return GNUNET_BLOCK_REPLY_OK_MORE; 143 return GNUNET_BLOCK_REPLY_OK_MORE;
@@ -246,7 +194,6 @@ libgnunet_plugin_block_consensus_init (void *cls)
246 ctx->cfg = cfg; 194 ctx->cfg = cfg;
247 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 195 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
248 api->cls = ctx; 196 api->cls = ctx;
249 api->evaluate = &block_plugin_consensus_evaluate;
250 api->get_key = &block_plugin_consensus_get_key; 197 api->get_key = &block_plugin_consensus_get_key;
251 api->check_query = &block_plugin_consensus_check_query; 198 api->check_query = &block_plugin_consensus_check_query;
252 api->check_block = &block_plugin_consensus_check_block; 199 api->check_block = &block_plugin_consensus_check_block;
diff --git a/src/consensus/test_consensus.conf b/src/consensus/test_consensus.conf
index 67b366405..df7fb6861 100644
--- a/src/consensus/test_consensus.conf
+++ b/src/consensus/test_consensus.conf
@@ -3,7 +3,7 @@ GNUNET_TEST_HOME = $GNUNET_TMP/test-consensus/
3 3
4[consensus] 4[consensus]
5#OPTIONS = -L INFO 5#OPTIONS = -L INFO
6BINARY = gnunet-service-evil-consensus 6BINARY = gnunet-service-consensus
7 7
8#PREFIX = valgrind 8#PREFIX = valgrind
9 9
diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c
index 944a99aad..761ab801f 100644
--- a/src/datacache/datacache.c
+++ b/src/datacache/datacache.c
@@ -114,11 +114,11 @@ env_delete_notify (void *cls,
114 h->utilization -= size; 114 h->utilization -= size;
115 GNUNET_CONTAINER_bloomfilter_remove (h->filter, key); 115 GNUNET_CONTAINER_bloomfilter_remove (h->filter, key);
116 GNUNET_STATISTICS_update (h->stats, 116 GNUNET_STATISTICS_update (h->stats,
117 gettext_noop ("# bytes stored"), 117 "# bytes stored",
118 -(long long) size, 118 -(long long) size,
119 GNUNET_NO); 119 GNUNET_NO);
120 GNUNET_STATISTICS_update (h->stats, 120 GNUNET_STATISTICS_update (h->stats,
121 gettext_noop ("# items stored"), 121 "# items stored",
122 -1, 122 -1,
123 GNUNET_NO); 123 GNUNET_NO);
124} 124}
@@ -136,15 +136,25 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
136 const struct GNUNET_OS_ProjectData *pd; 136 const struct GNUNET_OS_ProjectData *pd;
137 137
138 if (GNUNET_OK != 138 if (GNUNET_OK !=
139 GNUNET_CONFIGURATION_get_value_size (cfg, section, "QUOTA", &quota)) 139 GNUNET_CONFIGURATION_get_value_size (cfg,
140 section,
141 "QUOTA",
142 &quota))
140 { 143 {
141 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "QUOTA"); 144 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
145 section,
146 "QUOTA");
142 return NULL; 147 return NULL;
143 } 148 }
144 if (GNUNET_OK != 149 if (GNUNET_OK !=
145 GNUNET_CONFIGURATION_get_value_string (cfg, section, "DATABASE", &name)) 150 GNUNET_CONFIGURATION_get_value_string (cfg,
151 section,
152 "DATABASE",
153 &name))
146 { 154 {
147 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "DATABASE"); 155 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
156 section,
157 "DATABASE");
148 return NULL; 158 return NULL;
149 } 159 }
150 bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */ 160 bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */
@@ -152,10 +162,14 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
152 ret = GNUNET_new (struct GNUNET_DATACACHE_Handle); 162 ret = GNUNET_new (struct GNUNET_DATACACHE_Handle);
153 163
154 if (GNUNET_YES != 164 if (GNUNET_YES !=
155 GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF")) 165 GNUNET_CONFIGURATION_get_value_yesno (cfg,
166 section,
167 "DISABLE_BF"))
156 { 168 {
157 if (GNUNET_YES != 169 if (GNUNET_YES !=
158 GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF_RC")) 170 GNUNET_CONFIGURATION_get_value_yesno (cfg,
171 section,
172 "DISABLE_BF_RC"))
159 { 173 {
160 ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom"); 174 ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom");
161 } 175 }
@@ -174,7 +188,8 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
174 5); /* approx. 3% false positives at max use */ 188 5); /* approx. 3% false positives at max use */
175 } 189 }
176 } 190 }
177 ret->stats = GNUNET_STATISTICS_create ("datacache", cfg); 191 ret->stats = GNUNET_STATISTICS_create ("datacache",
192 cfg);
178 ret->section = GNUNET_strdup (section); 193 ret->section = GNUNET_strdup (section);
179 ret->env.cfg = cfg; 194 ret->env.cfg = cfg;
180 ret->env.delete_notify = &env_delete_notify; 195 ret->env.delete_notify = &env_delete_notify;
@@ -182,25 +197,31 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
182 ret->env.cls = ret; 197 ret->env.cls = ret;
183 ret->env.delete_notify = &env_delete_notify; 198 ret->env.delete_notify = &env_delete_notify;
184 ret->env.quota = quota; 199 ret->env.quota = quota;
185 LOG (GNUNET_ERROR_TYPE_INFO, _ ("Loading `%s' datacache plugin\n"), name); 200 LOG (GNUNET_ERROR_TYPE_INFO,
186 GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name); 201 "Loading `%s' datacache plugin\n",
202 name);
203 GNUNET_asprintf (&libname,
204 "libgnunet_plugin_datacache_%s",
205 name);
187 ret->short_name = name; 206 ret->short_name = name;
188 ret->lib_name = libname; 207 ret->lib_name = libname;
189 /* Load the plugin within GNUnet's default context */ 208 /* Load the plugin within GNUnet's default context */
190 pd = GNUNET_OS_project_data_get (); 209 pd = GNUNET_OS_project_data_get ();
191 GNUNET_OS_init (GNUNET_OS_project_data_default ()); 210 GNUNET_OS_init (GNUNET_OS_project_data_default ());
192 ret->api = GNUNET_PLUGIN_load (libname, &ret->env); 211 ret->api = GNUNET_PLUGIN_load (libname,
212 &ret->env);
193 GNUNET_OS_init (pd); 213 GNUNET_OS_init (pd);
194 if (NULL == ret->api) 214 if (NULL == ret->api)
195 { 215 {
196 /* Try to load the plugin within the application's context 216 /* Try to load the plugin within the application's context
197 This normally happens when the application is not GNUnet itself but a 217 This normally happens when the application is not GNUnet itself but a
198 third party; inside GNUnet this is effectively a double failure. */ 218 third party; inside GNUnet this is effectively a double failure. */
199 ret->api = GNUNET_PLUGIN_load (libname, &ret->env); 219 ret->api = GNUNET_PLUGIN_load (libname,
220 &ret->env);
200 if (NULL == ret->api) 221 if (NULL == ret->api)
201 { 222 {
202 LOG (GNUNET_ERROR_TYPE_ERROR, 223 LOG (GNUNET_ERROR_TYPE_ERROR,
203 _ ("Failed to load datacache plugin for `%s'\n"), 224 "Failed to load datacache plugin for `%s'\n",
204 name); 225 name);
205 GNUNET_DATACACHE_destroy (ret); 226 GNUNET_DATACACHE_destroy (ret);
206 return NULL; 227 return NULL;
@@ -216,7 +237,9 @@ GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
216 if (NULL != h->filter) 237 if (NULL != h->filter)
217 GNUNET_CONTAINER_bloomfilter_free (h->filter); 238 GNUNET_CONTAINER_bloomfilter_free (h->filter);
218 if (NULL != h->api) 239 if (NULL != h->api)
219 GNUNET_break (NULL == GNUNET_PLUGIN_unload (h->lib_name, h->api)); 240 GNUNET_break (NULL ==
241 GNUNET_PLUGIN_unload (h->lib_name,
242 h->api));
220 GNUNET_free (h->lib_name); 243 GNUNET_free (h->lib_name);
221 GNUNET_free (h->short_name); 244 GNUNET_free (h->short_name);
222 GNUNET_free (h->section); 245 GNUNET_free (h->section);
@@ -270,17 +293,19 @@ GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
270 "Stored data under key `%s' in cache\n", 293 "Stored data under key `%s' in cache\n",
271 GNUNET_h2s (key)); 294 GNUNET_h2s (key));
272 if (NULL != h->filter) 295 if (NULL != h->filter)
273 GNUNET_CONTAINER_bloomfilter_add (h->filter, key); 296 GNUNET_CONTAINER_bloomfilter_add (h->filter,
297 key);
274 GNUNET_STATISTICS_update (h->stats, 298 GNUNET_STATISTICS_update (h->stats,
275 gettext_noop ("# bytes stored"), 299 "# bytes stored",
276 used, 300 used,
277 GNUNET_NO); 301 GNUNET_NO);
278 GNUNET_STATISTICS_update (h->stats, 302 GNUNET_STATISTICS_update (h->stats,
279 gettext_noop ("# items stored"), 303 "# items stored",
280 1, 304 1,
281 GNUNET_NO); 305 GNUNET_NO);
282 while (h->utilization + used > h->env.quota) 306 while (h->utilization + used > h->env.quota)
283 GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls)); 307 GNUNET_assert (GNUNET_OK ==
308 h->api->del (h->api->cls));
284 h->utilization += used; 309 h->utilization += used;
285 return GNUNET_OK; 310 return GNUNET_OK;
286} 311}
@@ -294,18 +319,18 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
294 void *iter_cls) 319 void *iter_cls)
295{ 320{
296 GNUNET_STATISTICS_update (h->stats, 321 GNUNET_STATISTICS_update (h->stats,
297 gettext_noop ("# requests received"), 322 "# requests received",
298 1, 323 1,
299 GNUNET_NO); 324 GNUNET_NO);
300 LOG (GNUNET_ERROR_TYPE_DEBUG, 325 LOG (GNUNET_ERROR_TYPE_DEBUG,
301 "Processing request for key `%s'\n", 326 "Processing request for key `%s'\n",
302 GNUNET_h2s (key)); 327 GNUNET_h2s (key));
303 if ((NULL != h->filter) && 328 if ((NULL != h->filter) &&
304 (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_test (h->filter, key))) 329 (GNUNET_OK !=
330 GNUNET_CONTAINER_bloomfilter_test (h->filter, key)))
305 { 331 {
306 GNUNET_STATISTICS_update (h->stats, 332 GNUNET_STATISTICS_update (h->stats,
307 gettext_noop ( 333 "# requests filtered by bloom filter",
308 "# requests filtered by bloom filter"),
309 1, 334 1,
310 GNUNET_NO); 335 GNUNET_NO);
311 LOG (GNUNET_ERROR_TYPE_DEBUG, 336 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -313,26 +338,33 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
313 GNUNET_h2s (key)); 338 GNUNET_h2s (key));
314 return 0; /* can not be present */ 339 return 0; /* can not be present */
315 } 340 }
316 return h->api->get (h->api->cls, key, type, iter, iter_cls); 341 return h->api->get (h->api->cls,
342 key,
343 type,
344 iter, iter_cls);
317} 345}
318 346
319 347
320unsigned int 348unsigned int
321GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h, 349GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h,
322 const struct GNUNET_HashCode *key, 350 const struct GNUNET_HashCode *key,
351 enum GNUNET_BLOCK_Type type,
323 unsigned int num_results, 352 unsigned int num_results,
324 GNUNET_DATACACHE_Iterator iter, 353 GNUNET_DATACACHE_Iterator iter,
325 void *iter_cls) 354 void *iter_cls)
326{ 355{
327 GNUNET_STATISTICS_update (h->stats, 356 GNUNET_STATISTICS_update (h->stats,
328 gettext_noop ( 357 "# proximity search requests received",
329 "# proximity search requests received"),
330 1, 358 1,
331 GNUNET_NO); 359 GNUNET_NO);
332 LOG (GNUNET_ERROR_TYPE_DEBUG, 360 LOG (GNUNET_ERROR_TYPE_DEBUG,
333 "Processing proximity search at `%s'\n", 361 "Processing proximity search at `%s'\n",
334 GNUNET_h2s (key)); 362 GNUNET_h2s (key));
335 return h->api->get_closest (h->api->cls, key, num_results, iter, iter_cls); 363 return h->api->get_closest (h->api->cls,
364 key,
365 type,
366 num_results,
367 iter, iter_cls);
336} 368}
337 369
338 370
diff --git a/src/datacache/plugin_datacache_heap.c b/src/datacache/plugin_datacache_heap.c
index fbd3aea9a..5b50468a5 100644
--- a/src/datacache/plugin_datacache_heap.c
+++ b/src/datacache/plugin_datacache_heap.c
@@ -158,7 +158,7 @@ struct PutContext
158 * @param value an existing value 158 * @param value an existing value
159 * @return #GNUNET_YES if not found (to continue to iterate) 159 * @return #GNUNET_YES if not found (to continue to iterate)
160 */ 160 */
161static int 161static enum GNUNET_GenericReturnValue
162put_cb (void *cls, 162put_cb (void *cls,
163 const struct GNUNET_HashCode *key, 163 const struct GNUNET_HashCode *key,
164 void *value) 164 void *value)
@@ -224,15 +224,20 @@ heap_plugin_put (void *cls,
224{ 224{
225 struct Plugin *plugin = cls; 225 struct Plugin *plugin = cls;
226 struct Value *val; 226 struct Value *val;
227 struct PutContext put_ctx; 227 struct PutContext put_ctx = {
228 228 .data = data,
229 put_ctx.found = GNUNET_NO; 229 .size = size,
230 put_ctx.data = data; 230 .path_info = path_info,
231 put_ctx.size = size; 231 .path_info_len = path_info_len,
232 put_ctx.path_info = path_info; 232 .discard_time = discard_time,
233 put_ctx.path_info_len = path_info_len; 233 .type = type
234 put_ctx.discard_time = discard_time; 234 };
235 put_ctx.type = type; 235
236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
237 "Storing %u bytes under key %s with path length %u\n",
238 (unsigned int) size,
239 GNUNET_h2s (key),
240 path_info_len);
236 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->map, 241 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->map,
237 key, 242 key,
238 &put_cb, 243 &put_cb,
@@ -313,12 +318,25 @@ get_cb (void *cls,
313 struct Value *val = value; 318 struct Value *val = value;
314 int ret; 319 int ret;
315 320
316 if ((get_ctx->type != val->type) && 321 if ( (get_ctx->type != val->type) &&
317 (GNUNET_BLOCK_TYPE_ANY != get_ctx->type)) 322 (GNUNET_BLOCK_TYPE_ANY != get_ctx->type) )
323 {
324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
325 "Result for key %s does not match block type %d\n",
326 GNUNET_h2s (key),
327 get_ctx->type);
318 return GNUNET_OK; 328 return GNUNET_OK;
319 if (0 == 329 }
320 GNUNET_TIME_absolute_get_remaining (val->discard_time).rel_value_us) 330 if (GNUNET_TIME_absolute_is_past (val->discard_time))
331 {
332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
333 "Result for key %s is expired\n",
334 GNUNET_h2s (key));
321 return GNUNET_OK; 335 return GNUNET_OK;
336 }
337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
338 "Found result for key %s\n",
339 GNUNET_h2s (key));
322 if (NULL != get_ctx->iter) 340 if (NULL != get_ctx->iter)
323 ret = get_ctx->iter (get_ctx->iter_cls, 341 ret = get_ctx->iter (get_ctx->iter_cls,
324 key, 342 key,
@@ -409,13 +427,16 @@ struct GetClosestContext
409{ 427{
410 struct Value **values; 428 struct Value **values;
411 429
430 const struct GNUNET_HashCode *key;
431
432 enum GNUNET_BLOCK_Type type;
433
412 unsigned int num_results; 434 unsigned int num_results;
413 435
414 const struct GNUNET_HashCode *key;
415}; 436};
416 437
417 438
418static int 439static enum GNUNET_GenericReturnValue
419find_closest (void *cls, 440find_closest (void *cls,
420 const struct GNUNET_HashCode *key, 441 const struct GNUNET_HashCode *key,
421 void *value) 442 void *value)
@@ -427,6 +448,9 @@ find_closest (void *cls,
427 if (1 != GNUNET_CRYPTO_hash_cmp (key, 448 if (1 != GNUNET_CRYPTO_hash_cmp (key,
428 gcc->key)) 449 gcc->key))
429 return GNUNET_OK; /* useless */ 450 return GNUNET_OK; /* useless */
451 if ( (val->type != gcc->type) &&
452 (GNUNET_BLOCK_TYPE_ANY != gcc->type) )
453 return GNUNET_OK; /* useless */
430 j = gcc->num_results; 454 j = gcc->num_results;
431 for (unsigned int i = 0; i < gcc->num_results; i++) 455 for (unsigned int i = 0; i < gcc->num_results; i++)
432 { 456 {
@@ -435,8 +459,9 @@ find_closest (void *cls,
435 j = i; 459 j = i;
436 break; 460 break;
437 } 461 }
438 if (1 == GNUNET_CRYPTO_hash_cmp (&gcc->values[i]->key, 462 if (1 ==
439 key)) 463 GNUNET_CRYPTO_hash_cmp (&gcc->values[i]->key,
464 key))
440 { 465 {
441 j = i; 466 j = i;
442 break; 467 break;
@@ -457,6 +482,7 @@ find_closest (void *cls,
457 * 482 *
458 * @param cls closure (internal context for the plugin) 483 * @param cls closure (internal context for the plugin)
459 * @param key area of the keyspace to look into 484 * @param key area of the keyspace to look into
485 * @param type desired block type for the replies
460 * @param num_results number of results that should be returned to @a iter 486 * @param num_results number of results that should be returned to @a iter
461 * @param iter maybe NULL (to just count) 487 * @param iter maybe NULL (to just count)
462 * @param iter_cls closure for @a iter 488 * @param iter_cls closure for @a iter
@@ -465,6 +491,7 @@ find_closest (void *cls,
465static unsigned int 491static unsigned int
466heap_plugin_get_closest (void *cls, 492heap_plugin_get_closest (void *cls,
467 const struct GNUNET_HashCode *key, 493 const struct GNUNET_HashCode *key,
494 enum GNUNET_BLOCK_Type type,
468 unsigned int num_results, 495 unsigned int num_results,
469 GNUNET_DATACACHE_Iterator iter, 496 GNUNET_DATACACHE_Iterator iter,
470 void *iter_cls) 497 void *iter_cls)
@@ -473,14 +500,15 @@ heap_plugin_get_closest (void *cls,
473 struct Value *values[num_results]; 500 struct Value *values[num_results];
474 struct GetClosestContext gcc = { 501 struct GetClosestContext gcc = {
475 .values = values, 502 .values = values,
476 .num_results = num_results, 503 .type = type,
504 .num_results = num_results * 2,
477 .key = key 505 .key = key
478 }; 506 };
479 507
480 GNUNET_CONTAINER_multihashmap_iterate (plugin->map, 508 GNUNET_CONTAINER_multihashmap_iterate (plugin->map,
481 &find_closest, 509 &find_closest,
482 &gcc); 510 &gcc);
483 for (unsigned int i = 0; i < num_results; i++) 511 for (unsigned int i = 0; i < num_results * 2; i++)
484 { 512 {
485 if (NULL == values[i]) 513 if (NULL == values[i])
486 return i; 514 return i;
@@ -493,7 +521,7 @@ heap_plugin_get_closest (void *cls,
493 values[i]->path_info_len, 521 values[i]->path_info_len,
494 values[i]->path_info); 522 values[i]->path_info);
495 } 523 }
496 return num_results; 524 return num_results * 2;
497} 525}
498 526
499 527
diff --git a/src/datacache/plugin_datacache_postgres.c b/src/datacache/plugin_datacache_postgres.c
index 6a44c44a5..1a83cda86 100644
--- a/src/datacache/plugin_datacache_postgres.c
+++ b/src/datacache/plugin_datacache_postgres.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2006, 2009, 2010, 2012, 2015, 2017, 2018 GNUnet e.V. 3 Copyright (C) 2006, 2009, 2010, 2012, 2015, 2017, 2018, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -109,9 +109,20 @@ init_connection (struct Plugin *plugin)
109 " ORDER BY prox ASC, discard_time ASC LIMIT 1", 109 " ORDER BY prox ASC, discard_time ASC LIMIT 1",
110 0), 110 0),
111 GNUNET_PQ_make_prepare ("get_closest", 111 GNUNET_PQ_make_prepare ("get_closest",
112 "SELECT discard_time,type,value,path,key FROM gn011dc " 112 "(SELECT discard_time,type,value,path,key FROM gn011dc"
113 "WHERE key>=$1 AND discard_time >= $2 ORDER BY key ASC LIMIT $3", 113 " WHERE key >= $1"
114 3), 114 " AND discard_time >= $2"
115 " AND ( (type = $3) OR ( 0 = $3) )"
116 " ORDER BY key ASC"
117 " LIMIT $4)"
118 " UNION "
119 "(SELECT discard_time,type,value,path,key FROM gn011dc"
120 " WHERE key <= $1"
121 " AND discard_time >= $2"
122 " AND ( (type = $3) OR ( 0 = $3) )"
123 " ORDER BY key DESC"
124 " LIMIT $4)",
125 4),
115 GNUNET_PQ_make_prepare ("delrow", 126 GNUNET_PQ_make_prepare ("delrow",
116 "DELETE FROM gn011dc WHERE oid=$1", 127 "DELETE FROM gn011dc WHERE oid=$1",
117 1), 128 1),
@@ -511,6 +522,7 @@ extract_result_cb (void *cls,
511 * 522 *
512 * @param cls closure (internal context for the plugin) 523 * @param cls closure (internal context for the plugin)
513 * @param key area of the keyspace to look into 524 * @param key area of the keyspace to look into
525 * @param type desired block type for the replies
514 * @param num_results number of results that should be returned to @a iter 526 * @param num_results number of results that should be returned to @a iter
515 * @param iter maybe NULL (to just count) 527 * @param iter maybe NULL (to just count)
516 * @param iter_cls closure for @a iter 528 * @param iter_cls closure for @a iter
@@ -519,16 +531,19 @@ extract_result_cb (void *cls,
519static unsigned int 531static unsigned int
520postgres_plugin_get_closest (void *cls, 532postgres_plugin_get_closest (void *cls,
521 const struct GNUNET_HashCode *key, 533 const struct GNUNET_HashCode *key,
534 enum GNUNET_BLOCK_Type type,
522 unsigned int num_results, 535 unsigned int num_results,
523 GNUNET_DATACACHE_Iterator iter, 536 GNUNET_DATACACHE_Iterator iter,
524 void *iter_cls) 537 void *iter_cls)
525{ 538{
526 struct Plugin *plugin = cls; 539 struct Plugin *plugin = cls;
527 uint32_t num_results32 = (uint32_t) num_results; 540 uint32_t num_results32 = (uint32_t) num_results;
541 uint32_t type32 = (uint32_t) type;
528 struct GNUNET_TIME_Absolute now; 542 struct GNUNET_TIME_Absolute now;
529 struct GNUNET_PQ_QueryParam params[] = { 543 struct GNUNET_PQ_QueryParam params[] = {
530 GNUNET_PQ_query_param_auto_from_type (key), 544 GNUNET_PQ_query_param_auto_from_type (key),
531 GNUNET_PQ_query_param_absolute_time (&now), 545 GNUNET_PQ_query_param_absolute_time (&now),
546 GNUNET_PQ_query_param_uint32 (&type32),
532 GNUNET_PQ_query_param_uint32 (&num_results32), 547 GNUNET_PQ_query_param_uint32 (&num_results32),
533 GNUNET_PQ_query_param_end 548 GNUNET_PQ_query_param_end
534 }; 549 };
diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c
index d08b32caf..6f2165433 100644
--- a/src/datacache/plugin_datacache_sqlite.c
+++ b/src/datacache/plugin_datacache_sqlite.c
@@ -454,6 +454,7 @@ sqlite_plugin_del (void *cls)
454 * 454 *
455 * @param cls closure (internal context for the plugin) 455 * @param cls closure (internal context for the plugin)
456 * @param key area of the keyspace to look into 456 * @param key area of the keyspace to look into
457 * @param type desired block type for the replies
457 * @param num_results number of results that should be returned to @a iter 458 * @param num_results number of results that should be returned to @a iter
458 * @param iter maybe NULL (to just count) 459 * @param iter maybe NULL (to just count)
459 * @param iter_cls closure for @a iter 460 * @param iter_cls closure for @a iter
@@ -462,11 +463,13 @@ sqlite_plugin_del (void *cls)
462static unsigned int 463static unsigned int
463sqlite_plugin_get_closest (void *cls, 464sqlite_plugin_get_closest (void *cls,
464 const struct GNUNET_HashCode *key, 465 const struct GNUNET_HashCode *key,
466 enum GNUNET_BLOCK_Type type,
465 unsigned int num_results, 467 unsigned int num_results,
466 GNUNET_DATACACHE_Iterator iter, 468 GNUNET_DATACACHE_Iterator iter,
467 void *iter_cls) 469 void *iter_cls)
468{ 470{
469 struct Plugin *plugin = cls; 471 struct Plugin *plugin = cls;
472 uint32_t type32 = type;
470 uint32_t num_results32 = num_results; 473 uint32_t num_results32 = num_results;
471 struct GNUNET_TIME_Absolute now; 474 struct GNUNET_TIME_Absolute now;
472 struct GNUNET_TIME_Absolute exp; 475 struct GNUNET_TIME_Absolute exp;
@@ -474,38 +477,46 @@ sqlite_plugin_get_closest (void *cls,
474 void *dat; 477 void *dat;
475 unsigned int cnt; 478 unsigned int cnt;
476 size_t psize; 479 size_t psize;
477 uint32_t type; 480 uint32_t rtype;
478 struct GNUNET_HashCode hc; 481 struct GNUNET_HashCode hc;
479 struct GNUNET_DHT_PathElement *path; 482 struct GNUNET_DHT_PathElement *path;
480 struct GNUNET_SQ_QueryParam params[] = 483 struct GNUNET_SQ_QueryParam params[] = {
481 { GNUNET_SQ_query_param_auto_from_type (key), 484 GNUNET_SQ_query_param_auto_from_type (key),
482 GNUNET_SQ_query_param_absolute_time (&now), 485 GNUNET_SQ_query_param_absolute_time (&now),
486 GNUNET_SQ_query_param_uint32 (&type32),
483 GNUNET_SQ_query_param_uint32 (&num_results32), 487 GNUNET_SQ_query_param_uint32 (&num_results32),
484 GNUNET_SQ_query_param_end }; 488 GNUNET_SQ_query_param_end
485 struct GNUNET_SQ_ResultSpec rs[] = 489 };
486 { GNUNET_SQ_result_spec_variable_size (&dat, &size), 490 struct GNUNET_SQ_ResultSpec rs[] = {
491 GNUNET_SQ_result_spec_variable_size (&dat, &size),
487 GNUNET_SQ_result_spec_absolute_time (&exp), 492 GNUNET_SQ_result_spec_absolute_time (&exp),
488 GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize), 493 GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize),
489 GNUNET_SQ_result_spec_uint32 (&type), 494 GNUNET_SQ_result_spec_uint32 (&rtype),
490 GNUNET_SQ_result_spec_auto_from_type (&hc), 495 GNUNET_SQ_result_spec_auto_from_type (&hc),
491 GNUNET_SQ_result_spec_end }; 496 GNUNET_SQ_result_spec_end
497 };
492 498
493 now = GNUNET_TIME_absolute_get (); 499 now = GNUNET_TIME_absolute_get ();
494 LOG (GNUNET_ERROR_TYPE_DEBUG, 500 LOG (GNUNET_ERROR_TYPE_DEBUG,
495 "Processing GET_CLOSEST for key `%s'\n", 501 "Processing GET_CLOSEST for key `%s'\n",
496 GNUNET_h2s (key)); 502 GNUNET_h2s (key));
497 if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_closest_stmt, params)) 503 if (GNUNET_OK !=
504 GNUNET_SQ_bind (plugin->get_closest_stmt,
505 params))
498 { 506 {
499 LOG_SQLITE (plugin->dbh, 507 LOG_SQLITE (plugin->dbh,
500 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 508 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
501 "sqlite3_bind_xxx"); 509 "sqlite3_bind_xxx");
502 GNUNET_SQ_reset (plugin->dbh, plugin->get_closest_stmt); 510 GNUNET_SQ_reset (plugin->dbh,
511 plugin->get_closest_stmt);
503 return 0; 512 return 0;
504 } 513 }
505 cnt = 0; 514 cnt = 0;
506 while (SQLITE_ROW == sqlite3_step (plugin->get_closest_stmt)) 515 while (SQLITE_ROW == sqlite3_step (plugin->get_closest_stmt))
507 { 516 {
508 if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->get_closest_stmt, rs)) 517 if (GNUNET_OK !=
518 GNUNET_SQ_extract_result (plugin->get_closest_stmt,
519 rs))
509 { 520 {
510 GNUNET_break (0); 521 GNUNET_break (0);
511 break; 522 break;
@@ -522,14 +533,22 @@ sqlite_plugin_get_closest (void *cls,
522 "Found %u-byte result at %s when processing GET_CLOSE\n", 533 "Found %u-byte result at %s when processing GET_CLOSE\n",
523 (unsigned int) size, 534 (unsigned int) size,
524 GNUNET_h2s (&hc)); 535 GNUNET_h2s (&hc));
525 if (GNUNET_OK != iter (iter_cls, &hc, size, dat, type, exp, psize, path)) 536 if (GNUNET_OK != iter (iter_cls,
537 &hc,
538 size,
539 dat,
540 rtype,
541 exp,
542 psize,
543 path))
526 { 544 {
527 GNUNET_SQ_cleanup_result (rs); 545 GNUNET_SQ_cleanup_result (rs);
528 break; 546 break;
529 } 547 }
530 GNUNET_SQ_cleanup_result (rs); 548 GNUNET_SQ_cleanup_result (rs);
531 } 549 }
532 GNUNET_SQ_reset (plugin->dbh, plugin->get_closest_stmt); 550 GNUNET_SQ_reset (plugin->dbh,
551 plugin->get_closest_stmt);
533 return cnt; 552 return cnt;
534} 553}
535 554
@@ -620,7 +639,7 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
620 &plugin->get_stmt)) || 639 &plugin->get_stmt)) ||
621 (SQLITE_OK != sq_prepare (plugin->dbh, 640 (SQLITE_OK != sq_prepare (plugin->dbh,
622 "SELECT _ROWID_,key,value FROM ds091" 641 "SELECT _ROWID_,key,value FROM ds091"
623 " WHERE expire < ?" 642 " WHERE expire < ?1"
624 " ORDER BY expire ASC LIMIT 1", 643 " ORDER BY expire ASC LIMIT 1",
625 &plugin->del_expired_stmt)) || 644 &plugin->del_expired_stmt)) ||
626 (SQLITE_OK != sq_prepare (plugin->dbh, 645 (SQLITE_OK != sq_prepare (plugin->dbh,
@@ -632,8 +651,19 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
632 &plugin->del_stmt)) || 651 &plugin->del_stmt)) ||
633 (SQLITE_OK != 652 (SQLITE_OK !=
634 sq_prepare (plugin->dbh, 653 sq_prepare (plugin->dbh,
635 "SELECT value,expire,path,type,key FROM ds091 " 654 "SELECT * FROM ("
636 "WHERE key>=? AND expire >= ? ORDER BY KEY ASC LIMIT ?", 655 " SELECT value,expire,path,type,key FROM ds091 "
656 " WHERE key>=?1 "
657 " AND expire >= ?2"
658 " AND ( (type=?3) or (0 == ?3) )"
659 " ORDER BY KEY ASC LIMIT ?4)"
660 "UNION "
661 "SELECT * FROM ("
662 " SELECT value,expire,path,type,key FROM ds091 "
663 " WHERE key<=?1 "
664 " AND expire >= ?2"
665 " AND ( (type=?3) or (0 == ?3) )"
666 " ORDER BY KEY DESC LIMIT ?4)",
637 &plugin->get_closest_stmt))) 667 &plugin->get_closest_stmt)))
638 { 668 {
639 LOG_SQLITE (plugin->dbh, 669 LOG_SQLITE (plugin->dbh,
diff --git a/src/datacache/plugin_datacache_template.c b/src/datacache/plugin_datacache_template.c
index 231413ce9..2f7b41dbe 100644
--- a/src/datacache/plugin_datacache_template.c
+++ b/src/datacache/plugin_datacache_template.c
@@ -116,6 +116,7 @@ template_plugin_del (void *cls)
116 * 116 *
117 * @param cls closure (internal context for the plugin) 117 * @param cls closure (internal context for the plugin)
118 * @param key area of the keyspace to look into 118 * @param key area of the keyspace to look into
119 * @param type desired block type for the replies
119 * @param num_results number of results that should be returned to @a iter 120 * @param num_results number of results that should be returned to @a iter
120 * @param iter maybe NULL (to just count) 121 * @param iter maybe NULL (to just count)
121 * @param iter_cls closure for @a iter 122 * @param iter_cls closure for @a iter
@@ -124,6 +125,7 @@ template_plugin_del (void *cls)
124static unsigned int 125static unsigned int
125template_plugin_get_closest (void *cls, 126template_plugin_get_closest (void *cls,
126 const struct GNUNET_HashCode *key, 127 const struct GNUNET_HashCode *key,
128 enum GNUNET_BLOCK_Type type,
127 unsigned int num_results, 129 unsigned int num_results,
128 GNUNET_DATACACHE_Iterator iter, 130 GNUNET_DATACACHE_Iterator iter,
129 void *iter_cls) 131 void *iter_cls)
diff --git a/src/dht/.gitignore b/src/dht/.gitignore
index 25b1daf28..bd8af1217 100644
--- a/src/dht/.gitignore
+++ b/src/dht/.gitignore
@@ -10,3 +10,4 @@ test_dht_monitor
10test_dht_multipeer 10test_dht_multipeer
11test_dht_tools.py 11test_dht_tools.py
12test_dht_twopeer 12test_dht_twopeer
13gnunet-dht-hello
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am
index be48fab02..68a17723d 100644
--- a/src/dht/Makefile.am
+++ b/src/dht/Makefile.am
@@ -50,7 +50,8 @@ libexec_PROGRAMS = \
50bin_PROGRAMS = \ 50bin_PROGRAMS = \
51 gnunet-dht-monitor \ 51 gnunet-dht-monitor \
52 gnunet-dht-get \ 52 gnunet-dht-get \
53 gnunet-dht-put 53 gnunet-dht-put \
54 gnunet-dht-hello
54 55
55noinst_PROGRAMS = \ 56noinst_PROGRAMS = \
56 gnunet-dht-profiler 57 gnunet-dht-profiler
@@ -58,8 +59,6 @@ noinst_PROGRAMS = \
58gnunet_service_dht_SOURCES = \ 59gnunet_service_dht_SOURCES = \
59 gnunet-service-dht.c gnunet-service-dht.h \ 60 gnunet-service-dht.c gnunet-service-dht.h \
60 gnunet-service-dht_datacache.c gnunet-service-dht_datacache.h \ 61 gnunet-service-dht_datacache.c gnunet-service-dht_datacache.h \
61 gnunet-service-dht_hello.c gnunet-service-dht_hello.h \
62 gnunet-service-dht_nse.c gnunet-service-dht_nse.h \
63 gnunet-service-dht_neighbours.c gnunet-service-dht_neighbours.h \ 62 gnunet-service-dht_neighbours.c gnunet-service-dht_neighbours.h \
64 gnunet-service-dht_routing.c gnunet-service-dht_routing.h 63 gnunet-service-dht_routing.c gnunet-service-dht_routing.h
65gnunet_service_dht_LDADD = \ 64gnunet_service_dht_LDADD = \
@@ -72,6 +71,7 @@ gnunet_service_dht_LDADD = \
72 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 71 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
73 $(top_builddir)/src/hello/libgnunethello.la \ 72 $(top_builddir)/src/hello/libgnunethello.la \
74 $(top_builddir)/src/block/libgnunetblock.la \ 73 $(top_builddir)/src/block/libgnunetblock.la \
74 $(top_builddir)/src/block/libgnunetblockgroup.la \
75 $(top_builddir)/src/datacache/libgnunetdatacache.la \ 75 $(top_builddir)/src/datacache/libgnunetdatacache.la \
76 $(top_builddir)/src/util/libgnunetutil.la \ 76 $(top_builddir)/src/util/libgnunetutil.la \
77 -lm 77 -lm
@@ -82,16 +82,22 @@ gnunet_dht_get_SOURCES = \
82 gnunet-dht-get.c 82 gnunet-dht-get.c
83gnunet_dht_get_LDADD = \ 83gnunet_dht_get_LDADD = \
84 libgnunetdht.la \ 84 libgnunetdht.la \
85 $(top_builddir)/src/core/libgnunetcore.la \
86 $(top_builddir)/src/util/libgnunetutil.la 85 $(top_builddir)/src/util/libgnunetutil.la
87gnunet_dht_get_LDFLAGS = \ 86gnunet_dht_get_LDFLAGS = \
88 $(GN_LIBINTL) 87 $(GN_LIBINTL)
89 88
89gnunet_dht_hello_SOURCES = \
90 gnunet-dht-hello.c
91gnunet_dht_hello_LDADD = \
92 libgnunetdht.la \
93 $(top_builddir)/src/util/libgnunetutil.la
94gnunet_dht_hello_LDFLAGS = \
95 $(GN_LIBINTL)
96
90gnunet_dht_put_SOURCES = \ 97gnunet_dht_put_SOURCES = \
91 gnunet-dht-put.c 98 gnunet-dht-put.c
92gnunet_dht_put_LDADD = \ 99gnunet_dht_put_LDADD = \
93 libgnunetdht.la \ 100 libgnunetdht.la \
94 $(top_builddir)/src/core/libgnunetcore.la \
95 $(top_builddir)/src/util/libgnunetutil.la 101 $(top_builddir)/src/util/libgnunetutil.la
96gnunet_dht_put_LDFLAGS = \ 102gnunet_dht_put_LDFLAGS = \
97 $(GN_LIBINTL) 103 $(GN_LIBINTL)
@@ -100,7 +106,6 @@ gnunet_dht_monitor_SOURCES = \
100 gnunet-dht-monitor.c 106 gnunet-dht-monitor.c
101gnunet_dht_monitor_LDADD = \ 107gnunet_dht_monitor_LDADD = \
102 libgnunetdht.la \ 108 libgnunetdht.la \
103 $(top_builddir)/src/core/libgnunetcore.la \
104 $(top_builddir)/src/util/libgnunetutil.la 109 $(top_builddir)/src/util/libgnunetutil.la
105gnunet_dht_monitor_LDFLAGS = \ 110gnunet_dht_monitor_LDFLAGS = \
106 $(GN_LIBINTL) 111 $(GN_LIBINTL)
@@ -199,7 +204,6 @@ test_dht_monitor_LDADD = \
199 libgnunetdht.la 204 libgnunetdht.la
200 205
201EXTRA_DIST = \ 206EXTRA_DIST = \
202 $(check_SCRIPTS) \
203 gnunet-service-dht_clients.c \ 207 gnunet-service-dht_clients.c \
204 test_dht_api_data.conf \ 208 test_dht_api_data.conf \
205 test_dht_api_peer1.conf \ 209 test_dht_api_peer1.conf \
@@ -209,7 +213,10 @@ EXTRA_DIST = \
209 test_dht_line.conf \ 213 test_dht_line.conf \
210 test_dht_tools.conf \ 214 test_dht_tools.conf \
211 test_dht_tools.py.in \ 215 test_dht_tools.py.in \
212 test_dht_multipeer_topology.dat 216 test_dht_multipeer_topology.dat \
217 dhtu_testbed_connect.sh \
218 dhtu_testbed_deploy.conf \
219 dhtu_testbed_deploy.sh
213 220
214if HAVE_PYTHON 221if HAVE_PYTHON
215check_SCRIPTS = \ 222check_SCRIPTS = \
diff --git a/src/dht/dht_api.c b/src/dht/dht_api.c
index 8389bbb95..474198004 100644
--- a/src/dht/dht_api.c
+++ b/src/dht/dht_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011, 2012, 2016, 2018 GNUnet e.V. 3 Copyright (C) 2009-2012, 2016, 2018, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -197,6 +197,40 @@ struct GNUNET_DHT_MonitorHandle
197 197
198 198
199/** 199/**
200 * Handle to get a HELLO URL from the DHT for manual bootstrapping.
201 */
202struct GNUNET_DHT_HelloGetHandle
203{
204
205 /**
206 * DLL.
207 */
208 struct GNUNET_DHT_HelloGetHandle *next;
209
210 /**
211 * DLL.
212 */
213 struct GNUNET_DHT_HelloGetHandle *prev;
214
215 /**
216 * Function to call with the result.
217 */
218 GNUNET_DHT_HelloGetCallback cb;
219
220 /**
221 * Closure for @a cb.
222 */
223 void *cb_cls;
224
225 /**
226 * Connection to the DHT service.
227 */
228 struct GNUNET_DHT_Handle *dht_handle;
229
230};
231
232
233/**
200 * Connection to the DHT service. 234 * Connection to the DHT service.
201 */ 235 */
202struct GNUNET_DHT_Handle 236struct GNUNET_DHT_Handle
@@ -232,6 +266,16 @@ struct GNUNET_DHT_Handle
232 struct GNUNET_DHT_PutHandle *put_tail; 266 struct GNUNET_DHT_PutHandle *put_tail;
233 267
234 /** 268 /**
269 * DLL.
270 */
271 struct GNUNET_DHT_HelloGetHandle *hgh_head;
272
273 /**
274 * DLL.
275 */
276 struct GNUNET_DHT_HelloGetHandle *hgh_tail;
277
278 /**
235 * Hash map containing the current outstanding unique GET requests 279 * Hash map containing the current outstanding unique GET requests
236 * (values are of type `struct GNUNET_DHT_GetHandle`). 280 * (values are of type `struct GNUNET_DHT_GetHandle`).
237 */ 281 */
@@ -517,9 +561,10 @@ handle_monitor_get (void *cls,
517 const struct GNUNET_DHT_MonitorGetMessage *msg) 561 const struct GNUNET_DHT_MonitorGetMessage *msg)
518{ 562{
519 struct GNUNET_DHT_Handle *handle = cls; 563 struct GNUNET_DHT_Handle *handle = cls;
520 struct GNUNET_DHT_MonitorHandle *mh;
521 564
522 for (mh = handle->monitor_head; NULL != mh; mh = mh->next) 565 for (struct GNUNET_DHT_MonitorHandle *mh = handle->monitor_head;
566 NULL != mh;
567 mh = mh->next)
523 { 568 {
524 if (NULL == mh->get_cb) 569 if (NULL == mh->get_cb)
525 continue; 570 continue;
@@ -582,10 +627,12 @@ handle_monitor_get_resp (void *cls,
582 const struct GNUNET_DHT_PathElement *path; 627 const struct GNUNET_DHT_PathElement *path;
583 uint32_t getl = ntohl (msg->get_path_length); 628 uint32_t getl = ntohl (msg->get_path_length);
584 uint32_t putl = ntohl (msg->put_path_length); 629 uint32_t putl = ntohl (msg->put_path_length);
585 struct GNUNET_DHT_MonitorHandle *mh; 630
586 631
587 path = (const struct GNUNET_DHT_PathElement *) &msg[1]; 632 path = (const struct GNUNET_DHT_PathElement *) &msg[1];
588 for (mh = handle->monitor_head; NULL != mh; mh = mh->next) 633 for (struct GNUNET_DHT_MonitorHandle *mh = handle->monitor_head;
634 NULL != mh;
635 mh = mh->next)
589 { 636 {
590 if (NULL == mh->get_resp_cb) 637 if (NULL == mh->get_resp_cb)
591 continue; 638 continue;
@@ -597,9 +644,9 @@ handle_monitor_get_resp (void *cls,
597 sizeof(struct GNUNET_HashCode))))) 644 sizeof(struct GNUNET_HashCode)))))
598 mh->get_resp_cb (mh->cb_cls, 645 mh->get_resp_cb (mh->cb_cls,
599 (enum GNUNET_BLOCK_Type) ntohl (msg->type), 646 (enum GNUNET_BLOCK_Type) ntohl (msg->type),
600 path, 647 &path[putl],
601 getl, 648 getl,
602 &path[getl], 649 path,
603 putl, 650 putl,
604 GNUNET_TIME_absolute_ntoh (msg->expiration_time), 651 GNUNET_TIME_absolute_ntoh (msg->expiration_time),
605 &msg->key, 652 &msg->key,
@@ -726,14 +773,21 @@ process_client_result (void *cls,
726 const struct GNUNET_DHT_ClientResultMessage *crm = cls; 773 const struct GNUNET_DHT_ClientResultMessage *crm = cls;
727 struct GNUNET_DHT_GetHandle *get_handle = value; 774 struct GNUNET_DHT_GetHandle *get_handle = value;
728 size_t msize = ntohs (crm->header.size) - sizeof(*crm); 775 size_t msize = ntohs (crm->header.size) - sizeof(*crm);
776 uint16_t type = ntohl (crm->type);
729 uint32_t put_path_length = ntohl (crm->put_path_length); 777 uint32_t put_path_length = ntohl (crm->put_path_length);
730 uint32_t get_path_length = ntohl (crm->get_path_length); 778 uint32_t get_path_length = ntohl (crm->get_path_length);
731 const struct GNUNET_DHT_PathElement *put_path; 779 const struct GNUNET_DHT_PathElement *put_path
732 const struct GNUNET_DHT_PathElement *get_path; 780 = (const struct GNUNET_DHT_PathElement *) &crm[1];
781 const struct GNUNET_DHT_PathElement *get_path
782 = &put_path[put_path_length];
783 const void *data
784 = &get_path[get_path_length];
785 size_t meta_length
786 = sizeof(struct GNUNET_DHT_PathElement) * (get_path_length
787 + put_path_length);
788 size_t data_length
789 = msize - meta_length;
733 struct GNUNET_HashCode hc; 790 struct GNUNET_HashCode hc;
734 size_t data_length;
735 size_t meta_length;
736 const void *data;
737 791
738 if (crm->unique_id != get_handle->unique_id) 792 if (crm->unique_id != get_handle->unique_id)
739 { 793 {
@@ -745,12 +799,14 @@ process_client_result (void *cls,
745 (unsigned long long) get_handle->unique_id); 799 (unsigned long long) get_handle->unique_id);
746 return GNUNET_YES; 800 return GNUNET_YES;
747 } 801 }
748 /* FIXME: might want to check that type matches */ 802 if ( (get_handle->type != GNUNET_BLOCK_TYPE_ANY) &&
749 meta_length = 803 (get_handle->type != type) )
750 sizeof(struct GNUNET_DHT_PathElement) * (get_path_length + put_path_length); 804 {
751 data_length = msize - meta_length; 805 /* type mismatch */
752 put_path = (const struct GNUNET_DHT_PathElement *) &crm[1]; 806 GNUNET_break (0);
753 get_path = &put_path[put_path_length]; 807 return GNUNET_YES;
808 }
809
754 { 810 {
755 char *pp; 811 char *pp;
756 char *gp; 812 char *gp;
@@ -768,7 +824,6 @@ process_client_result (void *cls,
768 GNUNET_free (gp); 824 GNUNET_free (gp);
769 GNUNET_free (pp); 825 GNUNET_free (pp);
770 } 826 }
771 data = &get_path[get_path_length];
772 /* remember that we've seen this result */ 827 /* remember that we've seen this result */
773 GNUNET_CRYPTO_hash (data, 828 GNUNET_CRYPTO_hash (data,
774 data_length, 829 data_length,
@@ -786,7 +841,7 @@ process_client_result (void *cls,
786 get_path_length, 841 get_path_length,
787 put_path, 842 put_path,
788 put_path_length, 843 put_path_length,
789 ntohl (crm->type), 844 type,
790 data_length, 845 data_length,
791 data); 846 data);
792 return GNUNET_YES; 847 return GNUNET_YES;
@@ -813,6 +868,53 @@ handle_client_result (void *cls,
813 868
814 869
815/** 870/**
871 * Process a client HELLO message received from the service.
872 *
873 * @param cls The DHT handle.
874 * @param hdr HELLO URL message from the service.
875 * @return #GNUNET_OK if @a hdr is well-formed
876 */
877static enum GNUNET_GenericReturnValue
878check_client_hello (void *cls,
879 const struct GNUNET_MessageHeader *hdr)
880{
881 uint16_t len = ntohs (hdr->size);
882 const char *buf = (const char *) &hdr[1];
883
884 (void) cls;
885 if ('\0' != buf[len - sizeof (*hdr) - 1])
886 {
887 GNUNET_break (0);
888 return GNUNET_SYSERR;
889 }
890 return GNUNET_OK;
891}
892
893
894/**
895 * Process a client HELLO message received from the service.
896 *
897 * @param cls The DHT handle.
898 * @param hdr HELLO URL message from the service.
899 */
900static void
901handle_client_hello (void *cls,
902 const struct GNUNET_MessageHeader *hdr)
903{
904 struct GNUNET_DHT_Handle *handle = cls;
905 const char *url = (const char *) &hdr[1];
906 struct GNUNET_DHT_HelloGetHandle *hgh;
907
908 while (NULL != (hgh = handle->hgh_head))
909 {
910 hgh->cb (hgh->cb_cls,
911 url);
912 GNUNET_DHT_hello_get_cancel (hgh);
913 }
914}
915
916
917/**
816 * Process a MQ PUT transmission notification. 918 * Process a MQ PUT transmission notification.
817 * 919 *
818 * @param cls The DHT handle. 920 * @param cls The DHT handle.
@@ -859,6 +961,10 @@ try_connect (struct GNUNET_DHT_Handle *h)
859 GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT, 961 GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT,
860 struct GNUNET_DHT_ClientResultMessage, 962 struct GNUNET_DHT_ClientResultMessage,
861 h), 963 h),
964 GNUNET_MQ_hd_var_size (client_hello,
965 GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL,
966 struct GNUNET_MessageHeader,
967 h),
862 GNUNET_MQ_handler_end () 968 GNUNET_MQ_handler_end ()
863 }; 969 };
864 970
@@ -1194,8 +1300,7 @@ GNUNET_DHT_pp2s (const struct GNUNET_DHT_PathElement *path,
1194 1300
1195 1301
1196unsigned int 1302unsigned int
1197GNUNET_DHT_verify_path (const struct GNUNET_HashCode *key, 1303GNUNET_DHT_verify_path (const void *data,
1198 const void *data,
1199 size_t data_size, 1304 size_t data_size,
1200 struct GNUNET_TIME_Absolute exp_time, 1305 struct GNUNET_TIME_Absolute exp_time,
1201 const struct GNUNET_DHT_PathElement *put_path, 1306 const struct GNUNET_DHT_PathElement *put_path,
@@ -1207,47 +1312,125 @@ GNUNET_DHT_verify_path (const struct GNUNET_HashCode *key,
1207 struct GNUNET_DHT_HopSignature hs = { 1312 struct GNUNET_DHT_HopSignature hs = {
1208 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DHT_HOP), 1313 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DHT_HOP),
1209 .purpose.size = htonl (sizeof (hs)), 1314 .purpose.size = htonl (sizeof (hs)),
1210 .expiration_time = GNUNET_TIME_absolute_hton (exp_time), 1315 .expiration_time = GNUNET_TIME_absolute_hton (exp_time)
1211 .key = *key,
1212 }; 1316 };
1317 const struct GNUNET_PeerIdentity *pred;
1318 const struct GNUNET_PeerIdentity *succ;
1213 unsigned int i; 1319 unsigned int i;
1214 1320
1215 if (0 == get_path_len + put_path_len) 1321 if (0 == get_path_len + put_path_len)
1216 return 0; 1322 return 0;
1217 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1218 "Verifying signatures with GPL: %u PPL: %u!\n", 1324 "%s is verifying signatures with GPL: %u PPL: %u!\n",
1325 GNUNET_i2s (me),
1219 get_path_len, 1326 get_path_len,
1220 put_path_len); 1327 put_path_len);
1328 for (unsigned int j = 0; j<put_path_len; j++)
1329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1330 "PP%u=%s\n",
1331 j,
1332 GNUNET_i2s (&put_path[j].pred));
1333 for (unsigned int j = 0; j<get_path_len; j++)
1334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1335 "GP%u=%s\n",
1336 j,
1337 GNUNET_i2s (&get_path[j].pred));
1338
1221 i = put_path_len + get_path_len - 1; 1339 i = put_path_len + get_path_len - 1;
1222 GNUNET_CRYPTO_hash (data, 1340 GNUNET_CRYPTO_hash (data,
1223 data_size, 1341 data_size,
1224 &hs.h_data); 1342 &hs.h_data);
1225 while (i > 0) 1343 while (i > 0)
1226 { 1344 {
1227 hs.pred = (i - 1 >= put_path_len) 1345 pred = (i - 1 >= put_path_len)
1228 ? get_path[i - put_path_len - 1].pred 1346 ? &get_path[i - put_path_len - 1].pred
1229 : put_path[i - 1].pred; 1347 : &put_path[i - 1].pred;
1230 if (i + 1 == get_path_len + put_path_len) 1348 if (i + 1 == get_path_len + put_path_len)
1231 hs.succ = *me; 1349 succ = me;
1232 else 1350 else
1233 hs.succ = (i + 1 >= put_path_len) 1351 succ = (i + 1 >= put_path_len)
1234 ? get_path[i + 1 - put_path_len].pred 1352 ? &get_path[i + 1 - put_path_len].pred
1235 : put_path[i + 1].pred; 1353 : &put_path[i + 1].pred;
1354 hs.pred = *pred;
1355 hs.succ = *succ;
1236 if (GNUNET_OK != 1356 if (GNUNET_OK !=
1237 GNUNET_CRYPTO_eddsa_verify ( 1357 GNUNET_CRYPTO_eddsa_verify (
1238 GNUNET_SIGNATURE_PURPOSE_DHT_HOP, 1358 GNUNET_SIGNATURE_PURPOSE_DHT_HOP,
1239 &hs, 1359 &hs,
1240 (i - 1 >= put_path_len) 1360 (i - 1 >= put_path_len)
1241 ? &get_path[i - put_path_len - 1].sig 1361 ? &get_path[i - put_path_len - 1].sig
1242 : &put_path[i - 1].sig, 1362 : &put_path[i - 1].sig,
1243 (i >= put_path_len) 1363 (i >= put_path_len)
1244 ? &get_path[i - put_path_len].pred.public_key 1364 ? &get_path[i - put_path_len].pred.public_key
1245 : &put_path[i].pred.public_key)) 1365 : &put_path[i].pred.public_key))
1366 {
1367 GNUNET_break_op (0);
1246 return i; 1368 return i;
1369 }
1247 i--; 1370 i--;
1248 } 1371 }
1249 return i; 1372 return i;
1250} 1373}
1251 1374
1252 1375
1376struct GNUNET_DHT_HelloGetHandle *
1377GNUNET_DHT_hello_get (struct GNUNET_DHT_Handle *dht_handle,
1378 GNUNET_DHT_HelloGetCallback cb,
1379 void *cb_cls)
1380{
1381 struct GNUNET_DHT_HelloGetHandle *hgh;
1382 struct GNUNET_MessageHeader *hdr;
1383 struct GNUNET_MQ_Envelope *env;
1384
1385 hgh = GNUNET_new (struct GNUNET_DHT_HelloGetHandle);
1386 hgh->cb = cb;
1387 hgh->cb_cls = cb_cls;
1388 hgh->dht_handle = dht_handle;
1389 GNUNET_CONTAINER_DLL_insert (dht_handle->hgh_head,
1390 dht_handle->hgh_tail,
1391 hgh);
1392 env = GNUNET_MQ_msg (hdr,
1393 GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_GET);
1394 GNUNET_MQ_send (dht_handle->mq,
1395 env);
1396 return hgh;
1397}
1398
1399
1400void
1401GNUNET_DHT_hello_get_cancel (struct GNUNET_DHT_HelloGetHandle *hgh)
1402{
1403 struct GNUNET_DHT_Handle *dht_handle = hgh->dht_handle;
1404
1405 GNUNET_CONTAINER_DLL_remove (dht_handle->hgh_head,
1406 dht_handle->hgh_tail,
1407 hgh);
1408 GNUNET_free (hgh);
1409}
1410
1411
1412void
1413GNUNET_DHT_hello_offer (struct GNUNET_DHT_Handle *dht_handle,
1414 const char *url,
1415 GNUNET_SCHEDULER_TaskCallback cb,
1416 void *cb_cls)
1417{
1418 struct GNUNET_MessageHeader *hdr;
1419 size_t slen = strlen (url) + 1;
1420 struct GNUNET_MQ_Envelope *env;
1421
1422 env = GNUNET_MQ_msg_extra (hdr,
1423 slen,
1424 GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL);
1425 memcpy (&hdr[1],
1426 url,
1427 slen);
1428 GNUNET_MQ_notify_sent (env,
1429 cb,
1430 cb_cls);
1431 GNUNET_MQ_send (dht_handle->mq,
1432 env);
1433}
1434
1435
1253/* end of dht_api.c */ 1436/* end of dht_api.c */
diff --git a/src/dht/dhtu_testbed_connect.sh b/src/dht/dhtu_testbed_connect.sh
new file mode 100755
index 000000000..871e9eb1b
--- /dev/null
+++ b/src/dht/dhtu_testbed_connect.sh
@@ -0,0 +1,31 @@
1#!/bin/bash
2# This file is in the public domain.
3
4# Helper script for dhtu_testbed_deploy.sh.
5# Do not invoke directly.
6
7n=$1
8CFG="/tmp/deployment/${n}.conf"
9HELLO=`gnunet-dht-hello -c $CFG`
10
11# Create dense topology:
12#for OFF in `seq 1 $MAX`
13#do
14# TCFG="/tmp/deployment/${OFF}.conf"
15# gnunet-dht-hello -c $TCFG $HELLO
16#done
17#exit 0
18
19# Create sparse topology:
20R=1
21while test `expr $R \* $R \* $R` -lt $MAX
22do
23 END=`expr $R \* $R`
24 for M in `seq $R $R $END`
25 do
26 OFF=`expr \( $n + $M \) % $MAX`
27 TCFG="/tmp/deployment/${OFF}.conf"
28 gnunet-dht-hello -c $TCFG $HELLO
29 done
30 R=`expr $R + 1`
31done
diff --git a/src/dht/dhtu_testbed_deploy.conf b/src/dht/dhtu_testbed_deploy.conf
new file mode 100644
index 000000000..59d69894a
--- /dev/null
+++ b/src/dht/dhtu_testbed_deploy.conf
@@ -0,0 +1,26 @@
1# This file is in the public domain.
2
3# Simple configuration template to deploy a DHT testbed
4# with peers using the IP underlay.
5
6[paths]
7GNUNET_DATA_HOME=/tmp/%N%
8
9[dht]
10UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-dht-%N%.sock
11
12[dhtu-ip]
13ENABLED = YES
14NSE = 10
15UDP_PORT = %N%
16
17[dhtu-gnunet]
18ENABLED = NO
19
20[statistics]
21DISABLE = YES
22
23[dhtcache]
24DATABASE = heap
25QUOTA = 50 MB
26DISABLE_BF_RC = YES
diff --git a/src/dht/dhtu_testbed_deploy.sh b/src/dht/dhtu_testbed_deploy.sh
new file mode 100755
index 000000000..908bbf685
--- /dev/null
+++ b/src/dht/dhtu_testbed_deploy.sh
@@ -0,0 +1,84 @@
1#!/bin/bash
2# This file is in the public domain.
3
4# We will use UDP ports above this number.
5MINPORT=10000
6
7# Cleanup to run whenever we exit
8function cleanup()
9{
10 for n in `jobs -p`
11 do
12 kill $n 2> /dev/null || true
13 done
14 wait
15}
16
17# Install cleanup handler (except for kill -9)
18trap cleanup EXIT
19
20if test -z "$1"
21then
22 echo "Call with the number of peers to launch."
23 exit 1
24fi
25
26if test ! -x `which parallel`
27then
28 echo "This script requires GNU parallel"
29 exit 1
30fi
31
32if test ! -x `which gnunet-service-dht`
33then
34 echo "This script requires gnunet-service-dht in \$PATH"
35 exit 1
36fi
37
38if test ! -x `which gnunet-dht-hello`
39then
40 echo "This script requires gnunet-dht-hello in \$PATH"
41 exit 1
42fi
43
44MAX=`expr $1 - 1`
45
46# export GNUNET_FORCE_LOG="dht*;;;;DEBUG"
47
48echo -n "Starting $1 peers "
49mkdir -p /tmp/deployment
50for n in `seq 0 $MAX`
51do
52 PORT=`expr $MINPORT + $n`
53 CFG="/tmp/deployment/${n}.conf"
54 cat dhtu_testbed_deploy.conf | sed -e "s/%N%/$PORT/" > $CFG
55 gnunet-service-dht -c $CFG &> /tmp/deployment/$n.log &
56 echo -n "."
57done
58
59echo ""
60echo "$1 peers ready".
61
62unset GNUNET_FORCE_LOG
63
64function connect()
65{
66 n=$1
67}
68
69echo -n "Connecting peers ..."
70
71export MAX
72if test 0 != $MAX
73then
74 seq 0 $MAX | parallel ./dhtu_testbed_connect.sh :::
75fi
76
77
78echo ""
79echo "Network ready. Press ENTER to terminate the testbed!"
80echo "Interact with peers using '-c /tmp/deployment/\$N.conf'"
81
82read
83
84exit 0
diff --git a/src/dht/gnunet-dht-get.c b/src/dht/gnunet-dht-get.c
index f1076490b..42ffe75ba 100644
--- a/src/dht/gnunet-dht-get.c
+++ b/src/dht/gnunet-dht-get.c
@@ -58,6 +58,11 @@ static unsigned int verbose;
58static int demultixplex_everywhere; 58static int demultixplex_everywhere;
59 59
60/** 60/**
61 * Use #GNUNET_DHT_RO_RECORD_ROUTE.
62 */
63static int record_route;
64
65/**
61 * Handle to the DHT 66 * Handle to the DHT
62 */ 67 */
63static struct GNUNET_DHT_Handle *dht_handle; 68static struct GNUNET_DHT_Handle *dht_handle;
@@ -160,9 +165,9 @@ get_result_iterator (void *cls,
160 : _ ("Result %d, type %d:\n"), 165 : _ ("Result %d, type %d:\n"),
161 result_count, 166 result_count,
162 type, 167 type,
163 (unsigned int) size, 168 (int) size,
164 (char *) data); 169 (char *) data);
165 if (verbose) 170 if (record_route && verbose)
166 { 171 {
167 fprintf (stdout, 172 fprintf (stdout,
168 " GET path: "); 173 " GET path: ");
@@ -200,6 +205,7 @@ run (void *cls,
200 const struct GNUNET_CONFIGURATION_Handle *c) 205 const struct GNUNET_CONFIGURATION_Handle *c)
201{ 206{
202 struct GNUNET_HashCode key; 207 struct GNUNET_HashCode key;
208 enum GNUNET_DHT_RouteOption ro;
203 209
204 cfg = c; 210 cfg = c;
205 if (NULL == query_key) 211 if (NULL == query_key)
@@ -228,13 +234,16 @@ run (void *cls,
228 GNUNET_h2s_full (&key)); 234 GNUNET_h2s_full (&key));
229 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL); 235 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
230 tt = GNUNET_SCHEDULER_add_delayed (timeout_request, &timeout_task, NULL); 236 tt = GNUNET_SCHEDULER_add_delayed (timeout_request, &timeout_task, NULL);
237 ro = GNUNET_DHT_RO_NONE;
238 if (demultixplex_everywhere)
239 ro |= GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE;
240 if (record_route)
241 ro |= GNUNET_DHT_RO_RECORD_ROUTE;
231 get_handle = GNUNET_DHT_get_start (dht_handle, 242 get_handle = GNUNET_DHT_get_start (dht_handle,
232 query_type, 243 query_type,
233 &key, 244 &key,
234 replication, 245 replication,
235 (demultixplex_everywhere) 246 ro,
236 ? GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
237 : GNUNET_DHT_RO_NONE,
238 NULL, 247 NULL,
239 0, 248 0,
240 &get_result_iterator, 249 &get_result_iterator,
@@ -265,6 +274,11 @@ main (int argc, char *const *argv)
265 "LEVEL", 274 "LEVEL",
266 gettext_noop ("how many parallel requests (replicas) to create"), 275 gettext_noop ("how many parallel requests (replicas) to create"),
267 &replication), 276 &replication),
277 GNUNET_GETOPT_option_flag (
278 'R',
279 "record",
280 gettext_noop ("use DHT's record route option"),
281 &record_route),
268 GNUNET_GETOPT_option_uint ( 282 GNUNET_GETOPT_option_uint (
269 't', 283 't',
270 "type", 284 "type",
diff --git a/src/dht/gnunet-dht-hello.c b/src/dht/gnunet-dht-hello.c
new file mode 100644
index 000000000..369ed5643
--- /dev/null
+++ b/src/dht/gnunet-dht-hello.c
@@ -0,0 +1,178 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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 */
20/**
21 * @file dht/gnunet-dht-hello.c
22 * @brief Obtain HELLO from DHT for bootstrapping
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_dht_service.h"
27
28#define LOG(kind, ...) GNUNET_log_from (kind, "dht-clients", __VA_ARGS__)
29
30/**
31 * Handle to the DHT
32 */
33static struct GNUNET_DHT_Handle *dht_handle;
34
35/**
36 * Handle to the DHT hello get operation.
37 */
38static struct GNUNET_DHT_HelloGetHandle *get_hello_handle;
39
40/**
41 * Global status value
42 */
43static int global_ret;
44
45
46/**
47 * Task run to clean up on shutdown.
48 *
49 * @param cls unused
50 */
51static void
52cleanup_task (void *cls)
53{
54 if (NULL != get_hello_handle)
55 {
56 GNUNET_DHT_hello_get_cancel (get_hello_handle);
57 get_hello_handle = NULL;
58 }
59 if (NULL != dht_handle)
60 {
61 GNUNET_DHT_disconnect (dht_handle);
62 dht_handle = NULL;
63 }
64}
65
66
67/**
68 * Task run when we are finished. Triggers shutdown.
69 *
70 * @param cls unused
71 */
72static void
73hello_done_cb (void *cls)
74{
75 GNUNET_SCHEDULER_shutdown ();
76}
77
78
79/**
80 * Function called on our HELLO.
81 *
82 * @param cls closure
83 * @param url the HELLO URL
84 */
85static void
86hello_result_cb (void *cls,
87 const char *url)
88{
89 get_hello_handle = NULL;
90 fprintf (stdout,
91 "%s\n",
92 url);
93 GNUNET_SCHEDULER_shutdown ();
94}
95
96
97/**
98 * Main function that will be run by the scheduler.
99 *
100 * @param cls closure, NULL
101 * @param args remaining command-line arguments
102 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
103 * @param cfg configuration
104 */
105static void
106run (void *cls,
107 char *const *args,
108 const char *cfgfile,
109 const struct GNUNET_CONFIGURATION_Handle *cfg)
110{
111 (void) cls;
112 (void) cfgfile;
113 GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
114 NULL);
115 if (NULL == (dht_handle = GNUNET_DHT_connect (cfg,
116 1)))
117 {
118 fprintf (stderr,
119 _ ("Failed to connect to DHT service!\n"));
120 global_ret = EXIT_NOTCONFIGURED;
121 GNUNET_SCHEDULER_shutdown ();
122 return;
123 }
124 if (NULL == args[0])
125 {
126 get_hello_handle = GNUNET_DHT_hello_get (dht_handle,
127 &hello_result_cb,
128 NULL);
129 GNUNET_break (NULL != get_hello_handle);
130 }
131 else
132 {
133 GNUNET_DHT_hello_offer (dht_handle,
134 args[0],
135 &hello_done_cb,
136 NULL);
137 }
138}
139
140
141/**
142 * Entry point for gnunet-dht-hello
143 *
144 * @param argc number of arguments from the command line
145 * @param argv command line arguments
146 * @return 0 ok, 1 on error
147 */
148int
149main (int argc,
150 char *const *argv)
151{
152 struct GNUNET_GETOPT_CommandLineOption options[] = {
153 GNUNET_GETOPT_OPTION_END
154 };
155 enum GNUNET_GenericReturnValue iret;
156
157 if (GNUNET_OK !=
158 GNUNET_STRINGS_get_utf8_args (argc, argv,
159 &argc, &argv))
160 return 2;
161 iret = GNUNET_PROGRAM_run (
162 argc,
163 argv,
164 "gnunet-dht-hello [URL]",
165 gettext_noop (
166 "Obtain HELLO from DHT or provide HELLO to DHT for bootstrapping"),
167 options,
168 &run,
169 NULL);
170 if (GNUNET_SYSERR == iret)
171 return EXIT_FAILURE;
172 if (GNUNET_NO == iret)
173 return EXIT_SUCCESS;
174 return global_ret;
175}
176
177
178/* end of gnunet-dht-hello.c */
diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c
index da46dcfee..39433791d 100644
--- a/src/dht/gnunet-service-dht.c
+++ b/src/dht/gnunet-service-dht.c
@@ -27,53 +27,335 @@
27#include "platform.h" 27#include "platform.h"
28#include "gnunet_block_lib.h" 28#include "gnunet_block_lib.h"
29#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
30#include "gnunet_transport_service.h"
31#include "gnunet_transport_hello_service.h"
32#include "gnunet_hello_lib.h" 30#include "gnunet_hello_lib.h"
31#include "gnunet_hello_uri_lib.h"
33#include "gnunet_dht_service.h" 32#include "gnunet_dht_service.h"
34#include "gnunet_statistics_service.h" 33#include "gnunet_statistics_service.h"
35#include "gnunet-service-dht.h" 34#include "gnunet-service-dht.h"
36#include "gnunet-service-dht_datacache.h" 35#include "gnunet-service-dht_datacache.h"
37#include "gnunet-service-dht_hello.h"
38#include "gnunet-service-dht_neighbours.h" 36#include "gnunet-service-dht_neighbours.h"
39#include "gnunet-service-dht_nse.h"
40#include "gnunet-service-dht_routing.h" 37#include "gnunet-service-dht_routing.h"
41 38
42/** 39/**
40 * How often do we broadcast our HELLO to neighbours if
41 * nothing special happens?
42 */
43#define HELLO_FREQUENCY GNUNET_TIME_UNIT_HOURS
44
45
46/**
47 * Information we keep per underlay.
48 */
49struct GDS_Underlay
50{
51
52 /**
53 * Kept in a DLL.
54 */
55 struct GDS_Underlay *next;
56
57 /**
58 * Kept in a DLL.
59 */
60 struct GDS_Underlay *prev;
61
62 /**
63 * Environment for this underlay.
64 */
65 struct GNUNET_DHTU_PluginEnvironment env;
66
67 /**
68 * Underlay API handle.
69 */
70 struct GNUNET_DHTU_PluginFunctions *dhtu;
71
72 /**
73 * current network size estimate for this underlay.
74 */
75 double network_size_estimate;
76
77 /**
78 * Name of the underlay (i.e. "gnunet" or "ip").
79 */
80 char *name;
81
82 /**
83 * Name of the library providing the underlay.
84 */
85 char *libname;
86};
87
88
89/**
90 * An address of this peer.
91 */
92struct MyAddress
93{
94 /**
95 * Kept in a DLL.
96 */
97 struct MyAddress *next;
98
99 /**
100 * Kept in a DLL.
101 */
102 struct MyAddress *prev;
103
104 /**
105 * Underlay handle for the address.
106 */
107 struct GNUNET_DHTU_Source *source;
108
109 /**
110 * Textual representation of the address.
111 */
112 char *url;
113
114 /**
115 * Underlay of this address.
116 */
117 struct GDS_Underlay *u;
118};
119
120
121/**
43 * Our HELLO 122 * Our HELLO
44 */ 123 */
45struct GNUNET_MessageHeader *GDS_my_hello; 124struct GNUNET_HELLO_Builder *GDS_my_hello;
46 125
47/** 126/**
48 * Handle to get our current HELLO. 127 * Identity of this peer.
49 */ 128 */
50static struct GNUNET_TRANSPORT_HelloGetHandle *ghh; 129struct GNUNET_PeerIdentity GDS_my_identity;
51 130
52/** 131/**
53 * Hello address expiration 132 * Hash of the identity of this peer.
54 */ 133 */
55struct GNUNET_TIME_Relative hello_expiration; 134struct GNUNET_HashCode GDS_my_identity_hash;
135
136/**
137 * Our private key.
138 */
139struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key;
140
141/**
142 * Task broadcasting our HELLO.
143 */
144static struct GNUNET_SCHEDULER_Task *hello_task;
145
146/**
147 * Handles for the DHT underlays.
148 */
149static struct GDS_Underlay *u_head;
150
151/**
152 * Handles for the DHT underlays.
153 */
154static struct GDS_Underlay *u_tail;
155
156/**
157 * Head of addresses of this peer.
158 */
159static struct MyAddress *a_head;
160
161/**
162 * Tail of addresses of this peer.
163 */
164static struct MyAddress *a_tail;
165
166/**
167 * log of the current network size estimate, used as the point where
168 * we switch between random and deterministic routing.
169 */
170static double log_of_network_size_estimate;
171
172
173/**
174 * Callback that is called when network size estimate is updated.
175 *
176 * @param cls a `struct GDS_Underlay`
177 * @param timestamp time when the estimate was received from the server (or created by the server)
178 * @param logestimate the log(Base 2) value of the current network size estimate
179 * @param std_dev standard deviation for the estimate
180 *
181 */
182static void
183update_network_size_estimate (void *cls,
184 struct GNUNET_TIME_Absolute timestamp,
185 double logestimate,
186 double std_dev)
187{
188 struct GDS_Underlay *u = cls;
189 double sum = 0.0;
190
191 GNUNET_STATISTICS_update (GDS_stats,
192 "# Network size estimates received",
193 1,
194 GNUNET_NO);
195 /* do not allow estimates < 0.5 */
196 u->network_size_estimate = pow (2.0,
197 GNUNET_MAX (0.5,
198 logestimate));
199 for (struct GDS_Underlay *p = u_head; NULL != p; p = p->next)
200 sum += p->network_size_estimate;
201 if (sum <= 2.0)
202 log_of_network_size_estimate = 0.5;
203 else
204 log_of_network_size_estimate = log2 (sum);
205}
206
207
208/**
209 * Return the current NSE
210 *
211 * @return the current NSE as a logarithm
212 */
213double
214GDS_NSE_get (void)
215{
216 return log_of_network_size_estimate;
217}
56 218
57 219
58#include "gnunet-service-dht_clients.c" 220#include "gnunet-service-dht_clients.c"
59 221
60 222
61/** 223/**
62 * Receive the HELLO from transport service, free current and replace 224 * Task run periodically to broadcast our HELLO.
63 * if necessary.
64 * 225 *
65 * @param cls NULL 226 * @param cls NULL
66 * @param message HELLO message of peer
67 */ 227 */
68static void 228static void
69process_hello (void *cls, 229broadcast_hello (void *cls)
70 const struct GNUNET_MessageHeader *message)
71{ 230{
72 GNUNET_free (GDS_my_hello); 231 struct GNUNET_MessageHeader *hello;
73 GDS_my_hello = GNUNET_malloc (ntohs (message->size)); 232
74 GNUNET_memcpy (GDS_my_hello, 233 (void) cls;
75 message, 234 /* TODO: randomize! */
76 ntohs (message->size)); 235 hello_task = GNUNET_SCHEDULER_add_delayed (HELLO_FREQUENCY,
236 &broadcast_hello,
237 NULL);
238 hello = GNUNET_HELLO_builder_to_dht_hello_msg (GDS_my_hello,
239 &GDS_my_private_key);
240 if (NULL == hello)
241 {
242 GNUNET_break (0);
243 return;
244 }
245 GDS_NEIGHBOURS_broadcast (hello);
246 GNUNET_free (hello);
247}
248
249
250/**
251 * Function to call with new addresses of this peer.
252 *
253 * @param cls the closure
254 * @param address address under which we are likely reachable,
255 * pointer will remain valid until @e address_del_cb is called; to be used for HELLOs. Example: "ip+udp://$PID/1.1.1.1:2086/"
256 * @param source handle for sending from this address, NULL if we can only receive
257 * @param[out] ctx storage space for DHT to use in association with this address
258 */
259static void
260u_address_add (void *cls,
261 const char *address,
262 struct GNUNET_DHTU_Source *source,
263 void **ctx)
264{
265 struct GDS_Underlay *u = cls;
266 struct MyAddress *a;
267
268 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
269 "Underlay adds address %s for this peer\n",
270 address);
271 a = GNUNET_new (struct MyAddress);
272 a->source = source;
273 a->url = GNUNET_strdup (address);
274 a->u = u;
275 GNUNET_CONTAINER_DLL_insert (a_head,
276 a_tail,
277 a);
278 *ctx = a;
279 GNUNET_HELLO_builder_add_address (GDS_my_hello,
280 address);
281 if (NULL != hello_task)
282 GNUNET_SCHEDULER_cancel (hello_task);
283 hello_task = GNUNET_SCHEDULER_add_now (&broadcast_hello,
284 NULL);
285}
286
287
288/**
289 * Function to call with expired addresses of this peer.
290 *
291 * @param[in] ctx storage space used by the DHT in association with this address
292 */
293static void
294u_address_del (void *ctx)
295{
296 struct MyAddress *a = ctx;
297
298 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
299 "Underlay deletes address %s for this peer\n",
300 a->url);
301 GNUNET_HELLO_builder_del_address (GDS_my_hello,
302 a->url);
303 GNUNET_CONTAINER_DLL_remove (a_head,
304 a_tail,
305 a);
306 GNUNET_free (a->url);
307 GNUNET_free (a);
308 if (NULL != hello_task)
309 GNUNET_SCHEDULER_cancel (hello_task);
310 hello_task = GNUNET_SCHEDULER_add_now (&broadcast_hello,
311 NULL);
312}
313
314
315void
316GDS_u_try_connect (const struct GNUNET_PeerIdentity *pid,
317 const char *address)
318{
319 for (struct GDS_Underlay *u = u_head;
320 NULL != u;
321 u = u->next)
322 u->dhtu->try_connect (u->dhtu->cls,
323 pid,
324 address);
325}
326
327
328void
329GDS_u_send (struct GDS_Underlay *u,
330 struct GNUNET_DHTU_Target *target,
331 const void *msg,
332 size_t msg_size,
333 GNUNET_SCHEDULER_TaskCallback finished_cb,
334 void *finished_cb_cls)
335{
336 u->dhtu->send (u->dhtu->cls,
337 target,
338 msg,
339 msg_size,
340 finished_cb,
341 finished_cb_cls);
342}
343
344
345void
346GDS_u_drop (struct GDS_Underlay *u,
347 struct GNUNET_DHTU_PreferenceHandle *ph)
348{
349 u->dhtu->drop (ph);
350}
351
352
353struct GNUNET_DHTU_PreferenceHandle *
354GDS_u_hold (struct GDS_Underlay *u,
355 struct GNUNET_DHTU_Target *target)
356{
357 return u->dhtu->hold (u->dhtu->cls,
358 target);
77} 359}
78 360
79 361
@@ -85,30 +367,97 @@ process_hello (void *cls,
85static void 367static void
86shutdown_task (void *cls) 368shutdown_task (void *cls)
87{ 369{
88 if (NULL != ghh) 370 struct GDS_Underlay *u;
371
372 while (NULL != (u = u_head))
89 { 373 {
90 GNUNET_TRANSPORT_hello_get_cancel (ghh); 374 GNUNET_PLUGIN_unload (u->libname,
91 ghh = NULL; 375 u->dhtu);
376 GNUNET_CONTAINER_DLL_remove (u_head,
377 u_tail,
378 u);
379 GNUNET_free (u->name);
380 GNUNET_free (u->libname);
381 GNUNET_free (u);
92 } 382 }
93 GDS_NEIGHBOURS_done (); 383 GDS_NEIGHBOURS_done ();
94 GDS_DATACACHE_done (); 384 GDS_DATACACHE_done ();
95 GDS_ROUTING_done (); 385 GDS_ROUTING_done ();
96 GDS_HELLO_done ();
97 GDS_NSE_done ();
98 if (NULL != GDS_block_context) 386 if (NULL != GDS_block_context)
99 { 387 {
100 GNUNET_BLOCK_context_destroy (GDS_block_context); 388 GNUNET_BLOCK_context_destroy (GDS_block_context);
101 GDS_block_context = NULL; 389 GDS_block_context = NULL;
102 } 390 }
391 GDS_CLIENTS_stop ();
103 if (NULL != GDS_stats) 392 if (NULL != GDS_stats)
104 { 393 {
105 GNUNET_STATISTICS_destroy (GDS_stats, 394 GNUNET_STATISTICS_destroy (GDS_stats,
106 GNUNET_YES); 395 GNUNET_YES);
107 GDS_stats = NULL; 396 GDS_stats = NULL;
108 } 397 }
109 GNUNET_free (GDS_my_hello); 398 if (NULL != GDS_my_hello)
110 GDS_my_hello = NULL; 399 {
111 GDS_CLIENTS_stop (); 400 GNUNET_HELLO_builder_free (GDS_my_hello);
401 GDS_my_hello = NULL;
402 }
403 if (NULL != hello_task)
404 {
405 GNUNET_SCHEDULER_cancel (hello_task);
406 hello_task = NULL;
407 }
408}
409
410
411/**
412 * Function iterating over all configuration sections.
413 * Loads plugins for enabled DHT underlays.
414 *
415 * @param cls NULL
416 * @param section configuration section to inspect
417 */
418static void
419load_underlay (void *cls,
420 const char *section)
421{
422 struct GDS_Underlay *u;
423 char *libname;
424
425 (void) cls;
426 if (0 != strncasecmp (section,
427 "dhtu-",
428 strlen ("dhtu-")))
429 return;
430 if (GNUNET_YES !=
431 GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg,
432 section,
433 "ENABLED"))
434 return;
435 section += strlen ("dhtu-");
436 u = GNUNET_new (struct GDS_Underlay);
437 u->env.cls = u;
438 u->env.cfg = GDS_cfg;
439 u->env.address_add_cb = &u_address_add;
440 u->env.address_del_cb = &u_address_del;
441 u->env.network_size_cb = &update_network_size_estimate;
442 u->env.connect_cb = &GDS_u_connect;
443 u->env.disconnect_cb = &GDS_u_disconnect;
444 u->env.receive_cb = &GDS_u_receive;
445 GNUNET_asprintf (&libname,
446 "libgnunet_plugin_dhtu_%s",
447 section);
448 u->dhtu = GNUNET_PLUGIN_load (libname,
449 &u->env);
450 if (NULL == u->dhtu)
451 {
452 GNUNET_free (libname);
453 GNUNET_free (u);
454 return;
455 }
456 u->libname = libname;
457 u->name = GNUNET_strdup (section);
458 GNUNET_CONTAINER_DLL_insert (u_head,
459 u_tail,
460 u);
112} 461}
113 462
114 463
@@ -126,34 +475,64 @@ run (void *cls,
126{ 475{
127 GDS_cfg = c; 476 GDS_cfg = c;
128 GDS_service = service; 477 GDS_service = service;
129 if (GNUNET_OK !=
130 GNUNET_CONFIGURATION_get_value_time (c,
131 "transport",
132 "HELLO_EXPIRATION",
133 &hello_expiration))
134 { 478 {
135 hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; 479 char *keyfile;
480
481 if (GNUNET_OK !=
482 GNUNET_CONFIGURATION_get_value_filename (GDS_cfg,
483 "PEER",
484 "PRIVATE_KEY",
485 &keyfile))
486 {
487 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
488 "PEER",
489 "PRIVATE_KEY");
490 GNUNET_SCHEDULER_shutdown ();
491 return;
492 }
493 if (GNUNET_SYSERR ==
494 GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
495 GNUNET_YES,
496 &GDS_my_private_key))
497 {
498 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
499 "Failed to setup peer's private key\n");
500 GNUNET_free (keyfile);
501 GNUNET_SCHEDULER_shutdown ();
502 return;
503 }
504 GNUNET_free (keyfile);
136 } 505 }
506 GNUNET_CRYPTO_eddsa_key_get_public (&GDS_my_private_key,
507 &GDS_my_identity.public_key);
508 GDS_my_hello = GNUNET_HELLO_builder_new (&GDS_my_identity);
509 GNUNET_CRYPTO_hash (&GDS_my_identity,
510 sizeof(struct GNUNET_PeerIdentity),
511 &GDS_my_identity_hash);
137 GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg); 512 GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg);
138 GDS_stats = GNUNET_STATISTICS_create ("dht", 513 GDS_stats = GNUNET_STATISTICS_create ("dht",
139 GDS_cfg); 514 GDS_cfg);
140 GNUNET_SERVICE_suspend (GDS_service);
141 GDS_CLIENTS_init (); 515 GDS_CLIENTS_init ();
142 GDS_ROUTING_init (); 516 GDS_ROUTING_init ();
143 GDS_NSE_init ();
144 GDS_DATACACHE_init (); 517 GDS_DATACACHE_init ();
145 GDS_HELLO_init (); 518 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
146 if (GNUNET_OK != GDS_NEIGHBOURS_init ()) 519 NULL);
520 if (GNUNET_OK !=
521 GDS_NEIGHBOURS_init ())
147 { 522 {
148 shutdown_task (NULL); 523 GNUNET_SCHEDULER_shutdown ();
524 return;
525 }
526 GNUNET_CONFIGURATION_iterate_sections (GDS_cfg,
527 &load_underlay,
528 NULL);
529 if (NULL == u_head)
530 {
531 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
532 "No DHT underlays configured!\n");
533 GNUNET_SCHEDULER_shutdown ();
149 return; 534 return;
150 } 535 }
151 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
152 NULL);
153 ghh = GNUNET_TRANSPORT_hello_get (GDS_cfg,
154 GNUNET_TRANSPORT_AC_GLOBAL,
155 &process_hello,
156 NULL);
157} 536}
158 537
159 538
diff --git a/src/dht/gnunet-service-dht.h b/src/dht/gnunet-service-dht.h
index 367ff426e..a1513fcce 100644
--- a/src/dht/gnunet-service-dht.h
+++ b/src/dht/gnunet-service-dht.h
@@ -27,6 +27,7 @@
27#define GNUNET_SERVICE_DHT_H 27#define GNUNET_SERVICE_DHT_H
28 28
29#include "gnunet-service-dht_datacache.h" 29#include "gnunet-service-dht_datacache.h"
30#include "gnunet-service-dht_neighbours.h"
30#include "gnunet_statistics_service.h" 31#include "gnunet_statistics_service.h"
31#include "gnunet_transport_service.h" 32#include "gnunet_transport_service.h"
32 33
@@ -34,6 +35,11 @@
34#define DEBUG_DHT GNUNET_EXTRA_LOGGING 35#define DEBUG_DHT GNUNET_EXTRA_LOGGING
35 36
36/** 37/**
38 * Information we keep per underlay.
39 */
40struct GDS_Underlay;
41
42/**
37 * Configuration we use. 43 * Configuration we use.
38 */ 44 */
39extern const struct GNUNET_CONFIGURATION_Handle *GDS_cfg; 45extern const struct GNUNET_CONFIGURATION_Handle *GDS_cfg;
@@ -54,9 +60,81 @@ extern struct GNUNET_BLOCK_Context *GDS_block_context;
54extern struct GNUNET_STATISTICS_Handle *GDS_stats; 60extern struct GNUNET_STATISTICS_Handle *GDS_stats;
55 61
56/** 62/**
57 * Our HELLO 63 * Our HELLO builder.
64 */
65extern struct GNUNET_HELLO_Builder *GDS_my_hello;
66
67/**
68 * Identity of this peer.
69 */
70extern struct GNUNET_PeerIdentity GDS_my_identity;
71
72/**
73 * Hash of the identity of this peer.
74 */
75extern struct GNUNET_HashCode GDS_my_identity_hash;
76
77/**
78 * Our private key.
79 */
80extern struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key;
81
82
83/**
84 * Ask all underlays to connect to peer @a pid at @a address.
85 *
86 * @param pid identity of the peer we would connect to
87 * @param address an address of @a pid
88 */
89void
90GDS_u_try_connect (const struct GNUNET_PeerIdentity *pid,
91 const char *address);
92
93
94/**
95 * Send message to some other participant over the network. Note that
96 * sending is not guaranteeing that the other peer actually received the
97 * message. For any given @a target, the DHT must wait for the @a
98 * finished_cb to be called before calling send() again.
99 *
100 * @param u underlay to use for transmission
101 * @param target receiver identification
102 * @param msg message
103 * @param msg_size number of bytes in @a msg
104 * @param finished_cb function called once transmission is done
105 * (not called if @a target disconnects, then only the
106 * disconnect_cb is called).
107 * @param finished_cb_cls closure for @a finished_cb
108 */
109void
110GDS_u_send (struct GDS_Underlay *u,
111 struct GNUNET_DHTU_Target *target,
112 const void *msg,
113 size_t msg_size,
114 GNUNET_SCHEDULER_TaskCallback finished_cb,
115 void *finished_cb_cls);
116
117
118/**
119 * Drop a hold @a ph from underlay @a u.
120 *
121 * @param u the underlay controlling the hold
122 * @param ph the preference handle
123 */
124void
125GDS_u_drop (struct GDS_Underlay *u,
126 struct GNUNET_DHTU_PreferenceHandle *ph);
127
128
129/**
130 * Create a hold on @a target at underlay @a u.
131 *
132 * @param u the underlay controlling the target
133 * @param target the peer to hold the connection to
58 */ 134 */
59extern struct GNUNET_MessageHeader *GDS_my_hello; 135struct GNUNET_DHTU_PreferenceHandle *
136GDS_u_hold (struct GDS_Underlay *u,
137 struct GNUNET_DHTU_Target *target);
60 138
61 139
62/** 140/**
@@ -68,8 +146,9 @@ extern struct GNUNET_MessageHeader *GDS_my_hello;
68 * @param query_hash hash of the original query, might not match key in @a bd 146 * @param query_hash hash of the original query, might not match key in @a bd
69 * @param get_path_length number of entries in @a get_path 147 * @param get_path_length number of entries in @a get_path
70 * @param get_path path the reply has taken 148 * @param get_path path the reply has taken
149 * @return true on success, false on failures
71 */ 150 */
72void 151bool
73GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd, 152GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd,
74 const struct GNUNET_HashCode *query_hash, 153 const struct GNUNET_HashCode *query_hash,
75 unsigned int get_path_length, 154 unsigned int get_path_length,
@@ -128,4 +207,12 @@ GDS_CLIENTS_process_put (enum GNUNET_DHT_RouteOption options,
128 uint32_t hop_count, 207 uint32_t hop_count,
129 uint32_t desired_replication_level); 208 uint32_t desired_replication_level);
130 209
210/**
211 * Return the current NSE
212 *
213 * @return the current NSE as a logarithm
214 */
215double
216GDS_NSE_get (void);
217
131#endif 218#endif
diff --git a/src/dht/gnunet-service-dht_clients.c b/src/dht/gnunet-service-dht_clients.c
index a1c3024de..6a4f58d1f 100644
--- a/src/dht/gnunet-service-dht_clients.c
+++ b/src/dht/gnunet-service-dht_clients.c
@@ -24,7 +24,6 @@
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * @author Nathan Evans 25 * @author Nathan Evans
26 */ 26 */
27
28#include "platform.h" 27#include "platform.h"
29#include "gnunet_constants.h" 28#include "gnunet_constants.h"
30#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
@@ -36,6 +35,14 @@
36 35
37 36
38/** 37/**
38 * Enable slow sanity checks to debug issues.
39 * 0: do not check
40 * 1: check all external inputs
41 * 2: check internal computations as well
42 */
43#define SANITY_CHECKS 2
44
45/**
39 * Should routing details be logged to stderr (for debugging)? 46 * Should routing details be logged to stderr (for debugging)?
40 */ 47 */
41#define LOG_TRAFFIC(kind, ...) GNUNET_log_from (kind, "dht-traffic", \ 48#define LOG_TRAFFIC(kind, ...) GNUNET_log_from (kind, "dht-traffic", \
@@ -503,6 +510,15 @@ handle_dht_local_put (void *cls,
503 (unsigned long) (size - sizeof(struct GNUNET_DHT_ClientPutMessage)), 510 (unsigned long) (size - sizeof(struct GNUNET_DHT_ClientPutMessage)),
504 GNUNET_h2s (&dht_msg->key), 511 GNUNET_h2s (&dht_msg->key),
505 (unsigned int) bd.type); 512 (unsigned int) bd.type);
513 if (GNUNET_OK !=
514 GNUNET_BLOCK_check_block (GDS_block_context,
515 bd.type,
516 bd.data,
517 bd.data_size))
518 {
519 GNUNET_break (0);
520 return;
521 }
506 GNUNET_STATISTICS_update (GDS_stats, 522 GNUNET_STATISTICS_update (GDS_stats,
507 "# PUT requests received from clients", 523 "# PUT requests received from clients",
508 1, 524 1,
@@ -511,9 +527,9 @@ handle_dht_local_put (void *cls,
511 "CLIENT-PUT %s\n", 527 "CLIENT-PUT %s\n",
512 GNUNET_h2s_full (&dht_msg->key)); 528 GNUNET_h2s_full (&dht_msg->key));
513 /* give to local clients */ 529 /* give to local clients */
514 GDS_CLIENTS_handle_reply (&bd, 530 GNUNET_break (GDS_CLIENTS_handle_reply (&bd,
515 &bd.key, 531 &bd.key,
516 0, NULL /* get path */); 532 0, NULL /* get path */));
517 533
518 { 534 {
519 struct GNUNET_CONTAINER_BloomFilter *peer_bf; 535 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
@@ -561,10 +577,12 @@ static void
561handle_local_result (void *cls, 577handle_local_result (void *cls,
562 const struct GDS_DATACACHE_BlockData *bd) 578 const struct GDS_DATACACHE_BlockData *bd)
563{ 579{
564 /* FIXME: use 'cls' instead of looking up the client? */ 580 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
565 GDS_CLIENTS_handle_reply (bd, 581 "Datacache provided result for query key %s\n",
566 &bd->key, 582 GNUNET_h2s (&bd->key));
567 0, NULL /* get_path */); 583 GNUNET_break (GDS_CLIENTS_handle_reply (bd,
584 &bd->key,
585 0, NULL /* get_path */));
568} 586}
569 587
570 588
@@ -917,7 +935,7 @@ forward_reply (void *cls,
917 GNUNET_NO); 935 GNUNET_NO);
918 return GNUNET_YES; /* type mismatch */ 936 return GNUNET_YES; /* type mismatch */
919 } 937 }
920 if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_PEER)) && 938 if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_APPROXIMATE)) &&
921 (0 != GNUNET_memcmp (&frc->bd->key, 939 (0 != GNUNET_memcmp (&frc->bd->key,
922 query_hash)) ) 940 query_hash)) )
923 { 941 {
@@ -973,9 +991,6 @@ forward_reply (void *cls,
973 /* should be impossible to encounter here */ 991 /* should be impossible to encounter here */
974 GNUNET_break (0); 992 GNUNET_break (0);
975 return GNUNET_YES; 993 return GNUNET_YES;
976 case GNUNET_BLOCK_REPLY_INVALID:
977 GNUNET_break_op (0);
978 return GNUNET_NO;
979 case GNUNET_BLOCK_REPLY_IRRELEVANT: 994 case GNUNET_BLOCK_REPLY_IRRELEVANT:
980 return GNUNET_YES; 995 return GNUNET_YES;
981 default: 996 default:
@@ -996,7 +1011,7 @@ forward_reply (void *cls,
996 reply->put_path_length = htonl (frc->bd->put_path_length); 1011 reply->put_path_length = htonl (frc->bd->put_path_length);
997 reply->unique_id = record->unique_id; 1012 reply->unique_id = record->unique_id;
998 reply->expiration = GNUNET_TIME_absolute_hton (frc->bd->expiration_time); 1013 reply->expiration = GNUNET_TIME_absolute_hton (frc->bd->expiration_time);
999 reply->key = frc->bd->key; 1014 reply->key = *query_hash;
1000 paths = (struct GNUNET_DHT_PathElement *) &reply[1]; 1015 paths = (struct GNUNET_DHT_PathElement *) &reply[1];
1001 GNUNET_memcpy (paths, 1016 GNUNET_memcpy (paths,
1002 frc->bd->put_path, 1017 frc->bd->put_path,
@@ -1004,7 +1019,8 @@ forward_reply (void *cls,
1004 * frc->bd->put_path_length); 1019 * frc->bd->put_path_length);
1005 GNUNET_memcpy (&paths[frc->bd->put_path_length], 1020 GNUNET_memcpy (&paths[frc->bd->put_path_length],
1006 frc->get_path, 1021 frc->get_path,
1007 sizeof(struct GNUNET_DHT_PathElement) * frc->get_path_length); 1022 sizeof(struct GNUNET_DHT_PathElement)
1023 * frc->get_path_length);
1008 GNUNET_memcpy (&paths[frc->get_path_length + frc->bd->put_path_length], 1024 GNUNET_memcpy (&paths[frc->get_path_length + frc->bd->put_path_length],
1009 frc->bd->data, 1025 frc->bd->data,
1010 frc->bd->data_size); 1026 frc->bd->data_size);
@@ -1020,7 +1036,7 @@ forward_reply (void *cls,
1020} 1036}
1021 1037
1022 1038
1023void 1039bool
1024GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd, 1040GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd,
1025 const struct GNUNET_HashCode *query_hash, 1041 const struct GNUNET_HashCode *query_hash,
1026 unsigned int get_path_length, 1042 unsigned int get_path_length,
@@ -1035,14 +1051,31 @@ GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd,
1035 if (msize >= GNUNET_MAX_MESSAGE_SIZE) 1051 if (msize >= GNUNET_MAX_MESSAGE_SIZE)
1036 { 1052 {
1037 GNUNET_break (0); 1053 GNUNET_break (0);
1038 return; 1054 return false;
1039 } 1055 }
1056#if SANITY_CHECKS > 1
1057 if (0 !=
1058 GNUNET_DHT_verify_path (bd->data,
1059 bd->data_size,
1060 bd->expiration_time,
1061 bd->put_path,
1062 bd->put_path_length,
1063 get_path,
1064 get_path_length,
1065 &GDS_my_identity))
1066 {
1067 GNUNET_break (0);
1068 return false;
1069 }
1070#endif
1040 frc.bd = bd; 1071 frc.bd = bd;
1041 frc.get_path = get_path; 1072 frc.get_path = get_path;
1042 frc.get_path_length = get_path_length; 1073 frc.get_path_length = get_path_length;
1043 LOG (GNUNET_ERROR_TYPE_DEBUG, 1074 LOG (GNUNET_ERROR_TYPE_DEBUG,
1044 "Forwarding reply for query hash %s to client\n", 1075 "Forwarding reply for query hash %s with GPL %u and PPL %u to client\n",
1045 GNUNET_h2s (query_hash)); 1076 GNUNET_h2s (query_hash),
1077 get_path_length,
1078 bd->put_path_length);
1046 if (0 == 1079 if (0 ==
1047 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, 1080 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
1048 query_hash, 1081 query_hash,
@@ -1057,6 +1090,102 @@ GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd,
1057 1, 1090 1,
1058 GNUNET_NO); 1091 GNUNET_NO);
1059 } 1092 }
1093 return true;
1094}
1095
1096
1097/* **************** HELLO logic ***************** */
1098
1099/**
1100 * Handler for HELLO GET message. Reply to client
1101 * with a URL of our HELLO.
1102 *
1103 * @param cls the client we received this message from
1104 * @param msg the actual message received
1105 *
1106 */
1107static void
1108handle_dht_local_hello_get (void *cls,
1109 const struct GNUNET_MessageHeader *msg)
1110{
1111 struct ClientHandle *ch = cls;
1112 char *url = GNUNET_HELLO_builder_to_url (GDS_my_hello,
1113 &GDS_my_private_key);
1114 size_t slen = strlen (url) + 1;
1115 struct GNUNET_MessageHeader *hdr;
1116 struct GNUNET_MQ_Envelope *env;
1117
1118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1119 "Handling request from local client for my HELLO\n");
1120 env = GNUNET_MQ_msg_extra (hdr,
1121 slen,
1122 GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL);
1123 memcpy (&hdr[1],
1124 url,
1125 slen);
1126 GNUNET_free (url);
1127 GNUNET_MQ_send (ch->mq,
1128 env);
1129 GNUNET_SERVICE_client_continue (ch->client);
1130}
1131
1132
1133/**
1134 * Process a client HELLO message received from the service.
1135 *
1136 * @param cls the client we received this message from
1137 * @param hdr HELLO URL message from the service.
1138 * @return #GNUNET_OK if @a hdr is well-formed
1139 */
1140static enum GNUNET_GenericReturnValue
1141check_dht_local_hello_offer (void *cls,
1142 const struct GNUNET_MessageHeader *hdr)
1143{
1144 uint16_t len = ntohs (hdr->size);
1145 const char *buf = (const char *) &hdr[1];
1146
1147 (void) cls;
1148 if ('\0' != buf[len - sizeof (*hdr) - 1])
1149 {
1150 GNUNET_break (0);
1151 return GNUNET_SYSERR;
1152 }
1153 return GNUNET_OK;
1154}
1155
1156
1157/**
1158 * Handler for HELLO OFFER message. Try to use the
1159 * HELLO to connect to another peer.
1160 *
1161 * @param cls the client we received this message from
1162 * @param msg the actual message received
1163 */
1164static void
1165handle_dht_local_hello_offer (void *cls,
1166 const struct GNUNET_MessageHeader *msg)
1167{
1168 struct ClientHandle *ch = cls;
1169 const char *url = (const char *) &msg[1];
1170 struct GNUNET_HELLO_Builder *b;
1171 struct GNUNET_PeerIdentity pid;
1172
1173 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1174 "Local client provided HELLO URL %s\n",
1175 url);
1176 b = GNUNET_HELLO_builder_from_url (url);
1177 if (NULL == b)
1178 {
1179 GNUNET_break (0);
1180 GNUNET_SERVICE_client_drop (ch->client);
1181 return;
1182 }
1183 GNUNET_SERVICE_client_continue (ch->client);
1184 GNUNET_HELLO_builder_iterate (b,
1185 &pid,
1186 &GDS_try_connect,
1187 &pid);
1188 GNUNET_HELLO_builder_free (b);
1060} 1189}
1061 1190
1062 1191
@@ -1330,8 +1459,8 @@ response_action (void *cls,
1330 bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement)); 1459 bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement));
1331 GNUNET_memcpy (path, 1460 GNUNET_memcpy (path,
1332 resp_ctx->get_path, 1461 resp_ctx->get_path,
1333 resp_ctx->get_path_length * sizeof(struct 1462 resp_ctx->get_path_length
1334 GNUNET_DHT_PathElement)); 1463 * sizeof(struct GNUNET_DHT_PathElement));
1335 GNUNET_memcpy (&path[resp_ctx->get_path_length], 1464 GNUNET_memcpy (&path[resp_ctx->get_path_length],
1336 bd->data, 1465 bd->data,
1337 bd->data_size); 1466 bd->data_size);
@@ -1504,6 +1633,14 @@ GDS_CLIENTS_stop (void)
1504 GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN, \ 1633 GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN, \
1505 struct GNUNET_DHT_ClientGetResultSeenMessage, \ 1634 struct GNUNET_DHT_ClientGetResultSeenMessage, \
1506 NULL), \ 1635 NULL), \
1636 GNUNET_MQ_hd_fixed_size (dht_local_hello_get, \
1637 GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_GET, \
1638 struct GNUNET_MessageHeader, \
1639 NULL), \
1640 GNUNET_MQ_hd_var_size (dht_local_hello_offer, \
1641 GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL, \
1642 struct GNUNET_MessageHeader, \
1643 NULL), \
1507 GNUNET_MQ_handler_end ()) 1644 GNUNET_MQ_handler_end ())
1508 1645
1509 1646
diff --git a/src/dht/gnunet-service-dht_datacache.c b/src/dht/gnunet-service-dht_datacache.c
index cb778717b..be0a6db81 100644
--- a/src/dht/gnunet-service-dht_datacache.c
+++ b/src/dht/gnunet-service-dht_datacache.c
@@ -36,7 +36,7 @@
36 * How many "closest" results to we return for migration when 36 * How many "closest" results to we return for migration when
37 * asked (at most)? 37 * asked (at most)?
38 */ 38 */
39#define NUM_CLOSEST 42 39#define NUM_CLOSEST 4
40 40
41 41
42/** 42/**
@@ -68,7 +68,7 @@ GDS_DATACACHE_handle_put (const struct GDS_DATACACHE_BlockData *bd)
68 1, 68 1,
69 GNUNET_NO); 69 GNUNET_NO);
70 GNUNET_CRYPTO_hash_xor (&bd->key, 70 GNUNET_CRYPTO_hash_xor (&bd->key,
71 &my_identity_hash, 71 &GDS_my_identity_hash,
72 &xor); 72 &xor);
73 r = GNUNET_DATACACHE_put (datacache, 73 r = GNUNET_DATACACHE_put (datacache,
74 &bd->key, 74 &bd->key,
@@ -126,7 +126,7 @@ struct GetRequestContext
126 /** 126 /**
127 * Return value to give back. 127 * Return value to give back.
128 */ 128 */
129 enum GNUNET_BLOCK_EvaluationResult eval; 129 enum GNUNET_BLOCK_ReplyEvaluationResult eval;
130}; 130};
131 131
132 132
@@ -204,13 +204,6 @@ datacache_get_iterator (void *cls,
204 1, 204 1,
205 GNUNET_NO); 205 GNUNET_NO);
206 break; 206 break;
207 case GNUNET_BLOCK_REPLY_INVALID:
208 /* maybe it expired? */
209 GNUNET_STATISTICS_update (GDS_stats,
210 "# Invalid RESULTS found in datacache",
211 1,
212 GNUNET_NO);
213 break;
214 case GNUNET_BLOCK_REPLY_IRRELEVANT: 207 case GNUNET_BLOCK_REPLY_IRRELEVANT:
215 GNUNET_STATISTICS_update (GDS_stats, 208 GNUNET_STATISTICS_update (GDS_stats,
216 "# Irrelevant RESULTS found in datacache", 209 "# Irrelevant RESULTS found in datacache",
@@ -222,7 +215,7 @@ datacache_get_iterator (void *cls,
222} 215}
223 216
224 217
225enum GNUNET_BLOCK_EvaluationResult 218enum GNUNET_BLOCK_ReplyEvaluationResult
226GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key, 219GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
227 enum GNUNET_BLOCK_Type type, 220 enum GNUNET_BLOCK_Type type,
228 const void *xquery, 221 const void *xquery,
@@ -231,22 +224,23 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
231 GDS_DATACACHE_GetCallback gc, 224 GDS_DATACACHE_GetCallback gc,
232 void *gc_cls) 225 void *gc_cls)
233{ 226{
234 struct GetRequestContext ctx; 227 struct GetRequestContext ctx = {
228 .eval = GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED,
229 .key = *key,
230 .xquery = xquery,
231 .xquery_size = xquery_size,
232 .bg = bg,
233 .gc = gc,
234 .gc_cls = gc_cls
235 };
235 unsigned int r; 236 unsigned int r;
236 237
237 if (NULL == datacache) 238 if (NULL == datacache)
238 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; 239 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
239 GNUNET_STATISTICS_update (GDS_stats, 240 GNUNET_STATISTICS_update (GDS_stats,
240 "# GET requests given to datacache", 241 "# GET requests given to datacache",
241 1, 242 1,
242 GNUNET_NO); 243 GNUNET_NO);
243 ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
244 ctx.key = *key;
245 ctx.xquery = xquery;
246 ctx.xquery_size = xquery_size;
247 ctx.bg = bg;
248 ctx.gc = gc;
249 ctx.gc_cls = gc_cls;
250 r = GNUNET_DATACACHE_get (datacache, 244 r = GNUNET_DATACACHE_get (datacache,
251 key, 245 key,
252 type, 246 type,
@@ -261,85 +255,44 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
261} 255}
262 256
263 257
264/** 258enum GNUNET_BLOCK_ReplyEvaluationResult
265 * Closure for #datacache_get_successors_iterator().
266 */
267struct SuccContext
268{
269 /**
270 * Function to call on the result
271 */
272 GDS_DATACACHE_GetCallback cb;
273
274 /**
275 * Closure for @e cb.
276 */
277 void *cb_cls;
278
279};
280
281
282/**
283 * Iterator for local get request results,
284 *
285 * @param cls closure with the `struct GNUNET_HashCode *` with the trail ID
286 * @param key the key this data is stored under
287 * @param size the size of the data identified by key
288 * @param data the actual data
289 * @param type the type of the data
290 * @param exp when does this value expire?
291 * @param put_path_length number of peers in @a put_path
292 * @param put_path path the reply took on put
293 * @return #GNUNET_OK to continue iteration, anything else
294 * to stop iteration.
295 */
296static enum GNUNET_GenericReturnValue
297datacache_get_successors_iterator (void *cls,
298 const struct GNUNET_HashCode *key,
299 size_t size,
300 const char *data,
301 enum GNUNET_BLOCK_Type type,
302 struct GNUNET_TIME_Absolute exp,
303 unsigned int put_path_length,
304 const struct
305 GNUNET_DHT_PathElement *put_path)
306{
307 const struct SuccContext *sc = cls;
308 struct GDS_DATACACHE_BlockData bd = {
309 .key = *key,
310 .expiration_time = exp,
311 .put_path = put_path,
312 .data = data,
313 .data_size = size,
314 .put_path_length = put_path_length,
315 .type = type
316 };
317
318 /* NOTE: The datacache currently does not store the RO from
319 the original 'put', so we don't know the 'correct' option
320 at this point anymore. Thus, we conservatively assume
321 that recording is desired (for now). */
322 sc->cb (sc->cb_cls,
323 &bd);
324 return GNUNET_OK;
325}
326
327
328void
329GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key, 259GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
260 enum GNUNET_BLOCK_Type type,
261 const void *xquery,
262 size_t xquery_size,
263 struct GNUNET_BLOCK_Group *bg,
330 GDS_DATACACHE_GetCallback cb, 264 GDS_DATACACHE_GetCallback cb,
331 void *cb_cls) 265 void *cb_cls)
332{ 266{
333 struct SuccContext sc = { 267 struct GetRequestContext ctx = {
334 .cb = cb, 268 .eval = GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED,
335 .cb_cls = cb_cls 269 .key = *key,
270 .xquery = xquery,
271 .xquery_size = xquery_size,
272 .bg = bg,
273 .gc = cb,
274 .gc_cls = cb_cls
336 }; 275 };
276 unsigned int r;
337 277
338 (void) GNUNET_DATACACHE_get_closest (datacache, 278 if (NULL == datacache)
339 key, 279 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
340 NUM_CLOSEST, 280 GNUNET_STATISTICS_update (GDS_stats,
341 &datacache_get_successors_iterator, 281 "# GET closest requests given to datacache",
342 &sc); 282 1,
283 GNUNET_NO);
284 r = GNUNET_DATACACHE_get_closest (datacache,
285 key,
286 type,
287 NUM_CLOSEST,
288 &datacache_get_iterator,
289 &ctx);
290 LOG (GNUNET_ERROR_TYPE_DEBUG,
291 "DATACACHE approximate GET for key %s completed (%d). %u results found.\n",
292 GNUNET_h2s (key),
293 ctx.eval,
294 r);
295 return ctx.eval;
343} 296}
344 297
345 298
diff --git a/src/dht/gnunet-service-dht_datacache.h b/src/dht/gnunet-service-dht_datacache.h
index 691a51e0e..d860139f5 100644
--- a/src/dht/gnunet-service-dht_datacache.h
+++ b/src/dht/gnunet-service-dht_datacache.h
@@ -107,7 +107,7 @@ typedef void
107 * @param gc_cls closure for @a gc 107 * @param gc_cls closure for @a gc
108 * @return evaluation result for the local replies 108 * @return evaluation result for the local replies
109 */ 109 */
110enum GNUNET_BLOCK_EvaluationResult 110enum GNUNET_BLOCK_ReplyEvaluationResult
111GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key, 111GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
112 enum GNUNET_BLOCK_Type type, 112 enum GNUNET_BLOCK_Type type,
113 const void *xquery, 113 const void *xquery,
@@ -122,11 +122,20 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
122 * another peer. 122 * another peer.
123 * 123 *
124 * @param key the location at which the peer is looking for data that is close 124 * @param key the location at which the peer is looking for data that is close
125 * @param type requested data type
126 * @param xquery extended query
127 * @param xquery_size number of bytes in xquery
128 * @param bg block group to use for evaluation of replies
125 * @param cb function to call with the result 129 * @param cb function to call with the result
126 * @param cb_cls closure for @a cb 130 * @param cb_cls closure for @a cb
131 * @return evaluation result for the local replies
127 */ 132 */
128void 133enum GNUNET_BLOCK_ReplyEvaluationResult
129GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key, 134GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
135 enum GNUNET_BLOCK_Type type,
136 const void *xquery,
137 size_t xquery_size,
138 struct GNUNET_BLOCK_Group *bg,
130 GDS_DATACACHE_GetCallback cb, 139 GDS_DATACACHE_GetCallback cb,
131 void *cb_cls); 140 void *cb_cls);
132 141
diff --git a/src/dht/gnunet-service-dht_hello.c b/src/dht/gnunet-service-dht_hello.c
deleted file mode 100644
index 949456575..000000000
--- a/src/dht/gnunet-service-dht_hello.c
+++ /dev/null
@@ -1,154 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 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 */
20
21/**
22 * @file dht/gnunet-service-dht_hello.c
23 * @brief GNUnet DHT integration with peerinfo
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - consider adding mechanism to remove expired HELLOs
28 */
29#include "platform.h"
30#include "gnunet-service-dht.h"
31#include "gnunet-service-dht_hello.h"
32#include "gnunet_peerinfo_service.h"
33
34
35/**
36 * Handle for peerinfo notifications.
37 */
38static struct GNUNET_PEERINFO_NotifyContext *pnc;
39
40/**
41 * Hash map of peers to HELLOs.
42 */
43static struct GNUNET_CONTAINER_MultiPeerMap *peer_to_hello;
44
45
46/**
47 * Obtain a peer's HELLO if available
48 *
49 * @param peer peer to look for a HELLO from
50 * @return HELLO for the given peer
51 */
52const struct GNUNET_HELLO_Message *
53GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer)
54{
55 if (NULL == peer_to_hello)
56 return NULL;
57 return GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
58 peer);
59}
60
61
62/**
63 * Function called for each HELLO known to PEERINFO.
64 *
65 * @param cls closure
66 * @param peer id of the peer, NULL for last call
67 * @param hello hello message for the peer (can be NULL)
68 * @param err_msg error message (not used)
69 *
70 * FIXME this is called once per address. Merge instead of replacing?
71 */
72static void
73process_hello (void *cls,
74 const struct GNUNET_PeerIdentity *peer,
75 const struct GNUNET_HELLO_Message *hello,
76 const char *err_msg)
77{
78 struct GNUNET_TIME_Absolute ex;
79 struct GNUNET_HELLO_Message *hm;
80
81 if (NULL == hello)
82 return;
83 ex = GNUNET_HELLO_get_last_expiration (hello);
84 if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us)
85 return;
86 GNUNET_STATISTICS_update (GDS_stats,
87 "# HELLOs obtained from peerinfo",
88 1,
89 GNUNET_NO);
90 hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
91 peer);
92 GNUNET_free (hm);
93 hm = GNUNET_malloc (GNUNET_HELLO_size (hello));
94 GNUNET_memcpy (hm,
95 hello,
96 GNUNET_HELLO_size (hello));
97 GNUNET_assert (GNUNET_SYSERR !=
98 GNUNET_CONTAINER_multipeermap_put (peer_to_hello,
99 peer,
100 hm,
101 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
102}
103
104
105/**
106 * Initialize HELLO subsystem.
107 */
108void
109GDS_HELLO_init ()
110{
111 pnc = GNUNET_PEERINFO_notify (GDS_cfg,
112 GNUNET_NO,
113 &process_hello,
114 NULL);
115 peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256,
116 GNUNET_NO);
117}
118
119
120/**
121 * Free memory occopied by the HELLO.
122 */
123static enum GNUNET_GenericReturnValue
124free_hello (void *cls,
125 const struct GNUNET_PeerIdentity *key,
126 void *hello)
127{
128 GNUNET_free (hello);
129 return GNUNET_OK;
130}
131
132
133/**
134 * Shutdown HELLO subsystem.
135 */
136void
137GDS_HELLO_done ()
138{
139 if (NULL != pnc)
140 {
141 GNUNET_PEERINFO_notify_cancel (pnc);
142 pnc = NULL;
143 }
144 if (NULL != peer_to_hello)
145 {
146 GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello,
147 &free_hello,
148 NULL);
149 GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello);
150 }
151}
152
153
154/* end of gnunet-service-dht_hello.c */
diff --git a/src/dht/gnunet-service-dht_hello.h b/src/dht/gnunet-service-dht_hello.h
deleted file mode 100644
index f8b90862d..000000000
--- a/src/dht/gnunet-service-dht_hello.h
+++ /dev/null
@@ -1,55 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 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 */
20
21/**
22 * @file dht/gnunet-service-dht_hello.h
23 * @brief GNUnet DHT integration with peerinfo
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_DHT_HELLO_H
27#define GNUNET_SERVICE_DHT_HELLO_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_hello_lib.h"
31
32/**
33 * Obtain a peer's HELLO if available
34 *
35 * @param peer peer to look for a HELLO from
36 * @return HELLO for the given peer
37 */
38const struct GNUNET_HELLO_Message *
39GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer);
40
41
42/**
43 * Initialize HELLO subsystem.
44 */
45void
46GDS_HELLO_init (void);
47
48
49/**
50 * Shutdown HELLO subsystem.
51 */
52void
53GDS_HELLO_done (void);
54
55#endif
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c
index cf150ea0c..2f9cbab84 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -28,13 +28,10 @@
28#include "gnunet_constants.h" 28#include "gnunet_constants.h"
29#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
30#include "gnunet_signatures.h" 30#include "gnunet_signatures.h"
31#include "gnunet_ats_service.h"
32#include "gnunet_core_service.h"
33#include "gnunet_hello_lib.h" 31#include "gnunet_hello_lib.h"
32#include "gnunet_hello_uri_lib.h"
34#include "gnunet-service-dht.h" 33#include "gnunet-service-dht.h"
35#include "gnunet-service-dht_hello.h"
36#include "gnunet-service-dht_neighbours.h" 34#include "gnunet-service-dht_neighbours.h"
37#include "gnunet-service-dht_nse.h"
38#include "gnunet-service-dht_routing.h" 35#include "gnunet-service-dht_routing.h"
39#include "dht.h" 36#include "dht.h"
40 37
@@ -42,9 +39,17 @@
42 __VA_ARGS__) 39 __VA_ARGS__)
43 40
44/** 41/**
45 * Enable slow sanity checks to debug issues. 42 * Enable slow sanity checks to debug issues.
43 *
44 * TODO: might want to eventually implement probabilistic
45 * load-based path verification, but for now it is all or nothing
46 * based on this define.
47 *
48 * 0: do not check -- if signatures become performance critical
49 * 1: check all external inputs -- normal production for now
50 * 2: check internal computations as well -- for debugging
46 */ 51 */
47#define SANITY_CHECKS 1 52#define SANITY_CHECKS 2
48 53
49/** 54/**
50 * How many buckets will we allow in total. 55 * How many buckets will we allow in total.
@@ -74,6 +79,7 @@
74#define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \ 79#define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \
75 GNUNET_TIME_UNIT_MINUTES, 2) 80 GNUNET_TIME_UNIT_MINUTES, 2)
76 81
82
77/** 83/**
78 * How long to additionally wait on average per #bucket_size to send out the 84 * How long to additionally wait on average per #bucket_size to send out the
79 * FIND PEER requests if we did successfully connect (!) to a a new peer and 85 * FIND PEER requests if we did successfully connect (!) to a a new peer and
@@ -83,7 +89,7 @@
83 * top). Also the range in which we randomize, so the effective value 89 * top). Also the range in which we randomize, so the effective value
84 * is half of the number given here. 90 * is half of the number given here.
85 */ 91 */
86#define DHT_AVG_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \ 92#define DHT_AVG_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \
87 GNUNET_TIME_UNIT_SECONDS, 6) 93 GNUNET_TIME_UNIT_SECONDS, 6)
88 94
89/** 95/**
@@ -91,11 +97,6 @@
91 */ 97 */
92#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) 98#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
93 99
94/**
95 * Hello address expiration
96 */
97extern struct GNUNET_TIME_Relative hello_expiration;
98
99 100
100GNUNET_NETWORK_STRUCT_BEGIN 101GNUNET_NETWORK_STRUCT_BEGIN
101 102
@@ -263,81 +264,134 @@ GNUNET_NETWORK_STRUCT_END
263/** 264/**
264 * Entry for a peer in a bucket. 265 * Entry for a peer in a bucket.
265 */ 266 */
266struct PeerInfo 267struct PeerInfo;
268
269
270/**
271 * List of targets that we can use to reach this peer.
272 */
273struct Target
267{ 274{
268 /** 275 /**
269 * Next peer entry (DLL) 276 * Kept in a DLL.
270 */ 277 */
271 struct PeerInfo *next; 278 struct Target *next;
272 279
273 /** 280 /**
274 * Prev peer entry (DLL) 281 * Kept in a DLL.
275 */ 282 */
276 struct PeerInfo *prev; 283 struct Target *prev;
277 284
278 /** 285 /**
279 * Handle for sending messages to this peer. 286 * Handle for sending messages to this peer.
280 */ 287 */
281 struct GNUNET_MQ_Handle *mq; 288 struct GNUNET_DHTU_Target *utarget;
282 289
283 /** 290 /**
284 * What is the identity of the peer? 291 * Underlay providing this target.
285 */ 292 */
286 const struct GNUNET_PeerIdentity *id; 293 struct GDS_Underlay *u;
287 294
288 /** 295 /**
289 * Hash of @e id. 296 * Peer this is a target for.
290 */ 297 */
291 struct GNUNET_HashCode phash; 298 struct PeerInfo *pi;
292 299
293 /** 300 /**
294 * Which bucket is this peer in? 301 * Handle used to 'hold' the connection to this peer.
295 */ 302 */
296 int peer_bucket; 303 struct GNUNET_DHTU_PreferenceHandle *ph;
304
305 /**
306 * Set to number of messages are waiting for the transmission to finish.
307 */
308 unsigned int load;
309
310 /**
311 * Set to @a true if the target was dropped, but we could not clean
312 * up yet because @e busy was also true.
313 */
314 bool dropped;
315
297}; 316};
298 317
299 318
300/** 319/**
301 * Peers are grouped into buckets. 320 * Entry for a peer in a bucket.
302 */ 321 */
303struct PeerBucket 322struct PeerInfo
304{ 323{
305 /** 324 /**
306 * Head of DLL 325 * What is the identity of the peer?
307 */ 326 */
308 struct PeerInfo *head; 327 struct GNUNET_PeerIdentity id;
309 328
310 /** 329 /**
311 * Tail of DLL 330 * Hash of @e id.
312 */ 331 */
313 struct PeerInfo *tail; 332 struct GNUNET_HashCode phash;
314 333
315 /** 334 /**
316 * Number of peers in the bucket. 335 * When does our HELLO from this peer expire?
317 */ 336 */
318 unsigned int peers_size; 337 struct GNUNET_TIME_Absolute hello_expiration;
338
339 /**
340 * Next peer entry (DLL)
341 */
342 struct PeerInfo *next;
343
344 /**
345 * Prev peer entry (DLL)
346 */
347 struct PeerInfo *prev;
348
349 /**
350 * Head of DLL of targets for this peer.
351 */
352 struct Target *t_head;
353
354 /**
355 * Tail of DLL of targets for this peer.
356 */
357 struct Target *t_tail;
358
359 /**
360 * Block with a HELLO of this peer.
361 */
362 void *hello;
363
364 /**
365 * Number of bytes in @e hello.
366 */
367 size_t hello_size;
368
369 /**
370 * Which bucket is this peer in?
371 */
372 int peer_bucket;
319}; 373};
320 374
321 375
322/** 376/**
323 * Information about a peer that we would like to connect to. 377 * Peers are grouped into buckets.
324 */ 378 */
325struct ConnectInfo 379struct PeerBucket
326{ 380{
327 /** 381 /**
328 * Handle to active HELLO offer operation, or NULL. 382 * Head of DLL
329 */ 383 */
330 struct GNUNET_TRANSPORT_OfferHelloHandle *oh; 384 struct PeerInfo *head;
331 385
332 /** 386 /**
333 * Handle to active connectivity suggestion operation, or NULL. 387 * Tail of DLL
334 */ 388 */
335 struct GNUNET_ATS_ConnectivitySuggestHandle *sh; 389 struct PeerInfo *tail;
336 390
337 /** 391 /**
338 * How much would we like to connect to this peer? 392 * Number of peers in the bucket.
339 */ 393 */
340 uint32_t strength; 394 unsigned int peers_size;
341}; 395};
342 396
343 397
@@ -374,12 +428,6 @@ static struct PeerBucket k_buckets[MAX_BUCKETS];
374static struct GNUNET_CONTAINER_MultiPeerMap *all_connected_peers; 428static struct GNUNET_CONTAINER_MultiPeerMap *all_connected_peers;
375 429
376/** 430/**
377 * Hash map of all peers we would like to be connected to.
378 * Values are of type `struct ConnectInfo`.
379 */
380static struct GNUNET_CONTAINER_MultiPeerMap *all_desired_peers;
381
382/**
383 * Maximum size for each bucket. 431 * Maximum size for each bucket.
384 */ 432 */
385static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; 433static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
@@ -389,30 +437,83 @@ static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
389 */ 437 */
390static struct GNUNET_SCHEDULER_Task *find_peer_task; 438static struct GNUNET_SCHEDULER_Task *find_peer_task;
391 439
392/**
393 * Identity of this peer.
394 */
395static struct GNUNET_PeerIdentity my_identity;
396 440
397/** 441/**
398 * Hash of the identity of this peer. 442 * Function called whenever we finished sending to a target.
443 * Marks the transmission as finished (and the target as ready
444 * for the next message).
445 *
446 * @param cls a `struct Target *`
399 */ 447 */
400struct GNUNET_HashCode my_identity_hash; 448static void
449send_done_cb (void *cls)
450{
451 struct Target *t = cls;
452 struct PeerInfo *pi = t->pi; /* NULL if t->dropped! */
401 453
402/** 454 GNUNET_assert (t->load > 0);
403 * Handle to CORE. 455 t->load--;
404 */ 456 if (0 < t->load)
405static struct GNUNET_CORE_Handle *core_api; 457 return;
458 if (t->dropped)
459 {
460 GNUNET_free (t);
461 return;
462 }
463 /* move target back to the front */
464 GNUNET_CONTAINER_DLL_remove (pi->t_head,
465 pi->t_tail,
466 t);
467 GNUNET_CONTAINER_DLL_insert (pi->t_head,
468 pi->t_tail,
469 t);
470}
406 471
407/**
408 * Handle to ATS connectivity.
409 */
410static struct GNUNET_ATS_ConnectivityHandle *ats_ch;
411 472
412/** 473/**
413 * Our private key. 474 * Send @a msg to @a pi.
475 *
476 * @param pi where to send the message
477 * @param msg message to send
414 */ 478 */
415static struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key; 479static void
480do_send (struct PeerInfo *pi,
481 const struct GNUNET_MessageHeader *msg)
482{
483 struct Target *t;
484
485 for (t = pi->t_head;
486 NULL != t;
487 t = t->next)
488 if (t->load < MAXIMUM_PENDING_PER_PEER)
489 break;
490 if (NULL == t)
491 {
492 /* all targets busy, drop message */
493 GNUNET_STATISTICS_update (GDS_stats,
494 "# messages dropped (underlays busy)",
495 1,
496 GNUNET_NO);
497 return;
498 }
499 t->load++;
500 /* rotate busy targets to the end */
501 if (MAXIMUM_PENDING_PER_PEER == t->load)
502 {
503 GNUNET_CONTAINER_DLL_remove (pi->t_head,
504 pi->t_tail,
505 t);
506 GNUNET_CONTAINER_DLL_insert_tail (pi->t_head,
507 pi->t_tail,
508 t);
509 }
510 GDS_u_send (t->u,
511 t->utarget,
512 msg,
513 ntohs (msg->size),
514 &send_done_cb,
515 t);
516}
416 517
417 518
418/** 519/**
@@ -426,11 +527,10 @@ static struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key;
426 * @param pred predecessor peer ID 527 * @param pred predecessor peer ID
427 * @param succ successor peer ID 528 * @param succ successor peer ID
428 * @param[out] sig where to write the signature 529 * @param[out] sig where to write the signature
429 * (of purpose #GNUNET_SIGNATURE_PURPOSE_DHT_HOP) 530 * (of purpose #GNUNET_SIGNATURE_PURPOSE_DHT_PUT_HOP)
430 */ 531 */
431static void 532static void
432sign_path (const struct GNUNET_HashCode *key, 533sign_path (const void *data,
433 const void *data,
434 size_t data_size, 534 size_t data_size,
435 struct GNUNET_TIME_Absolute exp_time, 535 struct GNUNET_TIME_Absolute exp_time,
436 const struct GNUNET_PeerIdentity *pred, 536 const struct GNUNET_PeerIdentity *pred,
@@ -441,7 +541,6 @@ sign_path (const struct GNUNET_HashCode *key,
441 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DHT_HOP), 541 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DHT_HOP),
442 .purpose.size = htonl (sizeof (hs)), 542 .purpose.size = htonl (sizeof (hs)),
443 .expiration_time = GNUNET_TIME_absolute_hton (exp_time), 543 .expiration_time = GNUNET_TIME_absolute_hton (exp_time),
444 .key = *key,
445 .pred = *pred, 544 .pred = *pred,
446 .succ = *succ 545 .succ = *succ
447 }; 546 };
@@ -449,7 +548,7 @@ sign_path (const struct GNUNET_HashCode *key,
449 GNUNET_CRYPTO_hash (data, 548 GNUNET_CRYPTO_hash (data,
450 data_size, 549 data_size,
451 &hs.h_data); 550 &hs.h_data);
452 GNUNET_CRYPTO_eddsa_sign (&my_private_key, 551 GNUNET_CRYPTO_eddsa_sign (&GDS_my_private_key,
453 &hs, 552 &hs,
454 sig); 553 sig);
455} 554}
@@ -469,7 +568,7 @@ find_bucket (const struct GNUNET_HashCode *hc)
469 unsigned int bits; 568 unsigned int bits;
470 569
471 GNUNET_CRYPTO_hash_xor (hc, 570 GNUNET_CRYPTO_hash_xor (hc,
472 &my_identity_hash, 571 &GDS_my_identity_hash,
473 &xor); 572 &xor);
474 bits = GNUNET_CRYPTO_hash_count_leading_zeros (&xor); 573 bits = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
475 if (bits == MAX_BUCKETS) 574 if (bits == MAX_BUCKETS)
@@ -483,171 +582,6 @@ find_bucket (const struct GNUNET_HashCode *hc)
483 582
484 583
485/** 584/**
486 * Function called when #GNUNET_TRANSPORT_offer_hello() is done.
487 * Clean up the "oh" field in the @a cls
488 *
489 * @param cls a `struct ConnectInfo`
490 */
491static void
492offer_hello_done (void *cls)
493{
494 struct ConnectInfo *ci = cls;
495
496 ci->oh = NULL;
497}
498
499
500/**
501 * Function called for all entries in #all_desired_peers to clean up.
502 *
503 * @param cls NULL
504 * @param peer peer the entry is for
505 * @param value the value to remove
506 * @return #GNUNET_YES
507 */
508static enum GNUNET_GenericReturnValue
509free_connect_info (void *cls,
510 const struct GNUNET_PeerIdentity *peer,
511 void *value)
512{
513 struct ConnectInfo *ci = value;
514
515 (void) cls;
516 GNUNET_assert (GNUNET_YES ==
517 GNUNET_CONTAINER_multipeermap_remove (all_desired_peers,
518 peer,
519 ci));
520 if (NULL != ci->sh)
521 {
522 GNUNET_ATS_connectivity_suggest_cancel (ci->sh);
523 ci->sh = NULL;
524 }
525 if (NULL != ci->oh)
526 {
527 GNUNET_TRANSPORT_offer_hello_cancel (ci->oh);
528 ci->oh = NULL;
529 }
530 GNUNET_free (ci);
531 return GNUNET_YES;
532}
533
534
535/**
536 * Consider if we want to connect to a given peer, and if so
537 * let ATS know. If applicable, the HELLO is offered to the
538 * TRANSPORT service.
539 *
540 * @param pid peer to consider connectivity requirements for
541 * @param h a HELLO message, or NULL
542 */
543static void
544try_connect (const struct GNUNET_PeerIdentity *pid,
545 const struct GNUNET_MessageHeader *h)
546{
547 int bucket_idx;
548 struct GNUNET_HashCode pid_hash;
549 struct ConnectInfo *ci;
550 uint32_t strength;
551 struct PeerBucket *bucket;
552
553 GNUNET_CRYPTO_hash (pid,
554 sizeof(struct GNUNET_PeerIdentity),
555 &pid_hash);
556 bucket_idx = find_bucket (&pid_hash);
557 if (bucket_idx < 0)
558 {
559 GNUNET_break (0);
560 return; /* self!? */
561 }
562 bucket = &k_buckets[bucket_idx];
563 ci = GNUNET_CONTAINER_multipeermap_get (all_desired_peers,
564 pid);
565 if (bucket->peers_size < bucket_size)
566 strength = (bucket_size - bucket->peers_size) * bucket_idx;
567 else
568 strength = 0;
569 if (GNUNET_YES ==
570 GNUNET_CONTAINER_multipeermap_contains (all_connected_peers,
571 pid))
572 strength *= 2; /* double for connected peers */
573 if ( (0 == strength) &&
574 (NULL != ci) )
575 {
576 /* release request */
577 GNUNET_assert (GNUNET_YES ==
578 free_connect_info (NULL,
579 pid,
580 ci));
581 return;
582 }
583 if (NULL == ci)
584 {
585 ci = GNUNET_new (struct ConnectInfo);
586 GNUNET_assert (GNUNET_OK ==
587 GNUNET_CONTAINER_multipeermap_put (all_desired_peers,
588 pid,
589 ci,
590 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
591 }
592 if ( (NULL != ci->oh) &&
593 (NULL != h) )
594 GNUNET_TRANSPORT_offer_hello_cancel (ci->oh);
595 if (NULL != h)
596 ci->oh = GNUNET_TRANSPORT_offer_hello (GDS_cfg,
597 h,
598 &offer_hello_done,
599 ci);
600 if ( (NULL != ci->sh) &&
601 (ci->strength != strength) )
602 GNUNET_ATS_connectivity_suggest_cancel (ci->sh);
603 if (ci->strength != strength)
604 {
605 ci->sh = GNUNET_ATS_connectivity_suggest (ats_ch,
606 pid,
607 strength);
608 ci->strength = strength;
609 }
610}
611
612
613/**
614 * Function called for each peer in #all_desired_peers during
615 * #update_connect_preferences() if we have reason to adjust
616 * the strength of our desire to keep connections to certain
617 * peers. Calls #try_connect() to update the calculations for
618 * the given @a pid.
619 *
620 * @param cls NULL
621 * @param pid peer to update
622 * @param value unused
623 * @return #GNUNET_YES (continue to iterate)
624 */
625static enum GNUNET_GenericReturnValue
626update_desire_strength (void *cls,
627 const struct GNUNET_PeerIdentity *pid,
628 void *value)
629{
630 (void) cls;
631 (void) value;
632 try_connect (pid,
633 NULL);
634 return GNUNET_YES;
635}
636
637
638/**
639 * Update our preferences for connectivity as given to ATS.
640 */
641static void
642update_connect_preferences (void)
643{
644 GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
645 &update_desire_strength,
646 NULL);
647}
648
649
650/**
651 * Add each of the peers we already know to the Bloom filter of 585 * Add each of the peers we already know to the Bloom filter of
652 * the request so that we don't get duplicate HELLOs. 586 * the request so that we don't get duplicate HELLOs.
653 * 587 *
@@ -702,7 +636,7 @@ send_find_peer_message (void *cls)
702 GNUNET_CRYPTO_QUALITY_WEAK, 636 GNUNET_CRYPTO_QUALITY_WEAK,
703 GNUNET_TIME_relative_multiply ( 637 GNUNET_TIME_relative_multiply (
704 DHT_AVG_FIND_PEER_INTERVAL, 638 DHT_AVG_FIND_PEER_INTERVAL,
705 100 * (1 + newly_found_peers) / bucket_size).rel_value_us); 639 1 + 100 * (1 + newly_found_peers) / bucket_size).rel_value_us);
706 newly_found_peers = 0; 640 newly_found_peers = 0;
707 GNUNET_assert (NULL == find_peer_task); 641 GNUNET_assert (NULL == find_peer_task);
708 find_peer_task = 642 find_peer_task =
@@ -719,7 +653,7 @@ send_find_peer_message (void *cls)
719 struct GNUNET_CONTAINER_BloomFilter *peer_bf; 653 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
720 654
721 bg = GNUNET_BLOCK_group_create (GDS_block_context, 655 bg = GNUNET_BLOCK_group_create (GDS_block_context,
722 GNUNET_BLOCK_TYPE_DHT_HELLO, 656 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
723 GNUNET_CRYPTO_random_u32 ( 657 GNUNET_CRYPTO_random_u32 (
724 GNUNET_CRYPTO_QUALITY_WEAK, 658 GNUNET_CRYPTO_QUALITY_WEAK,
725 UINT32_MAX), 659 UINT32_MAX),
@@ -736,12 +670,12 @@ send_find_peer_message (void *cls)
736 DHT_BLOOM_SIZE, 670 DHT_BLOOM_SIZE,
737 GNUNET_CONSTANTS_BLOOMFILTER_K); 671 GNUNET_CONSTANTS_BLOOMFILTER_K);
738 if (GNUNET_OK != 672 if (GNUNET_OK !=
739 GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_HELLO, 673 GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
740 GNUNET_DHT_RO_FIND_PEER 674 GNUNET_DHT_RO_FIND_APPROXIMATE
741 | GNUNET_DHT_RO_RECORD_ROUTE, 675 | GNUNET_DHT_RO_RECORD_ROUTE,
742 FIND_PEER_REPLICATION_LEVEL, 676 FIND_PEER_REPLICATION_LEVEL,
743 0, /* hop count */ 677 0, /* hop count */
744 &my_identity_hash, 678 &GDS_my_identity_hash,
745 NULL, 0, /* xquery */ 679 NULL, 0, /* xquery */
746 bg, 680 bg,
747 peer_bf)) 681 peer_bf))
@@ -765,123 +699,180 @@ send_find_peer_message (void *cls)
765 699
766 700
767/** 701/**
768 * Method called whenever a peer connects. 702 * The list of the first #bucket_size peers of @a bucket
703 * changed. We should thus make sure we have called 'hold'
704 * all of the first bucket_size peers!
769 * 705 *
770 * @param cls closure 706 * @param[in,out] bucket the bucket where the peer set changed
771 * @param peer peer identity this notification is about
772 * @param mq message queue for sending messages to @a peer
773 * @return our `struct PeerInfo` for @a peer
774 */ 707 */
775static void * 708static void
776handle_core_connect (void *cls, 709update_hold (struct PeerBucket *bucket)
777 const struct GNUNET_PeerIdentity *peer,
778 struct GNUNET_MQ_Handle *mq)
779{ 710{
711 unsigned int off = 0;
712
713 /* find the peer -- we just go over all of them, should
714 be hardly any more expensive than just finding the 'right'
715 one. */
716 for (struct PeerInfo *pos = bucket->head;
717 NULL != pos;
718 pos = pos->next)
719 {
720 if (off > bucket_size)
721 break; /* We only hold up to #bucket_size peers per bucket */
722 off++;
723 for (struct Target *tp = pos->t_head;
724 NULL != tp;
725 tp = tp->next)
726 if (NULL == tp->ph)
727 tp->ph = GDS_u_hold (tp->u,
728 tp->utarget);
729 }
730}
731
732
733void
734GDS_u_connect (void *cls,
735 struct GNUNET_DHTU_Target *target,
736 const struct GNUNET_PeerIdentity *pid,
737 void **ctx)
738{
739 struct GDS_Underlay *u = cls;
780 struct PeerInfo *pi; 740 struct PeerInfo *pi;
781 struct PeerBucket *bucket; 741 struct PeerBucket *bucket;
742 bool do_hold = false;
782 743
783 (void) cls;
784 /* Check for connect to self message */ 744 /* Check for connect to self message */
785 if (0 == GNUNET_memcmp (&my_identity, 745 if (0 == GNUNET_memcmp (&GDS_my_identity,
786 peer)) 746 pid))
787 return NULL; 747 return;
788 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
789 "Connected to peer %s\n", 749 "Connected to peer %s\n",
790 GNUNET_i2s (peer)); 750 GNUNET_i2s (pid));
791 GNUNET_assert (NULL == 751 pi = GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
792 GNUNET_CONTAINER_multipeermap_get (all_connected_peers, 752 pid);
793 peer)); 753 if (NULL == pi)
794 GNUNET_STATISTICS_update (GDS_stats,
795 "# peers connected",
796 1,
797 GNUNET_NO);
798 pi = GNUNET_new (struct PeerInfo);
799 pi->id = peer;
800 pi->mq = mq;
801 GNUNET_CRYPTO_hash (peer,
802 sizeof(struct GNUNET_PeerIdentity),
803 &pi->phash);
804 pi->peer_bucket = find_bucket (&pi->phash);
805 GNUNET_assert ( (pi->peer_bucket >= 0) &&
806 ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
807 bucket = &k_buckets[pi->peer_bucket];
808 GNUNET_CONTAINER_DLL_insert_tail (bucket->head,
809 bucket->tail,
810 pi);
811 bucket->peers_size++;
812 closest_bucket = GNUNET_MAX (closest_bucket,
813 (unsigned int) pi->peer_bucket + 1);
814 GNUNET_assert (GNUNET_OK ==
815 GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
816 pi->id,
817 pi,
818 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
819 if (bucket->peers_size <= bucket_size)
820 { 754 {
821 update_connect_preferences (); 755 GNUNET_STATISTICS_update (GDS_stats,
822 newly_found_peers++; 756 "# peers connected",
757 1,
758 GNUNET_NO);
759 pi = GNUNET_new (struct PeerInfo);
760 pi->id = *pid;
761 GNUNET_CRYPTO_hash (pid,
762 sizeof(*pid),
763 &pi->phash);
764 pi->peer_bucket = find_bucket (&pi->phash);
765 GNUNET_assert ( (pi->peer_bucket >= 0) &&
766 ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
767 bucket = &k_buckets[pi->peer_bucket];
768 GNUNET_CONTAINER_DLL_insert_tail (bucket->head,
769 bucket->tail,
770 pi);
771 bucket->peers_size++;
772 closest_bucket = GNUNET_MAX (closest_bucket,
773 (unsigned int) pi->peer_bucket + 1);
774 GNUNET_assert (GNUNET_OK ==
775 GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
776 &pi->id,
777 pi,
778 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
779 if (bucket->peers_size <= bucket_size)
780 {
781 newly_found_peers++;
782 do_hold = true;
783 }
784 if ( (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
785 (GNUNET_YES != disable_try_connect) )
786 {
787 /* got a first connection, good time to start with FIND PEER requests... */
788 GNUNET_assert (NULL == find_peer_task);
789 find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message,
790 NULL);
791 }
823 } 792 }
824 if ( (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
825 (GNUNET_YES != disable_try_connect) )
826 { 793 {
827 /* got a first connection, good time to start with FIND PEER requests... */ 794 struct Target *t;
828 GNUNET_assert (NULL == find_peer_task); 795
829 find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message, 796 t = GNUNET_new (struct Target);
830 NULL); 797 t->u = u;
798 t->utarget = target;
799 t->pi = pi;
800 GNUNET_CONTAINER_DLL_insert (pi->t_head,
801 pi->t_tail,
802 t);
803 *ctx = t;
804
831 } 805 }
832 return pi; 806 if (do_hold)
807 update_hold (bucket);
833} 808}
834 809
835 810
836/** 811void
837 * Method called whenever a peer disconnects. 812GDS_u_disconnect (void *ctx)
838 *
839 * @param cls closure
840 * @param peer peer identity this notification is about
841 * @param internal_cls our `struct PeerInfo` for @a peer
842 */
843static void
844handle_core_disconnect (void *cls,
845 const struct GNUNET_PeerIdentity *peer,
846 void *internal_cls)
847{ 813{
848 struct PeerInfo *to_remove = internal_cls; 814 struct Target *t = ctx;
815 struct PeerInfo *pi;
849 struct PeerBucket *bucket; 816 struct PeerBucket *bucket;
817 bool was_held = false;
850 818
851 (void) cls;
852 /* Check for disconnect from self message (on shutdown) */ 819 /* Check for disconnect from self message (on shutdown) */
853 if (NULL == to_remove) 820 if (NULL == t)
854 return; 821 return;
822 pi = t->pi;
823 GNUNET_CONTAINER_DLL_remove (pi->t_head,
824 pi->t_tail,
825 t);
826 if (NULL != t->ph)
827 {
828 GDS_u_drop (t->u,
829 t->ph);
830 t->ph = NULL;
831 was_held = true;
832 }
833 if (t->load > 0)
834 {
835 t->dropped = true;
836 t->pi = NULL;
837 }
838 else
839 {
840 GNUNET_free (t);
841 }
842 if (NULL != pi->t_head)
843 return; /* got other connections still */
855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 844 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
856 "Disconnected from peer %s\n", 845 "Disconnected from peer %s\n",
857 GNUNET_i2s (peer)); 846 GNUNET_i2s (&pi->id));
858 GNUNET_STATISTICS_update (GDS_stats, 847 GNUNET_STATISTICS_update (GDS_stats,
859 "# peers connected", 848 "# peers connected",
860 -1, 849 -1,
861 GNUNET_NO); 850 GNUNET_NO);
862 GNUNET_assert (GNUNET_YES == 851 GNUNET_assert (GNUNET_YES ==
863 GNUNET_CONTAINER_multipeermap_remove (all_connected_peers, 852 GNUNET_CONTAINER_multipeermap_remove (all_connected_peers,
864 peer, 853 &pi->id,
865 to_remove)); 854 pi));
866 if ( (0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) && 855 if ( (0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
867 (GNUNET_YES != disable_try_connect)) 856 (GNUNET_YES != disable_try_connect))
868 { 857 {
869 GNUNET_SCHEDULER_cancel (find_peer_task); 858 GNUNET_SCHEDULER_cancel (find_peer_task);
870 find_peer_task = NULL; 859 find_peer_task = NULL;
871 } 860 }
872 GNUNET_assert (to_remove->peer_bucket >= 0); 861 GNUNET_assert (pi->peer_bucket >= 0);
873 bucket = &k_buckets[to_remove->peer_bucket]; 862 bucket = &k_buckets[pi->peer_bucket];
874 GNUNET_CONTAINER_DLL_remove (bucket->head, 863 GNUNET_CONTAINER_DLL_remove (bucket->head,
875 bucket->tail, 864 bucket->tail,
876 to_remove); 865 pi);
877 GNUNET_assert (bucket->peers_size > 0); 866 GNUNET_assert (bucket->peers_size > 0);
878 bucket->peers_size--; 867 bucket->peers_size--;
868 if ( (was_held) &&
869 (bucket->peers_size >= bucket_size - 1) )
870 update_hold (bucket);
879 while ( (closest_bucket > 0) && 871 while ( (closest_bucket > 0) &&
880 (0 == k_buckets[closest_bucket - 1].peers_size)) 872 (0 == k_buckets[closest_bucket - 1].peers_size))
881 closest_bucket--; 873 closest_bucket--;
882 if (bucket->peers_size < bucket_size) 874 GNUNET_free (pi->hello);
883 update_connect_preferences (); 875 GNUNET_free (pi);
884 GNUNET_free (to_remove);
885} 876}
886 877
887 878
@@ -894,17 +885,14 @@ handle_core_disconnect (void *cls,
894 * @return Some number of peers to forward the message to 885 * @return Some number of peers to forward the message to
895 */ 886 */
896static unsigned int 887static unsigned int
897get_forward_count (uint32_t hop_count, 888get_forward_count (uint16_t hop_count,
898 uint32_t target_replication) 889 uint16_t target_replication)
899{ 890{
900 uint32_t random_value; 891 uint32_t random_value;
901 uint32_t forward_count; 892 uint32_t forward_count;
902 float target_value; 893 float target_value;
894 float rm1;
903 895
904 if (0 == target_replication)
905 target_replication = 1; /* 0 is verboten */
906 if (target_replication > GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL)
907 target_replication = GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL;
908 if (hop_count > GDS_NSE_get () * 4.0) 896 if (hop_count > GDS_NSE_get () * 4.0)
909 { 897 {
910 /* forcefully terminate */ 898 /* forcefully terminate */
@@ -919,15 +907,15 @@ get_forward_count (uint32_t hop_count,
919 /* Once we have reached our ideal number of hops, only forward to 1 peer */ 907 /* Once we have reached our ideal number of hops, only forward to 1 peer */
920 return 1; 908 return 1;
921 } 909 }
922 /* bound by system-wide maximum */ 910 /* bound by system-wide maximum and minimum */
911 if (0 == target_replication)
912 target_replication = 1; /* 0 is verboten */
923 target_replication = 913 target_replication =
924 GNUNET_MIN (GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL, 914 GNUNET_MIN (GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL,
925 target_replication); 915 target_replication);
916 rm1 = target_replication - 1.0;
926 target_value = 917 target_value =
927 1 + (target_replication - 1.0) / (GDS_NSE_get () 918 1 + (rm1) / (GDS_NSE_get () + (rm1 * hop_count));
928 + ((float) (target_replication - 1.0)
929 * hop_count));
930
931 919
932 /* Set forward count to floor of target_value */ 920 /* Set forward count to floor of target_value */
933 forward_count = (uint32_t) target_value; 921 forward_count = (uint32_t) target_value;
@@ -956,7 +944,7 @@ enum GNUNET_GenericReturnValue
956GDS_am_closest_peer (const struct GNUNET_HashCode *key, 944GDS_am_closest_peer (const struct GNUNET_HashCode *key,
957 const struct GNUNET_CONTAINER_BloomFilter *bloom) 945 const struct GNUNET_CONTAINER_BloomFilter *bloom)
958{ 946{
959 if (0 == GNUNET_memcmp (&my_identity_hash, 947 if (0 == GNUNET_memcmp (&GDS_my_identity_hash,
960 key)) 948 key))
961 return GNUNET_YES; 949 return GNUNET_YES;
962 for (int bucket_num = find_bucket (key); 950 for (int bucket_num = find_bucket (key);
@@ -983,7 +971,7 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
983 because an unfiltered peer exists, we are not the 971 because an unfiltered peer exists, we are not the
984 closest. */ 972 closest. */
985 int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash, 973 int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
986 &my_identity_hash, 974 &GDS_my_identity_hash,
987 key); 975 key);
988 switch (delta) 976 switch (delta)
989 { 977 {
@@ -1047,7 +1035,7 @@ select_peer (const struct GNUNET_HashCode *key,
1047 struct GNUNET_HashCode xor; 1035 struct GNUNET_HashCode xor;
1048 1036
1049 GNUNET_CRYPTO_hash_xor (key, 1037 GNUNET_CRYPTO_hash_xor (key,
1050 &my_identity_hash, 1038 &GDS_my_identity_hash,
1051 &xor); 1039 &xor);
1052 best_bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor); 1040 best_bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
1053 } 1041 }
@@ -1067,13 +1055,14 @@ select_peer (const struct GNUNET_HashCode *key,
1067 if (count >= bucket_size) 1055 if (count >= bucket_size)
1068 break; /* we only consider first #bucket_size entries per bucket */ 1056 break; /* we only consider first #bucket_size entries per bucket */
1069 count++; 1057 count++;
1070 if (GNUNET_YES == 1058 if ( (NULL != bloom) &&
1071 GNUNET_CONTAINER_bloomfilter_test (bloom, 1059 (GNUNET_YES ==
1072 &pos->phash)) 1060 GNUNET_CONTAINER_bloomfilter_test (bloom,
1061 &pos->phash)) )
1073 { 1062 {
1074 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1063 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1075 "Excluded peer `%s' due to BF match in greedy routing for %s\n", 1064 "Excluded peer `%s' due to BF match in greedy routing for %s\n",
1076 GNUNET_i2s (pos->id), 1065 GNUNET_i2s (&pos->id),
1077 GNUNET_h2s (key)); 1066 GNUNET_h2s (key));
1078 continue; 1067 continue;
1079 } 1068 }
@@ -1140,7 +1129,7 @@ select_peer (const struct GNUNET_HashCode *key,
1140 } 1129 }
1141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1130 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1142 "Selected peer `%s' in greedy routing for %s\n", 1131 "Selected peer `%s' in greedy routing for %s\n",
1143 GNUNET_i2s (chosen->id), 1132 GNUNET_i2s (&chosen->id),
1144 GNUNET_h2s (key)); 1133 GNUNET_h2s (key));
1145 return chosen; 1134 return chosen;
1146 } /* end of 'greedy' peer selection */ 1135 } /* end of 'greedy' peer selection */
@@ -1155,22 +1144,24 @@ select_peer (const struct GNUNET_HashCode *key,
1155 1144
1156 for (unsigned int bc = 0; bc < closest_bucket; bc++) 1145 for (unsigned int bc = 0; bc < closest_bucket; bc++)
1157 { 1146 {
1147 struct PeerBucket *bucket = &k_buckets[bc];
1158 unsigned int count = 0; 1148 unsigned int count = 0;
1159 1149
1160 for (struct PeerInfo *pos = k_buckets[bc].head; 1150 for (struct PeerInfo *pos = bucket->head;
1161 NULL != pos; 1151 NULL != pos;
1162 pos = pos->next) 1152 pos = pos->next)
1163 { 1153 {
1164 count++; 1154 count++;
1165 if (count > bucket_size) 1155 if (count > bucket_size)
1166 break; /* limits search to #bucket_size peers per bucket */ 1156 break; /* limits search to #bucket_size peers per bucket */
1167 if (GNUNET_YES == 1157 if ( (NULL != bloom) &&
1168 GNUNET_CONTAINER_bloomfilter_test (bloom, 1158 (GNUNET_YES ==
1169 &pos->phash)) 1159 GNUNET_CONTAINER_bloomfilter_test (bloom,
1160 &pos->phash)) )
1170 { 1161 {
1171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1162 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1172 "Excluded peer `%s' due to BF match in random routing for %s\n", 1163 "Excluded peer `%s' due to BF match in random routing for %s\n",
1173 GNUNET_i2s (pos->id), 1164 GNUNET_i2s (&pos->id),
1174 GNUNET_h2s (key)); 1165 GNUNET_h2s (key));
1175 continue; /* Ignore filtered peers */ 1166 continue; /* Ignore filtered peers */
1176 } 1167 }
@@ -1201,15 +1192,16 @@ select_peer (const struct GNUNET_HashCode *key,
1201 if (count > bucket_size) 1192 if (count > bucket_size)
1202 break; /* limits search to #bucket_size peers per bucket */ 1193 break; /* limits search to #bucket_size peers per bucket */
1203 1194
1204 if (GNUNET_YES == 1195 if ( (NULL != bloom) &&
1205 GNUNET_CONTAINER_bloomfilter_test (bloom, 1196 (GNUNET_YES ==
1206 &pos->phash)) 1197 GNUNET_CONTAINER_bloomfilter_test (bloom,
1198 &pos->phash)) )
1207 continue; /* Ignore bloomfiltered peers */ 1199 continue; /* Ignore bloomfiltered peers */
1208 if (0 == selected--) 1200 if (0 == selected--)
1209 { 1201 {
1210 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1211 "Selected peer `%s' in random routing for %s\n", 1203 "Selected peer `%s' in random routing for %s\n",
1212 GNUNET_i2s (pos->id), 1204 GNUNET_i2s (&pos->id),
1213 GNUNET_h2s (key)); 1205 GNUNET_h2s (key));
1214 return pos; 1206 return pos;
1215 } 1207 }
@@ -1237,8 +1229,8 @@ select_peer (const struct GNUNET_HashCode *key,
1237static unsigned int 1229static unsigned int
1238get_target_peers (const struct GNUNET_HashCode *key, 1230get_target_peers (const struct GNUNET_HashCode *key,
1239 struct GNUNET_CONTAINER_BloomFilter *bloom, 1231 struct GNUNET_CONTAINER_BloomFilter *bloom,
1240 uint32_t hop_count, 1232 uint16_t hop_count,
1241 uint32_t target_replication, 1233 uint16_t target_replication,
1242 struct PeerInfo ***targets) 1234 struct PeerInfo ***targets)
1243{ 1235{
1244 unsigned int target; 1236 unsigned int target;
@@ -1294,11 +1286,36 @@ get_target_peers (const struct GNUNET_HashCode *key,
1294} 1286}
1295 1287
1296 1288
1289/**
1290 * If we got a HELLO, consider it for our own routing table
1291 *
1292 * @param bd block data we got
1293 */
1294static void
1295hello_check (const struct GDS_DATACACHE_BlockData *bd)
1296{
1297 struct GNUNET_PeerIdentity pid;
1298 struct GNUNET_HELLO_Builder *b;
1299
1300 if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO != bd->type)
1301 return;
1302
1303 b = GNUNET_HELLO_builder_from_block (bd->data,
1304 bd->data_size);
1305 if (GNUNET_YES != disable_try_connect)
1306 GNUNET_HELLO_builder_iterate (b,
1307 &pid,
1308 &GDS_try_connect,
1309 &pid);
1310 GNUNET_HELLO_builder_free (b);
1311}
1312
1313
1297enum GNUNET_GenericReturnValue 1314enum GNUNET_GenericReturnValue
1298GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd, 1315GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1299 enum GNUNET_DHT_RouteOption options, 1316 enum GNUNET_DHT_RouteOption options,
1300 uint32_t desired_replication_level, 1317 uint16_t desired_replication_level,
1301 uint32_t hop_count, 1318 uint16_t hop_count,
1302 struct GNUNET_CONTAINER_BloomFilter *bf) 1319 struct GNUNET_CONTAINER_BloomFilter *bf)
1303{ 1320{
1304 unsigned int target_count; 1321 unsigned int target_count;
@@ -1308,27 +1325,31 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1308 unsigned int put_path_length = bd->put_path_length; 1325 unsigned int put_path_length = bd->put_path_length;
1309 1326
1310 GNUNET_assert (NULL != bf); 1327 GNUNET_assert (NULL != bf);
1311#if SANITY_CHECKS 1328#if SANITY_CHECKS > 1
1312 if (0 != 1329 if (0 !=
1313 GNUNET_DHT_verify_path (&bd->key, 1330 GNUNET_DHT_verify_path (bd->data,
1314 bd->data,
1315 bd->data_size, 1331 bd->data_size,
1316 bd->expiration_time, 1332 bd->expiration_time,
1317 bd->put_path, 1333 bd->put_path,
1318 bd->put_path_length, 1334 bd->put_path_length,
1319 NULL, 0, /* get_path */ 1335 NULL, 0, /* get_path */
1320 &my_identity)) 1336 &GDS_my_identity))
1321 { 1337 {
1322 GNUNET_break_op (0); 1338 GNUNET_break_op (0);
1323 put_path_length = 0; 1339 put_path_length = 0;
1324 } 1340 }
1325#endif 1341#endif
1326 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1327 "Adding myself (%s) to PUT bloomfilter for %s\n", 1343 "Adding myself (%s) to PUT bloomfilter for %s with RO(%s/%s)\n",
1328 GNUNET_i2s (&my_identity), 1344 GNUNET_i2s (&GDS_my_identity),
1329 GNUNET_h2s (&bd->key)); 1345 GNUNET_h2s (&bd->key),
1346 (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
1347 (options & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
1348
1349 /* if we got a HELLO, consider it for our own routing table */
1350 hello_check (bd);
1330 GNUNET_CONTAINER_bloomfilter_add (bf, 1351 GNUNET_CONTAINER_bloomfilter_add (bf,
1331 &my_identity_hash); 1352 &GDS_my_identity_hash);
1332 GNUNET_STATISTICS_update (GDS_stats, 1353 GNUNET_STATISTICS_update (GDS_stats,
1333 "# PUT requests routed", 1354 "# PUT requests routed",
1334 1, 1355 1,
@@ -1345,7 +1366,7 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1345 "Routing PUT for %s terminates after %u hops at %s\n", 1366 "Routing PUT for %s terminates after %u hops at %s\n",
1346 GNUNET_h2s (&bd->key), 1367 GNUNET_h2s (&bd->key),
1347 (unsigned int) hop_count, 1368 (unsigned int) hop_count,
1348 GNUNET_i2s (&my_identity)); 1369 GNUNET_i2s (&GDS_my_identity));
1349 return GNUNET_NO; 1370 return GNUNET_NO;
1350 } 1371 }
1351 msize = bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement) 1372 msize = bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement)
@@ -1367,33 +1388,23 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1367 for (unsigned int i = 0; i < target_count; i++) 1388 for (unsigned int i = 0; i < target_count; i++)
1368 { 1389 {
1369 struct PeerInfo *target = targets[i]; 1390 struct PeerInfo *target = targets[i];
1370 struct GNUNET_MQ_Envelope *env;
1371 struct PeerPutMessage *ppm; 1391 struct PeerPutMessage *ppm;
1392 char buf[sizeof (*ppm) + msize] GNUNET_ALIGN;
1372 struct GNUNET_DHT_PathElement *pp; 1393 struct GNUNET_DHT_PathElement *pp;
1373 1394
1374 if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
1375 {
1376 /* skip */
1377 GNUNET_STATISTICS_update (GDS_stats,
1378 "# P2P messages dropped due to full queue",
1379 1,
1380 GNUNET_NO);
1381 skip_count++;
1382 continue;
1383 }
1384 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1395 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1385 "Routing PUT for %s after %u hops to %s\n", 1396 "Routing PUT for %s after %u hops to %s\n",
1386 GNUNET_h2s (&bd->key), 1397 GNUNET_h2s (&bd->key),
1387 (unsigned int) hop_count, 1398 (unsigned int) hop_count,
1388 GNUNET_i2s (target->id)); 1399 GNUNET_i2s (&target->id));
1389 env = GNUNET_MQ_msg_extra (ppm, 1400 ppm = (struct PeerPutMessage *) buf;
1390 msize, 1401 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
1391 GNUNET_MESSAGE_TYPE_DHT_P2P_PUT); 1402 ppm->header.size = htons (sizeof (buf));
1392 ppm->options = htonl (options);
1393 ppm->type = htonl (bd->type); 1403 ppm->type = htonl (bd->type);
1394 ppm->hop_count = htonl (hop_count + 1); 1404 ppm->options = htons (options);
1395 ppm->desired_replication_level = htonl (desired_replication_level); 1405 ppm->hop_count = htons (hop_count + 1);
1396 ppm->put_path_length = htonl (put_path_length); 1406 ppm->desired_replication_level = htons (desired_replication_level);
1407 ppm->put_path_length = htons (put_path_length);
1397 ppm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time); 1408 ppm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1398 GNUNET_break (GNUNET_YES == 1409 GNUNET_break (GNUNET_YES ==
1399 GNUNET_CONTAINER_bloomfilter_test (bf, 1410 GNUNET_CONTAINER_bloomfilter_test (bf,
@@ -1412,20 +1423,23 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1412 { 1423 {
1413 /* Note that the signature in 'put_path' was not initialized before, 1424 /* Note that the signature in 'put_path' was not initialized before,
1414 so this is crucial to avoid sending garbage. */ 1425 so this is crucial to avoid sending garbage. */
1415 sign_path (&bd->key, 1426 sign_path (bd->data,
1416 bd->data,
1417 bd->data_size, 1427 bd->data_size,
1418 bd->expiration_time, 1428 bd->expiration_time,
1419 &pp[put_path_length - 1].pred, 1429 &pp[put_path_length - 1].pred,
1420 target->id, 1430 &target->id,
1421 &pp[put_path_length - 1].sig); 1431 &pp[put_path_length - 1].sig);
1432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1433 "Signing PUT PATH %u => %s\n",
1434 put_path_length,
1435 GNUNET_B2S (&pp[put_path_length - 1].sig));
1422 } 1436 }
1423 1437
1424 GNUNET_memcpy (&pp[put_path_length], 1438 GNUNET_memcpy (&pp[put_path_length],
1425 bd->data, 1439 bd->data,
1426 bd->data_size); 1440 bd->data_size);
1427 GNUNET_MQ_send (target->mq, 1441 do_send (target,
1428 env); 1442 &ppm->header);
1429 } 1443 }
1430 GNUNET_free (targets); 1444 GNUNET_free (targets);
1431 GNUNET_STATISTICS_update (GDS_stats, 1445 GNUNET_STATISTICS_update (GDS_stats,
@@ -1439,8 +1453,8 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1439enum GNUNET_GenericReturnValue 1453enum GNUNET_GenericReturnValue
1440GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type, 1454GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1441 enum GNUNET_DHT_RouteOption options, 1455 enum GNUNET_DHT_RouteOption options,
1442 uint32_t desired_replication_level, 1456 uint16_t desired_replication_level,
1443 uint32_t hop_count, 1457 uint16_t hop_count,
1444 const struct GNUNET_HashCode *key, 1458 const struct GNUNET_HashCode *key,
1445 const void *xquery, 1459 const void *xquery,
1446 size_t xquery_size, 1460 size_t xquery_size,
@@ -1466,18 +1480,21 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1466 desired_replication_level, 1480 desired_replication_level,
1467 &targets); 1481 &targets);
1468 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1469 "Adding myself (%s) to GET bloomfilter for %s\n", 1483 "Adding myself (%s) to GET bloomfilter for %s with RO(%s/%s)\n",
1470 GNUNET_i2s (&my_identity), 1484 GNUNET_i2s (&GDS_my_identity),
1471 GNUNET_h2s (key)); 1485 GNUNET_h2s (key),
1486 (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
1487 (options & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
1488
1472 GNUNET_CONTAINER_bloomfilter_add (peer_bf, 1489 GNUNET_CONTAINER_bloomfilter_add (peer_bf,
1473 &my_identity_hash); 1490 &GDS_my_identity_hash);
1474 if (0 == target_count) 1491 if (0 == target_count)
1475 { 1492 {
1476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1477 "Routing GET for %s terminates after %u hops at %s\n", 1494 "Routing GET for %s terminates after %u hops at %s\n",
1478 GNUNET_h2s (key), 1495 GNUNET_h2s (key),
1479 (unsigned int) hop_count, 1496 (unsigned int) hop_count,
1480 GNUNET_i2s (&my_identity)); 1497 GNUNET_i2s (&GDS_my_identity));
1481 return GNUNET_NO; 1498 return GNUNET_NO;
1482 } 1499 }
1483 if (GNUNET_OK != 1500 if (GNUNET_OK !=
@@ -1504,32 +1521,22 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1504 for (unsigned int i = 0; i < target_count; i++) 1521 for (unsigned int i = 0; i < target_count; i++)
1505 { 1522 {
1506 struct PeerInfo *target = targets[i]; 1523 struct PeerInfo *target = targets[i];
1507 struct GNUNET_MQ_Envelope *env;
1508 struct PeerGetMessage *pgm; 1524 struct PeerGetMessage *pgm;
1525 char buf[sizeof (*pgm) + msize] GNUNET_ALIGN;
1509 char *xq; 1526 char *xq;
1510 1527
1511 if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
1512 {
1513 /* skip */
1514 GNUNET_STATISTICS_update (GDS_stats,
1515 "# P2P messages dropped due to full queue",
1516 1,
1517 GNUNET_NO);
1518 skip_count++;
1519 continue;
1520 }
1521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1522 "Routing GET for %s after %u hops to %s\n", 1529 "Routing GET for %s after %u hops to %s\n",
1523 GNUNET_h2s (key), 1530 GNUNET_h2s (key),
1524 (unsigned int) hop_count, 1531 (unsigned int) hop_count,
1525 GNUNET_i2s (target->id)); 1532 GNUNET_i2s (&target->id));
1526 env = GNUNET_MQ_msg_extra (pgm, 1533 pgm = (struct PeerGetMessage *) buf;
1527 msize, 1534 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
1528 GNUNET_MESSAGE_TYPE_DHT_P2P_GET); 1535 pgm->header.size = htons (sizeof (buf));
1529 pgm->options = htonl (options);
1530 pgm->type = htonl (type); 1536 pgm->type = htonl (type);
1531 pgm->hop_count = htonl (hop_count + 1); 1537 pgm->options = htons (options);
1532 pgm->desired_replication_level = htonl (desired_replication_level); 1538 pgm->hop_count = htons (hop_count + 1);
1539 pgm->desired_replication_level = htons (desired_replication_level);
1533 pgm->xquery_size = htonl (xquery_size); 1540 pgm->xquery_size = htonl (xquery_size);
1534 pgm->bf_mutator = bf_nonce; 1541 pgm->bf_mutator = bf_nonce;
1535 GNUNET_break (GNUNET_YES == 1542 GNUNET_break (GNUNET_YES ==
@@ -1547,8 +1554,8 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1547 GNUNET_memcpy (&xq[xquery_size], 1554 GNUNET_memcpy (&xq[xquery_size],
1548 reply_bf, 1555 reply_bf,
1549 reply_bf_size); 1556 reply_bf_size);
1550 GNUNET_MQ_send (target->mq, 1557 do_send (target,
1551 env); 1558 &pgm->header);
1552 } 1559 }
1553 GNUNET_STATISTICS_update (GDS_stats, 1560 GNUNET_STATISTICS_update (GDS_stats,
1554 "# GET messages queued for transmission", 1561 "# GET messages queued for transmission",
@@ -1568,34 +1575,30 @@ GDS_NEIGHBOURS_lookup_peer (const struct GNUNET_PeerIdentity *target)
1568} 1575}
1569 1576
1570 1577
1571void 1578bool
1572GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi, 1579GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1573 const struct GDS_DATACACHE_BlockData *bd, 1580 const struct GDS_DATACACHE_BlockData *bd,
1574 const struct GNUNET_HashCode *query_hash, 1581 const struct GNUNET_HashCode *query_hash,
1575 unsigned int get_path_length, 1582 unsigned int get_path_length,
1576 const struct GNUNET_DHT_PathElement *get_path) 1583 const struct GNUNET_DHT_PathElement *get_path)
1577{ 1584{
1578 struct GNUNET_MQ_Envelope *env;
1579 struct PeerResultMessage *prm;
1580 struct GNUNET_DHT_PathElement *paths; 1585 struct GNUNET_DHT_PathElement *paths;
1581 size_t msize; 1586 size_t msize;
1582 unsigned int ppl = bd->put_path_length; 1587 unsigned int ppl = bd->put_path_length;
1583 1588
1584#if SANITY_CHECKS 1589#if SANITY_CHECKS > 1
1585 if (0 != 1590 if (0 !=
1586 GNUNET_DHT_verify_path (&bd->key, 1591 GNUNET_DHT_verify_path (bd->data,
1587 bd->data,
1588 bd->data_size, 1592 bd->data_size,
1589 bd->expiration_time, 1593 bd->expiration_time,
1590 bd->put_path, 1594 bd->put_path,
1591 bd->put_path_length, 1595 bd->put_path_length,
1592 get_path, 1596 get_path,
1593 get_path_length, 1597 get_path_length,
1594 &my_identity)) 1598 &GDS_my_identity))
1595 { 1599 {
1596 GNUNET_break_op (0); 1600 GNUNET_break_op (0);
1597 get_path_length = 0; 1601 return false;
1598 ppl = 0;
1599 } 1602 }
1600#endif 1603#endif
1601 msize = bd->data_size + (get_path_length + ppl) 1604 msize = bd->data_size + (get_path_length + ppl)
@@ -1620,84 +1623,99 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1620 (bd->data_size > GNUNET_MAX_MESSAGE_SIZE)) 1623 (bd->data_size > GNUNET_MAX_MESSAGE_SIZE))
1621 { 1624 {
1622 GNUNET_break (0); 1625 GNUNET_break (0);
1623 return; 1626 return false;
1624 }
1625 if (GNUNET_MQ_get_length (pi->mq) >= MAXIMUM_PENDING_PER_PEER)
1626 {
1627 /* skip */
1628 GNUNET_STATISTICS_update (GDS_stats,
1629 "# P2P messages dropped due to full queue",
1630 1,
1631 GNUNET_NO);
1632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1633 "Peer queue full, ignoring reply for key %s\n",
1634 GNUNET_h2s (&bd->key));
1635 return;
1636 } 1627 }
1637
1638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1639 "Forwarding reply for key %s to peer %s\n", 1629 "Forwarding reply for key %s to peer %s\n",
1640 GNUNET_h2s (query_hash), 1630 GNUNET_h2s (query_hash),
1641 GNUNET_i2s (pi->id)); 1631 GNUNET_i2s (&pi->id));
1642 GNUNET_STATISTICS_update (GDS_stats, 1632 GNUNET_STATISTICS_update (GDS_stats,
1643 "# RESULT messages queued for transmission", 1633 "# RESULT messages queued for transmission",
1644 1, 1634 1,
1645 GNUNET_NO); 1635 GNUNET_NO);
1646 env = GNUNET_MQ_msg_extra (prm,
1647 msize,
1648 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
1649 prm->type = htonl (bd->type);
1650 prm->put_path_length = htonl (ppl);
1651 prm->get_path_length = htonl (get_path_length);
1652 prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1653 prm->key = *query_hash;
1654 paths = (struct GNUNET_DHT_PathElement *) &prm[1];
1655 GNUNET_memcpy (paths,
1656 bd->put_path,
1657 ppl * sizeof(struct GNUNET_DHT_PathElement));
1658 GNUNET_memcpy (&paths[ppl],
1659 get_path,
1660 get_path_length * sizeof(struct GNUNET_DHT_PathElement));
1661 /* 0 == get_path_length means path is not being tracked */
1662 if (0 != get_path_length)
1663 { 1636 {
1664 /* Note that the signature in 'get_path' was not initialized before, 1637 struct PeerResultMessage *prm;
1665 so this is crucial to avoid sending garbage. */ 1638 char buf[sizeof (*prm) + msize] GNUNET_ALIGN;
1666 sign_path (&bd->key, 1639
1667 bd->data, 1640 prm = (struct PeerResultMessage *) buf;
1668 bd->data_size, 1641 prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
1669 bd->expiration_time, 1642 prm->header.size = htons (sizeof (buf));
1670 &paths[ppl + get_path_length - 1].pred, 1643 prm->type = htonl (bd->type);
1671 pi->id, 1644 prm->reserved = htonl (0);
1672 &paths[ppl + get_path_length - 1].sig); 1645 prm->put_path_length = htons (ppl);
1673 } 1646 prm->get_path_length = htons (get_path_length);
1674 GNUNET_memcpy (&paths[ppl + get_path_length], 1647 prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1675 bd->data, 1648 prm->key = *query_hash;
1676 bd->data_size); 1649 paths = (struct GNUNET_DHT_PathElement *) &prm[1];
1677 GNUNET_MQ_send (pi->mq, 1650 if (NULL != bd->put_path)
1678 env); 1651 {
1679} 1652 GNUNET_memcpy (paths,
1653 bd->put_path,
1654 ppl * sizeof(struct GNUNET_DHT_PathElement));
1655 }
1656 else
1657 {
1658 GNUNET_assert (0 == ppl);
1659 }
1660 if (NULL != get_path)
1661 {
1662 GNUNET_memcpy (&paths[ppl],
1663 get_path,
1664 get_path_length * sizeof(struct GNUNET_DHT_PathElement));
1665 }
1666 else
1667 {
1668 GNUNET_assert (0 == get_path_length);
1669 }
1670 /* 0 == get_path_length+ppl means path is not being tracked */
1671 if (0 != (get_path_length + ppl))
1672 {
1673 /* Note that the last signature in 'paths' was not initialized before,
1674 so this is crucial to avoid sending garbage. */
1675 sign_path (bd->data,
1676 bd->data_size,
1677 bd->expiration_time,
1678 &paths[ppl + get_path_length - 1].pred,
1679 &pi->id,
1680 &paths[ppl + get_path_length - 1].sig);
1681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1682 "Signing GET PATH %u/%u of %s => %s\n",
1683 ppl,
1684 get_path_length,
1685 GNUNET_h2s (query_hash),
1686 GNUNET_B2S (&paths[ppl + get_path_length - 1].sig));
1687 }
1688 GNUNET_memcpy (&paths[ppl + get_path_length],
1689 bd->data,
1690 bd->data_size);
1680 1691
1692#if SANITY_CHECKS > 1
1693 {
1694 struct GNUNET_DHT_PathElement xpaths[get_path_length + 1];
1681 1695
1682/** 1696 memcpy (xpaths,
1683 * To be called on core init. 1697 &paths[ppl],
1684 * 1698 get_path_length * sizeof (struct GNUNET_DHT_PathElement));
1685 * @param cls service closure 1699 xpaths[get_path_length].pred = GDS_my_identity;
1686 * @param identity the public identity of this peer 1700 if (0 !=
1687 */ 1701 GNUNET_DHT_verify_path (bd->data,
1688static void 1702 bd->data_size,
1689core_init (void *cls, 1703 bd->expiration_time,
1690 const struct GNUNET_PeerIdentity *identity) 1704 paths,
1691{ 1705 ppl,
1692 (void) cls; 1706 xpaths,
1693 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1707 get_path_length + 1,
1694 "CORE called, I am %s\n", 1708 &pi->id))
1695 GNUNET_i2s (identity)); 1709 {
1696 my_identity = *identity; 1710 GNUNET_break (0);
1697 GNUNET_CRYPTO_hash (identity, 1711 return false;
1698 sizeof(struct GNUNET_PeerIdentity), 1712 }
1699 &my_identity_hash); 1713 }
1700 GNUNET_SERVICE_resume (GDS_service); 1714#endif
1715 do_send (pi,
1716 &prm->header);
1717 }
1718 return true;
1701} 1719}
1702 1720
1703 1721
@@ -1713,7 +1731,7 @@ check_dht_p2p_put (void *cls,
1713 const struct PeerPutMessage *put) 1731 const struct PeerPutMessage *put)
1714{ 1732{
1715 uint16_t msize = ntohs (put->header.size); 1733 uint16_t msize = ntohs (put->header.size);
1716 uint32_t putlen = ntohl (put->put_path_length); 1734 uint16_t putlen = ntohs (put->put_path_length);
1717 1735
1718 (void) cls; 1736 (void) cls;
1719 if ( (msize < 1737 if ( (msize <
@@ -1732,34 +1750,37 @@ check_dht_p2p_put (void *cls,
1732/** 1750/**
1733 * Core handler for p2p put requests. 1751 * Core handler for p2p put requests.
1734 * 1752 *
1735 * @param cls closure with the `struct PeerInfo` of the sender 1753 * @param cls closure with the `struct Target` of the sender
1736 * @param message message 1754 * @param message message
1737 */ 1755 */
1738static void 1756static void
1739handle_dht_p2p_put (void *cls, 1757handle_dht_p2p_put (void *cls,
1740 const struct PeerPutMessage *put) 1758 const struct PeerPutMessage *put)
1741{ 1759{
1742 struct PeerInfo *peer = cls; 1760 struct Target *t = cls;
1761 struct PeerInfo *peer = t->pi;
1743 uint16_t msize = ntohs (put->header.size); 1762 uint16_t msize = ntohs (put->header.size);
1744 enum GNUNET_DHT_RouteOption options 1763 enum GNUNET_DHT_RouteOption options
1745 = (enum GNUNET_DHT_RouteOption) ntohl (put->options); 1764 = (enum GNUNET_DHT_RouteOption) ntohs (put->options);
1765 const struct GNUNET_DHT_PathElement *put_path
1766 = (const struct GNUNET_DHT_PathElement *) &put[1];
1767 uint16_t putlen
1768 = ntohs (put->put_path_length);
1746 struct GDS_DATACACHE_BlockData bd = { 1769 struct GDS_DATACACHE_BlockData bd = {
1747 .key = put->key, 1770 .key = put->key,
1748 .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time), 1771 .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time),
1749 .type = ntohl (put->type) 1772 .type = ntohl (put->type),
1773 .data_size = msize - (sizeof(*put)
1774 + putlen * sizeof(struct GNUNET_DHT_PathElement)),
1775 .data = &put_path[putlen]
1750 }; 1776 };
1751 const struct GNUNET_DHT_PathElement *put_path
1752 = (const struct GNUNET_DHT_PathElement *) &put[1];
1753 uint32_t putlen
1754 = ntohl (put->put_path_length);
1755 1777
1756 bd.data_size = msize - (sizeof(*put)
1757 + putlen * sizeof(struct GNUNET_DHT_PathElement));
1758 bd.data = &put_path[putlen];
1759 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1760 "PUT for `%s' from %s\n", 1779 "PUT for `%s' from %s with RO (%s/%s)\n",
1761 GNUNET_h2s (&put->key), 1780 GNUNET_h2s (&put->key),
1762 GNUNET_i2s (peer->id)); 1781 GNUNET_i2s (&peer->id),
1782 (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
1783 (options & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
1763 if (GNUNET_TIME_absolute_is_past (bd.expiration_time)) 1784 if (GNUNET_TIME_absolute_is_past (bd.expiration_time))
1764 { 1785 {
1765 GNUNET_STATISTICS_update (GDS_stats, 1786 GNUNET_STATISTICS_update (GDS_stats,
@@ -1768,6 +1789,17 @@ handle_dht_p2p_put (void *cls,
1768 GNUNET_NO); 1789 GNUNET_NO);
1769 return; 1790 return;
1770 } 1791 }
1792 if (GNUNET_NO ==
1793 GNUNET_BLOCK_check_block (GDS_block_context,
1794 bd.type,
1795 bd.data,
1796 bd.data_size))
1797 {
1798 GNUNET_break_op (0);
1799 return;
1800 }
1801 if (0 == (options & GNUNET_DHT_RO_RECORD_ROUTE))
1802 putlen = 0;
1771 GNUNET_STATISTICS_update (GDS_stats, 1803 GNUNET_STATISTICS_update (GDS_stats,
1772 "# P2P PUT requests received", 1804 "# P2P PUT requests received",
1773 1, 1805 1,
@@ -1796,25 +1828,14 @@ handle_dht_p2p_put (void *cls,
1796 } 1828 }
1797 break; 1829 break;
1798 case GNUNET_NO: 1830 case GNUNET_NO:
1799 GNUNET_break_op (0);
1800 return;
1801 case GNUNET_SYSERR:
1802 /* cannot verify, good luck */ 1831 /* cannot verify, good luck */
1803 break; 1832 break;
1833 case GNUNET_SYSERR:
1834 /* block type not supported, good luck */
1835 break;
1804 } 1836 }
1805 } 1837 }
1806 1838
1807 if (GNUNET_NO ==
1808 GNUNET_BLOCK_check_block (GDS_block_context,
1809 bd.type,
1810 &bd.key,
1811 bd.data,
1812 bd.data_size))
1813 {
1814 GNUNET_break_op (0);
1815 return;
1816 }
1817
1818 { 1839 {
1819 struct GNUNET_CONTAINER_BloomFilter *bf; 1840 struct GNUNET_CONTAINER_BloomFilter *bf;
1820 struct GNUNET_DHT_PathElement pp[putlen + 1]; 1841 struct GNUNET_DHT_PathElement pp[putlen + 1];
@@ -1830,42 +1851,39 @@ handle_dht_p2p_put (void *cls,
1830 bd.put_path_length = putlen + 1; 1851 bd.put_path_length = putlen + 1;
1831 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE)) 1852 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
1832 { 1853 {
1833#if SANITY_CHECKS 1854 unsigned int failure_offset;
1834 for (unsigned int i = 0; i <= putlen; i++) 1855
1835 {
1836 for (unsigned int j = 0; j < i; j++)
1837 {
1838 GNUNET_break (0 !=
1839 GNUNET_memcmp (&pp[i].pred,
1840 &pp[j].pred));
1841 }
1842 GNUNET_break (0 !=
1843 GNUNET_memcmp (&pp[i].pred,
1844 peer->id));
1845 }
1846 if (0 !=
1847 GNUNET_DHT_verify_path (&bd.key,
1848 bd.data,
1849 bd.data_size,
1850 bd.expiration_time,
1851 bd.put_path,
1852 putlen,
1853 NULL, 0, /* get_path */
1854 &my_identity))
1855 {
1856 GNUNET_break_op (0);
1857 putlen = 0;
1858 }
1859#endif
1860 GNUNET_memcpy (pp, 1856 GNUNET_memcpy (pp,
1861 put_path, 1857 put_path,
1862 putlen * sizeof(struct GNUNET_DHT_PathElement)); 1858 putlen * sizeof(struct GNUNET_DHT_PathElement));
1863 pp[putlen].pred = *peer->id; 1859 pp[putlen].pred = peer->id;
1864 /* zero-out signature, not valid until we actually do forward! */ 1860 /* zero-out signature, not valid until we actually do forward! */
1865 memset (&pp[putlen].sig, 1861 memset (&pp[putlen].sig,
1866 0, 1862 0,
1867 sizeof (pp[putlen].sig)); 1863 sizeof (pp[putlen].sig));
1868 putlen++; 1864#if SANITY_CHECKS
1865 /* TODO: might want to eventually implement probabilistic
1866 load-based path verification, but for now it is all or nothing */
1867 failure_offset
1868 = GNUNET_DHT_verify_path (bd.data,
1869 bd.data_size,
1870 bd.expiration_time,
1871 pp,
1872 putlen + 1,
1873 NULL, 0, /* get_path */
1874 &GDS_my_identity);
1875#else
1876 failure_offset = 0;
1877#endif
1878 if (0 != failure_offset)
1879 {
1880 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1881 "Recorded put path invalid at offset %u, truncating\n",
1882 failure_offset);
1883 GNUNET_assert (failure_offset <= putlen);
1884 bd.put_path = &pp[failure_offset];
1885 bd.put_path_length = putlen - failure_offset;
1886 }
1869 } 1887 }
1870 else 1888 else
1871 { 1889 {
@@ -1873,9 +1891,9 @@ handle_dht_p2p_put (void *cls,
1873 } 1891 }
1874 1892
1875 /* give to local clients */ 1893 /* give to local clients */
1876 GDS_CLIENTS_handle_reply (&bd, 1894 GNUNET_break (GDS_CLIENTS_handle_reply (&bd,
1877 &bd.key, 1895 &bd.key,
1878 0, NULL /* get path */); 1896 0, NULL /* get path */));
1879 1897
1880 /* store locally */ 1898 /* store locally */
1881 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) || 1899 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
@@ -1889,8 +1907,8 @@ handle_dht_p2p_put (void *cls,
1889 forwarded 1907 forwarded
1890 = GDS_NEIGHBOURS_handle_put (&bd, 1908 = GDS_NEIGHBOURS_handle_put (&bd,
1891 options, 1909 options,
1892 ntohl (put->desired_replication_level), 1910 ntohs (put->desired_replication_level),
1893 ntohl (put->hop_count), 1911 ntohs (put->hop_count),
1894 bf); 1912 bf);
1895 /* notify monitoring clients */ 1913 /* notify monitoring clients */
1896 GDS_CLIENTS_process_put (options 1914 GDS_CLIENTS_process_put (options
@@ -1898,8 +1916,8 @@ handle_dht_p2p_put (void *cls,
1898 ? GNUNET_DHT_RO_LAST_HOP 1916 ? GNUNET_DHT_RO_LAST_HOP
1899 : 0), 1917 : 0),
1900 &bd, 1918 &bd,
1901 ntohl (put->hop_count), 1919 ntohs (put->hop_count),
1902 ntohl (put->desired_replication_level)); 1920 ntohs (put->desired_replication_level));
1903 } 1921 }
1904 GNUNET_CONTAINER_bloomfilter_free (bf); 1922 GNUNET_CONTAINER_bloomfilter_free (bf);
1905 } 1923 }
@@ -1907,49 +1925,64 @@ handle_dht_p2p_put (void *cls,
1907 1925
1908 1926
1909/** 1927/**
1910 * We have received a FIND PEER request. Send matching 1928 * We have received a request for a HELLO. Sends our
1911 * HELLOs back. 1929 * HELLO back.
1912 * 1930 *
1913 * @param pi sender of the FIND PEER request 1931 * @param pi sender of the request
1914 * @param key peers close to this key are desired 1932 * @param key peers close to this key are desired
1915 * @param bg group for filtering peers 1933 * @param bg group for filtering peers
1916 */ 1934 */
1917static void 1935static void
1918handle_find_peer (struct PeerInfo *pi, 1936handle_find_my_hello (struct PeerInfo *pi,
1919 const struct GNUNET_HashCode *query_hash, 1937 const struct GNUNET_HashCode *query_hash,
1920 struct GNUNET_BLOCK_Group *bg) 1938 struct GNUNET_BLOCK_Group *bg)
1921{ 1939{
1922 int bucket_idx; 1940 size_t block_size = 0;
1923 struct PeerBucket *bucket; 1941
1924 struct PeerInfo *peer; 1942 /* TODO: consider caching our HELLO block for a bit, to
1925 unsigned int choice; 1943 avoid signing too often here... */
1926 struct GDS_DATACACHE_BlockData bd = { 1944 GNUNET_break (GNUNET_NO ==
1927 .type = GNUNET_BLOCK_TYPE_DHT_HELLO 1945 GNUNET_HELLO_builder_to_block (GDS_my_hello,
1928 }; 1946 &GDS_my_private_key,
1929 1947 NULL,
1930 /* first, check about our own HELLO */ 1948 &block_size));
1931 if (NULL != GDS_my_hello)
1932 { 1949 {
1933 bd.expiration_time = GNUNET_TIME_relative_to_absolute ( 1950 char block[block_size];
1934 hello_expiration), 1951
1935 bd.key = my_identity_hash, 1952 if (GNUNET_OK !=
1936 bd.data = GDS_my_hello; 1953 GNUNET_HELLO_builder_to_block (GDS_my_hello,
1937 bd.data_size = GNUNET_HELLO_size ( 1954 &GDS_my_private_key,
1938 (const struct GNUNET_HELLO_Message *) GDS_my_hello); 1955 block,
1939 GNUNET_break (bd.data_size >= sizeof(struct GNUNET_MessageHeader)); 1956 &block_size))
1940 if (GNUNET_BLOCK_REPLY_OK_MORE ==
1941 GNUNET_BLOCK_check_reply (GDS_block_context,
1942 GNUNET_BLOCK_TYPE_DHT_HELLO,
1943 bg,
1944 &my_identity_hash,
1945 NULL, 0,
1946 bd.data,
1947 bd.data_size))
1948 { 1957 {
1949 GDS_NEIGHBOURS_handle_reply (pi, 1958 GNUNET_STATISTICS_update (GDS_stats,
1950 &bd, 1959 "# FIND PEER requests ignored due to lack of HELLO",
1951 query_hash, 1960 1,
1952 0, NULL /* get path */); 1961 GNUNET_NO);
1962 }
1963 else if (GNUNET_BLOCK_REPLY_OK_MORE ==
1964 GNUNET_BLOCK_check_reply (GDS_block_context,
1965 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1966 bg,
1967 &GDS_my_identity_hash,
1968 NULL, 0,
1969 block,
1970 block_size))
1971 {
1972 struct GDS_DATACACHE_BlockData bd = {
1973 .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1974 .expiration_time
1975 = GNUNET_TIME_relative_to_absolute (
1976 GNUNET_HELLO_ADDRESS_EXPIRATION),
1977 .key = GDS_my_identity_hash,
1978 .data = block,
1979 .data_size = block_size
1980 };
1981
1982 GNUNET_break (GDS_NEIGHBOURS_handle_reply (pi,
1983 &bd,
1984 query_hash,
1985 0, NULL /* get path */));
1953 } 1986 }
1954 else 1987 else
1955 { 1988 {
@@ -1959,70 +1992,52 @@ handle_find_peer (struct PeerInfo *pi,
1959 GNUNET_NO); 1992 GNUNET_NO);
1960 } 1993 }
1961 } 1994 }
1962 else 1995}
1963 {
1964 GNUNET_STATISTICS_update (GDS_stats,
1965 "# FIND PEER requests ignored due to lack of HELLO",
1966 1,
1967 GNUNET_NO);
1968 }
1969 1996
1970 /* then, also consider sending a random HELLO from the closest bucket */
1971 /* FIXME: How can this be true? Shouldnt we just do find_bucket() ? */
1972 if (0 ==
1973 GNUNET_memcmp (&my_identity_hash,
1974 query_hash))
1975 bucket_idx = closest_bucket - 1;
1976 else
1977 bucket_idx = GNUNET_MIN ((int) closest_bucket - 1,
1978 find_bucket (query_hash));
1979 if (bucket_idx < 0)
1980 return;
1981 bucket = &k_buckets[bucket_idx];
1982 if (bucket->peers_size == 0)
1983 return;
1984 choice = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1985 bucket->peers_size);
1986 peer = bucket->head;
1987 while (choice > 0)
1988 {
1989 GNUNET_assert (NULL != peer);
1990 peer = peer->next;
1991 choice--;
1992 }
1993 choice = bucket->peers_size;
1994 1997
1995 { 1998/**
1996 const struct GNUNET_HELLO_Message *hello; 1999 * We have received a request for nearby HELLOs. Sends matching
1997 size_t hello_size; 2000 * HELLOs back.
2001 *
2002 * @param pi sender of the request
2003 * @param key peers close to this key are desired
2004 * @param bg group for filtering peers
2005 */
2006static void
2007handle_find_local_hello (struct PeerInfo *pi,
2008 const struct GNUNET_HashCode *query_hash,
2009 struct GNUNET_BLOCK_Group *bg)
2010{
2011 /* Force non-random selection by hop count */
2012 struct PeerInfo *peer;
1998 2013
1999 do 2014 peer = select_peer (query_hash,
2000 { 2015 NULL,
2001 peer = peer->next; 2016 GDS_NSE_get () + 1);
2002 if (0 == choice--) 2017 if ( (NULL != peer->hello) &&
2003 return; /* no non-masked peer available */ 2018 (! GNUNET_TIME_absolute_is_past (peer->hello_expiration)) &&
2004 if (NULL == peer) 2019 (GNUNET_BLOCK_REPLY_OK_MORE ==
2005 peer = bucket->head; 2020 GNUNET_BLOCK_check_reply (
2006 hello = GDS_HELLO_get (peer->id); 2021 GDS_block_context,
2007 } while ( (NULL == hello) || 2022 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
2008 (GNUNET_BLOCK_REPLY_OK_MORE != 2023 bg,
2009 GNUNET_BLOCK_check_reply ( 2024 &peer->phash,
2010 GDS_block_context, 2025 NULL, 0, /* xquery */
2011 GNUNET_BLOCK_TYPE_DHT_HELLO, 2026 peer->hello,
2012 bg, 2027 peer->hello_size)) )
2013 &peer->phash, 2028 {
2014 NULL, 0, /* xquery */ 2029 struct GDS_DATACACHE_BlockData bd = {
2015 hello, 2030 .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
2016 (hello_size = GNUNET_HELLO_size (hello))))); 2031 .expiration_time = peer->hello_expiration,
2017 bd.expiration_time = GNUNET_TIME_relative_to_absolute ( 2032 .key = peer->phash,
2018 GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION); 2033 .data = peer->hello,
2019 bd.key = peer->phash; 2034 .data_size = peer->hello_size
2020 bd.data = hello; 2035 };
2021 bd.data_size = hello_size; 2036
2022 GDS_NEIGHBOURS_handle_reply (pi, 2037 GNUNET_break (GDS_NEIGHBOURS_handle_reply (pi,
2023 &bd, 2038 &bd,
2024 query_hash, 2039 query_hash,
2025 0, NULL /* get path */); 2040 0, NULL /* get path */));
2026 } 2041 }
2027} 2042}
2028 2043
@@ -2039,17 +2054,17 @@ handle_local_result (void *cls,
2039{ 2054{
2040 struct PeerInfo *peer = cls; 2055 struct PeerInfo *peer = cls;
2041 2056
2042 GDS_NEIGHBOURS_handle_reply (peer, 2057 GNUNET_break (GDS_NEIGHBOURS_handle_reply (peer,
2043 bd, 2058 bd,
2044 &bd->key, 2059 &bd->key,
2045 0, NULL /* get path */); 2060 0, NULL /* get path */));
2046} 2061}
2047 2062
2048 2063
2049/** 2064/**
2050 * Check validity of p2p get request. 2065 * Check validity of p2p get request.
2051 * 2066 *
2052 * @param cls closure with the `struct PeerInfo` of the sender 2067 * @param cls closure with the `struct Target` of the sender
2053 * @param get the message 2068 * @param get the message
2054 * @return #GNUNET_OK if the message is well-formed 2069 * @return #GNUNET_OK if the message is well-formed
2055 */ 2070 */
@@ -2073,20 +2088,21 @@ check_dht_p2p_get (void *cls,
2073/** 2088/**
2074 * Core handler for p2p get requests. 2089 * Core handler for p2p get requests.
2075 * 2090 *
2076 * @param cls closure with the `struct PeerInfo` of the sender 2091 * @param cls closure with the `struct Target` of the sender
2077 * @param get the message 2092 * @param get the message
2078 */ 2093 */
2079static void 2094static void
2080handle_dht_p2p_get (void *cls, 2095handle_dht_p2p_get (void *cls,
2081 const struct PeerGetMessage *get) 2096 const struct PeerGetMessage *get)
2082{ 2097{
2083 struct PeerInfo *peer = cls; 2098 struct Target *t = cls;
2099 struct PeerInfo *peer = t->pi;
2084 uint16_t msize = ntohs (get->header.size); 2100 uint16_t msize = ntohs (get->header.size);
2085 uint32_t xquery_size = ntohl (get->xquery_size); 2101 uint32_t xquery_size = ntohl (get->xquery_size);
2086 uint32_t hop_count = ntohl (get->hop_count); 2102 uint32_t hop_count = ntohs (get->hop_count);
2087 size_t reply_bf_size = msize - (sizeof(*get) + xquery_size); 2103 size_t reply_bf_size = msize - (sizeof(*get) + xquery_size);
2088 enum GNUNET_BLOCK_Type type = (enum GNUNET_BLOCK_Type) ntohl (get->type); 2104 enum GNUNET_BLOCK_Type type = (enum GNUNET_BLOCK_Type) ntohl (get->type);
2089 enum GNUNET_DHT_RouteOption options = (enum GNUNET_DHT_RouteOption) ntohl ( 2105 enum GNUNET_DHT_RouteOption options = (enum GNUNET_DHT_RouteOption) ntohs (
2090 get->options); 2106 get->options);
2091 enum GNUNET_BLOCK_ReplyEvaluationResult eval = GNUNET_BLOCK_REPLY_OK_MORE; 2107 enum GNUNET_BLOCK_ReplyEvaluationResult eval = GNUNET_BLOCK_REPLY_OK_MORE;
2092 const void *xquery = (const void *) &get[1]; 2108 const void *xquery = (const void *) &get[1];
@@ -2133,32 +2149,45 @@ handle_dht_p2p_get (void *cls,
2133 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2149 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2134 "GET for %s at %s after %u hops\n", 2150 "GET for %s at %s after %u hops\n",
2135 GNUNET_h2s (&get->key), 2151 GNUNET_h2s (&get->key),
2136 GNUNET_i2s (&my_identity), 2152 GNUNET_i2s (&GDS_my_identity),
2137 (unsigned int) hop_count); 2153 (unsigned int) hop_count);
2138 /* local lookup (this may update the reply_bf) */ 2154 /* local lookup (this may update the bg) */
2139 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) || 2155 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
2140 (GDS_am_closest_peer (&get->key, 2156 (GDS_am_closest_peer (&get->key,
2141 peer_bf)) ) 2157 peer_bf)) )
2142 { 2158 {
2143 if ((0 != (options & GNUNET_DHT_RO_FIND_PEER))) 2159 if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO == type)
2144 { 2160 {
2145 GNUNET_STATISTICS_update (GDS_stats, 2161 GNUNET_STATISTICS_update (GDS_stats,
2146 "# P2P FIND PEER requests processed", 2162 "# P2P HELLO lookup requests processed",
2147 1, 2163 1,
2148 GNUNET_NO); 2164 GNUNET_NO);
2149 handle_find_peer (peer, 2165 handle_find_my_hello (peer,
2150 &get->key, 2166 &get->key,
2151 bg); 2167 bg);
2168 if (0 != (options & GNUNET_DHT_RO_FIND_APPROXIMATE))
2169 handle_find_local_hello (peer,
2170 &get->key,
2171 bg);
2152 } 2172 }
2153 else 2173 else
2154 { 2174 {
2155 eval = GDS_DATACACHE_handle_get (&get->key, 2175 if (0 != (options & GNUNET_DHT_RO_FIND_APPROXIMATE))
2156 type, 2176 eval = GDS_DATACACHE_get_closest (&get->key,
2157 xquery, 2177 type,
2158 xquery_size, 2178 xquery,
2159 bg, 2179 xquery_size,
2160 &handle_local_result, 2180 bg,
2161 peer); 2181 &handle_local_result,
2182 peer);
2183 else
2184 eval = GDS_DATACACHE_handle_get (&get->key,
2185 type,
2186 xquery,
2187 xquery_size,
2188 bg,
2189 &handle_local_result,
2190 peer);
2162 } 2191 }
2163 } 2192 }
2164 else 2193 else
@@ -2169,8 +2198,10 @@ handle_dht_p2p_get (void *cls,
2169 GNUNET_NO); 2198 GNUNET_NO);
2170 } 2199 }
2171 2200
2172 /* remember request for routing replies */ 2201 /* remember request for routing replies
2173 GDS_ROUTING_add (peer->id, 2202 TODO: why should we do this if GNUNET_BLOCK_REPLY_OK_LAST == eval?
2203 */
2204 GDS_ROUTING_add (&peer->id,
2174 type, 2205 type,
2175 bg, /* bg now owned by routing, but valid at least until end of this function! */ 2206 bg, /* bg now owned by routing, but valid at least until end of this function! */
2176 options, 2207 options,
@@ -2181,7 +2212,7 @@ handle_dht_p2p_get (void *cls,
2181 /* P2P forwarding */ 2212 /* P2P forwarding */
2182 { 2213 {
2183 bool forwarded = false; 2214 bool forwarded = false;
2184 uint32_t desired_replication_level = ntohl ( 2215 uint16_t desired_replication_level = ntohs (
2185 get->desired_replication_level); 2216 get->desired_replication_level);
2186 2217
2187 if (eval != GNUNET_BLOCK_REPLY_OK_LAST) 2218 if (eval != GNUNET_BLOCK_REPLY_OK_LAST)
@@ -2220,18 +2251,25 @@ handle_dht_p2p_get (void *cls,
2220 * @param query_hash hash of the original query, might not match key in @a bd 2251 * @param query_hash hash of the original query, might not match key in @a bd
2221 * @param get_path_length number of entries in @a get_path 2252 * @param get_path_length number of entries in @a get_path
2222 * @param get_path path the reply has taken 2253 * @param get_path path the reply has taken
2254 * @return true on success
2223 */ 2255 */
2224static void 2256static bool
2225process_reply_with_path (const struct GDS_DATACACHE_BlockData *bd, 2257process_reply_with_path (const struct GDS_DATACACHE_BlockData *bd,
2226 const struct GNUNET_HashCode *query_hash, 2258 const struct GNUNET_HashCode *query_hash,
2227 unsigned int get_path_length, 2259 unsigned int get_path_length,
2228 const struct GNUNET_DHT_PathElement *get_path) 2260 const struct GNUNET_DHT_PathElement *get_path)
2229{ 2261{
2230 /* forward to local clients */ 2262 /* forward to local clients */
2231 GDS_CLIENTS_handle_reply (bd, 2263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2232 query_hash, 2264 "Forwarding reply to local clients\n");
2233 get_path_length, 2265 if (! GDS_CLIENTS_handle_reply (bd,
2234 get_path); 2266 query_hash,
2267 get_path_length,
2268 get_path))
2269 {
2270 GNUNET_break (0);
2271 return false;
2272 }
2235 GDS_CLIENTS_process_get_resp (bd, 2273 GDS_CLIENTS_process_get_resp (bd,
2236 get_path, 2274 get_path,
2237 get_path_length); 2275 get_path_length);
@@ -2256,6 +2294,7 @@ process_reply_with_path (const struct GDS_DATACACHE_BlockData *bd,
2256 query_hash, 2294 query_hash,
2257 get_path_length, 2295 get_path_length,
2258 get_path); 2296 get_path);
2297 return true;
2259} 2298}
2260 2299
2261 2300
@@ -2270,8 +2309,8 @@ static enum GNUNET_GenericReturnValue
2270check_dht_p2p_result (void *cls, 2309check_dht_p2p_result (void *cls,
2271 const struct PeerResultMessage *prm) 2310 const struct PeerResultMessage *prm)
2272{ 2311{
2273 uint32_t get_path_length = ntohl (prm->get_path_length); 2312 uint16_t get_path_length = ntohs (prm->get_path_length);
2274 uint32_t put_path_length = ntohl (prm->put_path_length); 2313 uint16_t put_path_length = ntohs (prm->put_path_length);
2275 uint16_t msize = ntohs (prm->header.size); 2314 uint16_t msize = ntohs (prm->header.size);
2276 2315
2277 (void) cls; 2316 (void) cls;
@@ -2301,18 +2340,20 @@ static void
2301handle_dht_p2p_result (void *cls, 2340handle_dht_p2p_result (void *cls,
2302 const struct PeerResultMessage *prm) 2341 const struct PeerResultMessage *prm)
2303{ 2342{
2304 struct PeerInfo *peer = cls; 2343 struct Target *t = cls;
2344 struct PeerInfo *peer = t->pi;
2305 uint16_t msize = ntohs (prm->header.size); 2345 uint16_t msize = ntohs (prm->header.size);
2306 uint32_t get_path_length = ntohl (prm->get_path_length); 2346 uint16_t get_path_length = ntohs (prm->get_path_length);
2307 struct GDS_DATACACHE_BlockData bd = { 2347 struct GDS_DATACACHE_BlockData bd = {
2308 .expiration_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time), 2348 .expiration_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time),
2309 .put_path = (const struct GNUNET_DHT_PathElement *) &prm[1], 2349 .put_path = (const struct GNUNET_DHT_PathElement *) &prm[1],
2310 .put_path_length = ntohl (prm->put_path_length), 2350 .put_path_length = ntohs (prm->put_path_length),
2351 .key = prm->key,
2311 .type = ntohl (prm->type) 2352 .type = ntohl (prm->type)
2312 }; 2353 };
2313 const struct GNUNET_DHT_PathElement *get_path 2354 const struct GNUNET_DHT_PathElement *get_path
2314 = &bd.put_path[bd.put_path_length]; 2355 = &bd.put_path[bd.put_path_length];
2315 2356
2316 /* parse and validate message */ 2357 /* parse and validate message */
2317 if (GNUNET_TIME_absolute_is_past (bd.expiration_time)) 2358 if (GNUNET_TIME_absolute_is_past (bd.expiration_time))
2318 { 2359 {
@@ -2327,6 +2368,15 @@ handle_dht_p2p_result (void *cls,
2327 bd.data_size = msize - (sizeof(struct PeerResultMessage) 2368 bd.data_size = msize - (sizeof(struct PeerResultMessage)
2328 + (get_path_length + bd.put_path_length) 2369 + (get_path_length + bd.put_path_length)
2329 * sizeof(struct GNUNET_DHT_PathElement)); 2370 * sizeof(struct GNUNET_DHT_PathElement));
2371 if (GNUNET_OK !=
2372 GNUNET_BLOCK_check_block (GDS_block_context,
2373 bd.type,
2374 bd.data,
2375 bd.data_size))
2376 {
2377 GNUNET_break_op (0);
2378 return;
2379 }
2330 GNUNET_STATISTICS_update (GDS_stats, 2380 GNUNET_STATISTICS_update (GDS_stats,
2331 "# P2P RESULTS received", 2381 "# P2P RESULTS received",
2332 1, 2382 1,
@@ -2337,7 +2387,6 @@ handle_dht_p2p_result (void *cls,
2337 GNUNET_NO); 2387 GNUNET_NO);
2338 { 2388 {
2339 enum GNUNET_GenericReturnValue ret; 2389 enum GNUNET_GenericReturnValue ret;
2340 const struct GNUNET_HashCode *pquery;
2341 2390
2342 ret = GNUNET_BLOCK_get_key (GDS_block_context, 2391 ret = GNUNET_BLOCK_get_key (GDS_block_context,
2343 bd.type, 2392 bd.type,
@@ -2345,102 +2394,274 @@ handle_dht_p2p_result (void *cls,
2345 bd.data_size, 2394 bd.data_size,
2346 &bd.key); 2395 &bd.key);
2347 if (GNUNET_NO == ret) 2396 if (GNUNET_NO == ret)
2348 { 2397 bd.key = prm->key;
2349 GNUNET_break_op (0);
2350 return;
2351 }
2352 pquery = (GNUNET_OK == ret) ? &bd.key : &prm->key;
2353 if (GNUNET_OK !=
2354 GNUNET_BLOCK_check_block (GDS_block_context,
2355 bd.type,
2356 pquery,
2357 bd.data,
2358 bd.data_size))
2359 {
2360 GNUNET_break_op (0);
2361 return;
2362 }
2363 } 2398 }
2364 2399
2365 /* if we got a HELLO, consider it for our own routing table */ 2400 /* if we got a HELLO, consider it for our own routing table */
2366 if (GNUNET_BLOCK_TYPE_DHT_HELLO == bd.type) 2401 hello_check (&bd);
2367 {
2368 const struct GNUNET_MessageHeader *h = bd.data;
2369 struct GNUNET_PeerIdentity pid;
2370
2371 /* Should be a HELLO, validate and consider using it! */
2372 if (bd.data_size < sizeof(struct GNUNET_HELLO_Message))
2373 {
2374 GNUNET_break (0);
2375 return;
2376 }
2377 if (bd.data_size != ntohs (h->size))
2378 {
2379 GNUNET_break (0);
2380 return;
2381 }
2382 if (GNUNET_OK !=
2383 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) h,
2384 &pid))
2385 {
2386 GNUNET_break_op (0);
2387 return;
2388 }
2389 if ( (GNUNET_YES != disable_try_connect) &&
2390 (0 != GNUNET_memcmp (&my_identity,
2391 &pid)) )
2392 try_connect (&pid,
2393 h);
2394 }
2395 2402
2396 /* First, check if 'peer' is already on the path, and if 2403 /* Need to append 'peer' to 'get_path' */
2397 so, truncate it instead of expanding. */
2398 for (unsigned int i = 0; i <= get_path_length; i++)
2399 if (0 == GNUNET_memcmp (&get_path[i].pred,
2400 peer->id))
2401 {
2402 process_reply_with_path (&bd,
2403 &prm->key,
2404 i, get_path);
2405 return;
2406 }
2407
2408 /* Need to append 'peer' to 'get_path' (normal case) */
2409 { 2404 {
2410 struct GNUNET_DHT_PathElement xget_path[get_path_length + 1]; 2405 struct GNUNET_DHT_PathElement xget_path[get_path_length + 1];
2406 struct GNUNET_DHT_PathElement *gp = xget_path;
2407 unsigned int failure_offset;
2411 2408
2412 GNUNET_memcpy (xget_path, 2409 GNUNET_memcpy (xget_path,
2413 get_path, 2410 get_path,
2414 get_path_length * sizeof(struct GNUNET_DHT_PathElement)); 2411 get_path_length * sizeof(struct GNUNET_DHT_PathElement));
2415 xget_path[get_path_length].pred = *peer->id; 2412 xget_path[get_path_length].pred = peer->id;
2416 memset (&xget_path[get_path_length].sig, 2413 memset (&xget_path[get_path_length].sig,
2417 0, 2414 0,
2418 sizeof (xget_path[get_path_length].sig)); 2415 sizeof (xget_path[get_path_length].sig));
2419 process_reply_with_path (&bd, 2416#if SANITY_CHECKS
2420 &prm->key, 2417 /* TODO: might want to eventually implement probabilistic
2421 get_path_length + 1, xget_path); 2418 load-based path verification, but for now it is all or nothing */
2419 failure_offset
2420 = GNUNET_DHT_verify_path (bd.data,
2421 bd.data_size,
2422 bd.expiration_time,
2423 bd.put_path,
2424 bd.put_path_length,
2425 xget_path,
2426 get_path_length + 1,
2427 &GDS_my_identity);
2428#else
2429 failure_offset = 0;
2430#endif
2431 if (0 != failure_offset)
2432 {
2433 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2434 "Recorded path invalid at offset %u, truncating\n",
2435 failure_offset);
2436 GNUNET_assert (failure_offset <= bd.put_path_length + get_path_length);
2437 if (failure_offset >= bd.put_path_length)
2438 {
2439 /* failure on get path */
2440 get_path_length -= (failure_offset - bd.put_path_length);
2441 gp = &xget_path[failure_offset - bd.put_path_length];
2442 bd.put_path_length = 0;
2443 }
2444 else
2445 {
2446 /* failure on put path */
2447 bd.put_path = &bd.put_path[failure_offset];
2448 bd.put_path_length -= failure_offset;
2449 }
2450 }
2451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2452 "Extending GET path of length %u with %s\n",
2453 get_path_length,
2454 GNUNET_i2s (&peer->id));
2455 GNUNET_break (process_reply_with_path (&bd,
2456 &prm->key,
2457 get_path_length + 1,
2458 gp));
2422 } 2459 }
2423} 2460}
2424 2461
2425 2462
2426enum GNUNET_GenericReturnValue 2463/**
2427GDS_NEIGHBOURS_init () 2464 * Check validity of a p2p hello message.
2465 *
2466 * @param cls closure
2467 * @param hello message
2468 * @return #GNUNET_YES if the message is well-formed
2469 */
2470static enum GNUNET_GenericReturnValue
2471check_dht_p2p_hello (void *cls,
2472 const struct GNUNET_MessageHeader *hello)
2428{ 2473{
2474 struct Target *t = cls;
2475 struct PeerInfo *peer = t->pi;
2476 enum GNUNET_GenericReturnValue ret;
2477 size_t hellob_size;
2478 void *hellob;
2479 struct GNUNET_TIME_Absolute expiration;
2480
2481 ret = GNUNET_HELLO_dht_msg_to_block (hello,
2482 &peer->id,
2483 &hellob,
2484 &hellob_size,
2485 &expiration);
2486 GNUNET_free (hellob);
2487 return ret;
2488}
2489
2490
2491/**
2492 * Core handler for p2p HELLO messages.
2493 *
2494 * @param cls closure
2495 * @param message message
2496 */
2497static void
2498handle_dht_p2p_hello (void *cls,
2499 const struct GNUNET_MessageHeader *hello)
2500{
2501 struct Target *t = cls;
2502 struct PeerInfo *peer = t->pi;
2503
2504 GNUNET_free (peer->hello);
2505 peer->hello_size = 0;
2506 GNUNET_break (GNUNET_OK ==
2507 GNUNET_HELLO_dht_msg_to_block (hello,
2508 &peer->id,
2509 &peer->hello,
2510 &peer->hello_size,
2511 &peer->hello_expiration));
2512}
2513
2514
2515void
2516GDS_u_receive (void *cls,
2517 void **tctx,
2518 void **sctx,
2519 const void *message,
2520 size_t message_size)
2521{
2522 struct Target *t = *tctx;
2429 struct GNUNET_MQ_MessageHandler core_handlers[] = { 2523 struct GNUNET_MQ_MessageHandler core_handlers[] = {
2430 GNUNET_MQ_hd_var_size (dht_p2p_get, 2524 GNUNET_MQ_hd_var_size (dht_p2p_get,
2431 GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 2525 GNUNET_MESSAGE_TYPE_DHT_P2P_GET,
2432 struct PeerGetMessage, 2526 struct PeerGetMessage,
2433 NULL), 2527 t),
2434 GNUNET_MQ_hd_var_size (dht_p2p_put, 2528 GNUNET_MQ_hd_var_size (dht_p2p_put,
2435 GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 2529 GNUNET_MESSAGE_TYPE_DHT_P2P_PUT,
2436 struct PeerPutMessage, 2530 struct PeerPutMessage,
2437 NULL), 2531 t),
2438 GNUNET_MQ_hd_var_size (dht_p2p_result, 2532 GNUNET_MQ_hd_var_size (dht_p2p_result,
2439 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, 2533 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT,
2440 struct PeerResultMessage, 2534 struct PeerResultMessage,
2441 NULL), 2535 t),
2536 GNUNET_MQ_hd_var_size (dht_p2p_hello,
2537 GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO,
2538 struct GNUNET_MessageHeader,
2539 t),
2442 GNUNET_MQ_handler_end () 2540 GNUNET_MQ_handler_end ()
2443 }; 2541 };
2542 const struct GNUNET_MessageHeader *mh = message;
2543
2544 (void) cls; /* the 'struct GDS_Underlay' */
2545 (void) sctx; /* our receiver address */
2546 if (NULL == t)
2547 {
2548 /* Received message claiming to originate from myself?
2549 Ignore! */
2550 GNUNET_break_op (0);
2551 return;
2552 }
2553 if (message_size < sizeof (*mh))
2554 {
2555 GNUNET_break_op (0);
2556 return;
2557 }
2558 if (message_size != ntohs (mh->size))
2559 {
2560 GNUNET_break_op (0);
2561 return;
2562 }
2563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2564 "Handling message of type %u from peer %s\n",
2565 ntohs (mh->type),
2566 GNUNET_i2s (&t->pi->id));
2567 if (GNUNET_OK !=
2568 GNUNET_MQ_handle_message (core_handlers,
2569 mh))
2570 {
2571 GNUNET_break_op (0);
2572 return;
2573 }
2574}
2575
2576
2577/**
2578 * Callback function used to extract URIs from a builder.
2579 * Called when we should consider connecting to a peer.
2580 *
2581 * @param cls closure pointing to a `struct GNUNET_PeerIdentity *`
2582 * @param uri one of the URIs
2583 */
2584void
2585GDS_try_connect (void *cls,
2586 const char *uri)
2587{
2588 const struct GNUNET_PeerIdentity *pid = cls;
2589 struct GNUNET_HashCode phash;
2590 int peer_bucket;
2591 struct PeerBucket *bucket;
2592
2593 if (0 == GNUNET_memcmp (&GDS_my_identity,
2594 pid))
2595 {
2596 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2597 "Got a HELLO for my own PID, ignoring it\n");
2598 return; /* that's us! */
2599 }
2600 GNUNET_CRYPTO_hash (pid,
2601 sizeof(*pid),
2602 &phash);
2603 peer_bucket = find_bucket (&phash);
2604 GNUNET_assert ( (peer_bucket >= 0) &&
2605 ((unsigned int) peer_bucket < MAX_BUCKETS));
2606 bucket = &k_buckets[peer_bucket];
2607 if (bucket->peers_size >= bucket_size)
2608 return; /* do not care */
2609 for (struct PeerInfo *pi = bucket->head;
2610 NULL != pi;
2611 pi = pi->next)
2612 if (0 ==
2613 GNUNET_memcmp (&pi->id,
2614 pid))
2615 {
2616 /* already connected */
2617 /* TODO: maybe consider 'uri' anyway as an additional
2618 alternative address??? */
2619 return;
2620 }
2621 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2622 "Discovered peer %s at %s suitable for bucket %d (%u/%u), trying to connect\n",
2623 GNUNET_i2s (pid),
2624 uri,
2625 peer_bucket,
2626 bucket->peers_size,
2627 bucket_size);
2628 /* new peer that we like! */
2629 GDS_u_try_connect (pid,
2630 uri);
2631}
2632
2633
2634/**
2635 * Send @a msg to all peers in our buckets.
2636 *
2637 * @param msg message to broadcast
2638 */
2639void
2640GDS_NEIGHBOURS_broadcast (const struct GNUNET_MessageHeader *msg)
2641{
2642 for (unsigned int bc = 0; bc<closest_bucket; bc++)
2643 {
2644 struct PeerBucket *bucket = &k_buckets[bc];
2645 unsigned int count = 0;
2646
2647 for (struct PeerInfo *pos = bucket->head;
2648 NULL != pos;
2649 pos = pos->next)
2650 {
2651 if (count >= bucket_size)
2652 break; /* we only consider first #bucket_size entries per bucket */
2653 count++;
2654 do_send (pos,
2655 msg);
2656 }
2657 }
2658}
2659
2660
2661enum GNUNET_GenericReturnValue
2662GDS_NEIGHBOURS_init ()
2663{
2664
2444 unsigned long long temp_config_num; 2665 unsigned long long temp_config_num;
2445 2666
2446 disable_try_connect 2667 disable_try_connect
@@ -2457,45 +2678,8 @@ GDS_NEIGHBOURS_init ()
2457 = GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg, 2678 = GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg,
2458 "DHT", 2679 "DHT",
2459 "CACHE_RESULTS"); 2680 "CACHE_RESULTS");
2460 {
2461 char *keyfile;
2462
2463 if (GNUNET_OK !=
2464 GNUNET_CONFIGURATION_get_value_filename (GDS_cfg,
2465 "PEER",
2466 "PRIVATE_KEY",
2467 &keyfile))
2468 {
2469 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2470 "Core service is lacking HOSTKEY configuration setting. Exiting.\n");
2471 return GNUNET_SYSERR;
2472 }
2473 if (GNUNET_SYSERR ==
2474 GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
2475 GNUNET_YES,
2476 &my_private_key))
2477 {
2478 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2479 "Failed to setup peer's private key\n");
2480 GNUNET_free (keyfile);
2481 return GNUNET_SYSERR;
2482 }
2483 GNUNET_free (keyfile);
2484 }
2485
2486 ats_ch = GNUNET_ATS_connectivity_init (GDS_cfg);
2487 core_api = GNUNET_CORE_connect (GDS_cfg,
2488 NULL,
2489 &core_init,
2490 &handle_core_connect,
2491 &handle_core_disconnect,
2492 core_handlers);
2493 if (NULL == core_api)
2494 return GNUNET_SYSERR;
2495 all_connected_peers = GNUNET_CONTAINER_multipeermap_create (256, 2681 all_connected_peers = GNUNET_CONTAINER_multipeermap_create (256,
2496 GNUNET_YES); 2682 GNUNET_YES);
2497 all_desired_peers = GNUNET_CONTAINER_multipeermap_create (256,
2498 GNUNET_NO);
2499 return GNUNET_OK; 2683 return GNUNET_OK;
2500} 2684}
2501 2685
@@ -2503,21 +2687,12 @@ GDS_NEIGHBOURS_init ()
2503void 2687void
2504GDS_NEIGHBOURS_done () 2688GDS_NEIGHBOURS_done ()
2505{ 2689{
2506 if (NULL == core_api) 2690 if (NULL == all_connected_peers)
2507 return; 2691 return;
2508 GNUNET_CORE_disconnect (core_api);
2509 core_api = NULL;
2510 GNUNET_assert (0 == 2692 GNUNET_assert (0 ==
2511 GNUNET_CONTAINER_multipeermap_size (all_connected_peers)); 2693 GNUNET_CONTAINER_multipeermap_size (all_connected_peers));
2512 GNUNET_CONTAINER_multipeermap_destroy (all_connected_peers); 2694 GNUNET_CONTAINER_multipeermap_destroy (all_connected_peers);
2513 all_connected_peers = NULL; 2695 all_connected_peers = NULL;
2514 GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
2515 &free_connect_info,
2516 NULL);
2517 GNUNET_CONTAINER_multipeermap_destroy (all_desired_peers);
2518 all_desired_peers = NULL;
2519 GNUNET_ATS_connectivity_done (ats_ch);
2520 ats_ch = NULL;
2521 GNUNET_assert (NULL == find_peer_task); 2696 GNUNET_assert (NULL == find_peer_task);
2522} 2697}
2523 2698
@@ -2525,7 +2700,7 @@ GDS_NEIGHBOURS_done ()
2525struct GNUNET_PeerIdentity * 2700struct GNUNET_PeerIdentity *
2526GDS_NEIGHBOURS_get_id () 2701GDS_NEIGHBOURS_get_id ()
2527{ 2702{
2528 return &my_identity; 2703 return &GDS_my_identity;
2529} 2704}
2530 2705
2531 2706
diff --git a/src/dht/gnunet-service-dht_neighbours.h b/src/dht/gnunet-service-dht_neighbours.h
index 35bbb125d..4f4172f71 100644
--- a/src/dht/gnunet-service-dht_neighbours.h
+++ b/src/dht/gnunet-service-dht_neighbours.h
@@ -30,13 +30,9 @@
30#include "gnunet_util_lib.h" 30#include "gnunet_util_lib.h"
31#include "gnunet_block_lib.h" 31#include "gnunet_block_lib.h"
32#include "gnunet_dht_service.h" 32#include "gnunet_dht_service.h"
33#include "gnunet_dhtu_plugin.h"
33#include "gnunet-service-dht_datacache.h" 34#include "gnunet-service-dht_datacache.h"
34 35
35/**
36 * Hash of the identity of this peer.
37 */
38extern struct GNUNET_HashCode my_identity_hash;
39
40 36
41struct PeerInfo; 37struct PeerInfo;
42 38
@@ -67,8 +63,8 @@ GDS_NEIGHBOURS_lookup_peer (const struct GNUNET_PeerIdentity *target);
67enum GNUNET_GenericReturnValue 63enum GNUNET_GenericReturnValue
68GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd, 64GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
69 enum GNUNET_DHT_RouteOption options, 65 enum GNUNET_DHT_RouteOption options,
70 uint32_t desired_replication_level, 66 uint16_t desired_replication_level,
71 uint32_t hop_count, 67 uint16_t hop_count,
72 struct GNUNET_CONTAINER_BloomFilter *bf); 68 struct GNUNET_CONTAINER_BloomFilter *bf);
73 69
74 70
@@ -92,8 +88,8 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
92enum GNUNET_GenericReturnValue 88enum GNUNET_GenericReturnValue
93GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type, 89GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
94 enum GNUNET_DHT_RouteOption options, 90 enum GNUNET_DHT_RouteOption options,
95 uint32_t desired_replication_level, 91 uint16_t desired_replication_level,
96 uint32_t hop_count, 92 uint16_t hop_count,
97 const struct GNUNET_HashCode *key, 93 const struct GNUNET_HashCode *key,
98 const void *xquery, 94 const void *xquery,
99 size_t xquery_size, 95 size_t xquery_size,
@@ -112,8 +108,9 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
112 * @param query_hash query that was used for the request 108 * @param query_hash query that was used for the request
113 * @param get_path_length number of entries in put_path 109 * @param get_path_length number of entries in put_path
114 * @param get_path peers this reply has traversed so far (if tracked) 110 * @param get_path peers this reply has traversed so far (if tracked)
111 * @return true on success
115 */ 112 */
116void 113bool
117GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi, 114GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
118 const struct GDS_DATACACHE_BlockData *bd, 115 const struct GDS_DATACACHE_BlockData *bd,
119 const struct GNUNET_HashCode *query_hash, 116 const struct GNUNET_HashCode *query_hash,
@@ -137,6 +134,73 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
137 134
138 135
139/** 136/**
137 * Callback function used to extract URIs from a builder.
138 * Called when we should consider connecting to a peer.
139 *
140 * @param cls closure pointing to a `struct GNUNET_PeerIdentity *`
141 * @param uri one of the URIs
142 */
143void
144GDS_try_connect (void *cls,
145 const char *uri);
146
147
148/**
149 * Function to call when we connect to a peer and can henceforth transmit to
150 * that peer.
151 *
152 * @param cls the closure, must be a `struct GDS_Underlay`
153 * @param target handle to the target,
154 * pointer will remain valid until @e disconnect_cb is called
155 * @para pid peer identity,
156 * pointer will remain valid until @e disconnect_cb is called
157 * @param[out] ctx storage space for DHT to use in association with this target
158 */
159void
160GDS_u_connect (void *cls,
161 struct GNUNET_DHTU_Target *target,
162 const struct GNUNET_PeerIdentity *pid,
163 void **ctx);
164
165
166/**
167 * Function to call when we disconnected from a peer and can henceforth
168 * cannot transmit to that peer anymore.
169 *
170 * @param[in] ctx storage space used by the DHT in association with this target
171 */
172void
173GDS_u_disconnect (void *ctx);
174
175
176/**
177 * Function to call when we receive a message.
178 *
179 * @param cls the closure
180 * @param origin where the message originated from
181 * @param[in,out] tctx ctx of target address where we received the message from
182 * @param[in,out] sctx ctx of our own source address at which we received the message
183 * @param message the message we received @param message_size number of
184 * bytes in @a message
185 */
186void
187GDS_u_receive (void *cls,
188 void **tctx,
189 void **sctx,
190 const void *message,
191 size_t message_size);
192
193
194/**
195 * Send @a msg to all peers in our buckets.
196 *
197 * @param msg message to broadcast
198 */
199void
200GDS_NEIGHBOURS_broadcast (const struct GNUNET_MessageHeader *msg);
201
202
203/**
140 * Initialize neighbours subsystem. 204 * Initialize neighbours subsystem.
141 * 205 *
142 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 206 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
diff --git a/src/dht/gnunet-service-dht_nse.c b/src/dht/gnunet-service-dht_nse.c
deleted file mode 100644
index 58f18816a..000000000
--- a/src/dht/gnunet-service-dht_nse.c
+++ /dev/null
@@ -1,121 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 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 */
20
21/**
22 * @file dht/gnunet-service-dht_nse.c
23 * @brief GNUnet DHT integration with NSE
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_nse_service.h"
28#include "gnunet-service-dht.h"
29#include "gnunet-service-dht_nse.h"
30
31/**
32 * log of the current network size estimate, used as the point where
33 * we switch between random and deterministic routing. Default
34 * value of 4.0 is used if NSE module is not available (i.e. not
35 * configured).
36 */
37static double log_of_network_size_estimate = 4.0;
38
39/**
40 * Network size estimation handle.
41 */
42static struct GNUNET_NSE_Handle *nse;
43
44
45/**
46 * Callback that is called when network size estimate is updated.
47 *
48 * @param cls closure
49 * @param timestamp time when the estimate was received from the server (or created by the server)
50 * @param logestimate the log(Base 2) value of the current network size estimate
51 * @param std_dev standard deviation for the estimate
52 *
53 */
54static void
55update_network_size_estimate (void *cls,
56 struct GNUNET_TIME_Absolute timestamp,
57 double logestimate,
58 double std_dev)
59{
60 GNUNET_STATISTICS_update (GDS_stats,
61 "# Network size estimates received",
62 1, GNUNET_NO);
63 /* do not allow estimates < 0.5 */
64 log_of_network_size_estimate = GNUNET_MAX (0.5, logestimate);
65}
66
67
68/**
69 * Return the log of the current network size estimate.
70 *
71 * @return log of NSE
72 */
73double
74GDS_NSE_get ()
75{
76 return log_of_network_size_estimate;
77}
78
79
80/**
81 * Initialize NSE subsystem.
82 */
83void
84GDS_NSE_init ()
85{
86 unsigned long long hops;
87
88 if ( (GNUNET_YES ==
89 GNUNET_CONFIGURATION_have_value (GDS_cfg,
90 "dht",
91 "FORCE_NSE")) &&
92 (GNUNET_OK ==
93 GNUNET_CONFIGURATION_get_value_number (GDS_cfg,
94 "dht",
95 "FORCE_NSE",
96 &hops)) )
97 {
98 log_of_network_size_estimate = (double) hops;
99 return;
100 }
101 nse = GNUNET_NSE_connect (GDS_cfg,
102 &update_network_size_estimate,
103 NULL);
104}
105
106
107/**
108 * Shutdown NSE subsystem.
109 */
110void
111GDS_NSE_done ()
112{
113 if (NULL != nse)
114 {
115 GNUNET_NSE_disconnect (nse);
116 nse = NULL;
117 }
118}
119
120
121/* end of gnunet-service-dht_nse.c */
diff --git a/src/dht/gnunet-service-dht_nse.h b/src/dht/gnunet-service-dht_nse.h
deleted file mode 100644
index e99389e74..000000000
--- a/src/dht/gnunet-service-dht_nse.h
+++ /dev/null
@@ -1,52 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 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 */
20
21/**
22 * @file dht/gnunet-service-dht_nse.h
23 * @brief GNUnet DHT integration with NSE
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_DHT_NSE_H
27#define GNUNET_SERVICE_DHT_NSE_H
28
29
30/**
31 * Return the log of the current network size estimate.
32 *
33 * @return log of NSE
34 */
35double
36GDS_NSE_get (void);
37
38
39/**
40 * Initialize NSE subsystem.
41 */
42void
43GDS_NSE_init (void);
44
45
46/**
47 * Shutdown NSE subsystem.
48 */
49void
50GDS_NSE_done (void);
51
52#endif
diff --git a/src/dht/gnunet-service-dht_routing.c b/src/dht/gnunet-service-dht_routing.c
index e7b5c3571..6deb5fa16 100644
--- a/src/dht/gnunet-service-dht_routing.c
+++ b/src/dht/gnunet-service-dht_routing.c
@@ -27,6 +27,7 @@
27#include "gnunet-service-dht_neighbours.h" 27#include "gnunet-service-dht_neighbours.h"
28#include "gnunet-service-dht_routing.h" 28#include "gnunet-service-dht_routing.h"
29#include "gnunet-service-dht.h" 29#include "gnunet-service-dht.h"
30#include "gnunet_block_group_lib.h"
30 31
31 32
32/** 33/**
@@ -151,7 +152,7 @@ process (void *cls,
151 bdx.put_path_length = 0; 152 bdx.put_path_length = 0;
152 bdx.put_path = NULL; 153 bdx.put_path = NULL;
153 } 154 }
154 if ( (0 == (rr->options & GNUNET_DHT_RO_FIND_PEER)) && 155 if ( (0 == (rr->options & GNUNET_DHT_RO_FIND_APPROXIMATE)) &&
155 (0 != GNUNET_memcmp (query_hash, 156 (0 != GNUNET_memcmp (query_hash,
156 &bdx.key)) ) 157 &bdx.key)) )
157 { 158 {
@@ -174,6 +175,22 @@ process (void *cls,
174 GNUNET_h2s (&bdx.key), 175 GNUNET_h2s (&bdx.key),
175 bdx.type, 176 bdx.type,
176 eval); 177 eval);
178 if (GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED == eval)
179 {
180 /* If we do not know the block type, we still filter
181 exact duplicates by the block content */
182 struct GNUNET_HashCode chash;
183
184 GNUNET_CRYPTO_hash (bdx.data,
185 bdx.data_size,
186 &chash);
187 if (GNUNET_YES ==
188 GNUNET_BLOCK_GROUP_bf_test_and_set (rr->bg,
189 &chash))
190 eval = GNUNET_BLOCK_REPLY_OK_DUPLICATE;
191 else
192 eval = GNUNET_BLOCK_REPLY_OK_MORE;
193 }
177 switch (eval) 194 switch (eval)
178 { 195 {
179 case GNUNET_BLOCK_REPLY_OK_MORE: 196 case GNUNET_BLOCK_REPLY_OK_MORE:
@@ -195,10 +212,11 @@ process (void *cls,
195 GNUNET_h2s (query_hash)); 212 GNUNET_h2s (query_hash));
196 return GNUNET_OK; 213 return GNUNET_OK;
197 } 214 }
198 GDS_NEIGHBOURS_handle_reply (pi, 215 GNUNET_break (GDS_NEIGHBOURS_handle_reply (pi,
199 &bdx, 216 &bdx,
200 query_hash, 217 query_hash,
201 get_path_length, pc->get_path); 218 get_path_length,
219 pc->get_path));
202 } 220 }
203 break; 221 break;
204 case GNUNET_BLOCK_REPLY_OK_DUPLICATE: 222 case GNUNET_BLOCK_REPLY_OK_DUPLICATE:
@@ -207,13 +225,6 @@ process (void *cls,
207 1, 225 1,
208 GNUNET_NO); 226 GNUNET_NO);
209 return GNUNET_OK; 227 return GNUNET_OK;
210 case GNUNET_BLOCK_REPLY_INVALID:
211 GNUNET_break (0);
212 GNUNET_STATISTICS_update (GDS_stats,
213 "# Invalid REPLIES matched against routing table",
214 1,
215 GNUNET_NO);
216 return GNUNET_OK;
217 case GNUNET_BLOCK_REPLY_IRRELEVANT: 228 case GNUNET_BLOCK_REPLY_IRRELEVANT:
218 GNUNET_STATISTICS_update (GDS_stats, 229 GNUNET_STATISTICS_update (GDS_stats,
219 "# Irrelevant REPLIES matched against routing table", 230 "# Irrelevant REPLIES matched against routing table",
@@ -325,6 +336,7 @@ try_combine_recent (void *cls,
325 * 336 *
326 * @param sender peer that originated the request 337 * @param sender peer that originated the request
327 * @param type type of the block 338 * @param type type of the block
339 * @param[in] bg block group for filtering duplicate replies
328 * @param options options for processing 340 * @param options options for processing
329 * @param key key for the content 341 * @param key key for the content
330 * @param xquery extended query 342 * @param xquery extended query
diff --git a/src/dht/plugin_block_dht.c b/src/dht/plugin_block_dht.c
index 7c6fb9ed6..3dd3dd792 100644
--- a/src/dht/plugin_block_dht.c
+++ b/src/dht/plugin_block_dht.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2010, 2017 GNUnet e.V. 3 Copyright (C) 2010, 2017, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -28,6 +28,7 @@
28#include "platform.h" 28#include "platform.h"
29#include "gnunet_constants.h" 29#include "gnunet_constants.h"
30#include "gnunet_hello_lib.h" 30#include "gnunet_hello_lib.h"
31#include "gnunet_hello_uri_lib.h"
31#include "gnunet_block_plugin.h" 32#include "gnunet_block_plugin.h"
32#include "gnunet_block_group_lib.h" 33#include "gnunet_block_group_lib.h"
33 34
@@ -89,80 +90,9 @@ block_plugin_dht_create_group (void *cls,
89 90
90 91
91/** 92/**
92 * Function called to validate a reply or a request. For
93 * request evaluation, simply pass "NULL" for the @a reply_block.
94 *
95 * @param cls closure
96 * @param ctx context
97 * @param type block type
98 * @param group block group to check against
99 * @param eo control flags
100 * @param query original query (hash)
101 * @param xquery extended query data (can be NULL, depending on type)
102 * @param xquery_size number of bytes in @a xquery
103 * @param reply_block response to validate
104 * @param reply_block_size number of bytes in @a reply_block
105 * @return characterization of result
106 */
107static enum GNUNET_BLOCK_EvaluationResult
108block_plugin_dht_evaluate (void *cls,
109 struct GNUNET_BLOCK_Context *ctx,
110 enum GNUNET_BLOCK_Type type,
111 struct GNUNET_BLOCK_Group *group,
112 enum GNUNET_BLOCK_EvaluationOptions eo,
113 const struct GNUNET_HashCode *query,
114 const void *xquery,
115 size_t xquery_size,
116 const void *reply_block,
117 size_t reply_block_size)
118{
119 const struct GNUNET_HELLO_Message *hello;
120 struct GNUNET_PeerIdentity pid;
121 const struct GNUNET_MessageHeader *msg;
122 struct GNUNET_HashCode phash;
123
124 if (type != GNUNET_BLOCK_TYPE_DHT_HELLO)
125 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
126 if (0 != xquery_size)
127 {
128 GNUNET_break_op (0);
129 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
130 }
131 if (NULL == reply_block)
132 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
133 if (reply_block_size < sizeof(struct GNUNET_MessageHeader))
134 {
135 GNUNET_break_op (0);
136 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
137 }
138 msg = reply_block;
139 if (reply_block_size != ntohs (msg->size))
140 {
141 GNUNET_break_op (0);
142 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
143 }
144 hello = reply_block;
145 if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
146 {
147 GNUNET_break_op (0);
148 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
149 }
150 GNUNET_CRYPTO_hash (&pid,
151 sizeof(pid),
152 &phash);
153 if (GNUNET_YES ==
154 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
155 &phash))
156 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
157 return GNUNET_BLOCK_EVALUATION_OK_MORE;
158}
159
160
161/**
162 * Function called to validate a query. 93 * Function called to validate a query.
163 * 94 *
164 * @param cls closure 95 * @param cls closure
165 * @param ctx block context
166 * @param type block type 96 * @param type block type
167 * @param query original query (hash) 97 * @param query original query (hash)
168 * @param xquery extrended query data (can be NULL, depending on type) 98 * @param xquery extrended query data (can be NULL, depending on type)
@@ -171,19 +101,31 @@ block_plugin_dht_evaluate (void *cls,
171 */ 101 */
172static enum GNUNET_GenericReturnValue 102static enum GNUNET_GenericReturnValue
173block_plugin_dht_check_query (void *cls, 103block_plugin_dht_check_query (void *cls,
174 enum GNUNET_BLOCK_Type type, 104 enum GNUNET_BLOCK_Type type,
175 const struct GNUNET_HashCode *query, 105 const struct GNUNET_HashCode *query,
176 const void *xquery, 106 const void *xquery,
177 size_t xquery_size) 107 size_t xquery_size)
178{ 108{
179 if (type != GNUNET_BLOCK_TYPE_DHT_HELLO) 109 switch (type)
180 return GNUNET_SYSERR;
181 if (0 != xquery_size)
182 { 110 {
183 GNUNET_break_op (0); 111 case GNUNET_BLOCK_TYPE_DHT_HELLO:
184 return GNUNET_NO; 112 if (0 != xquery_size)
113 {
114 GNUNET_break_op (0);
115 return GNUNET_NO;
116 }
117 return GNUNET_OK;
118 case GNUNET_BLOCK_TYPE_DHT_URL_HELLO:
119 if (0 != xquery_size)
120 {
121 GNUNET_break_op (0);
122 return GNUNET_NO;
123 }
124 return GNUNET_OK;
125 default:
126 GNUNET_break (0);
127 return GNUNET_SYSERR;
185 } 128 }
186 return GNUNET_OK;
187} 129}
188 130
189 131
@@ -192,44 +134,71 @@ block_plugin_dht_check_query (void *cls,
192 * 134 *
193 * @param cls closure 135 * @param cls closure
194 * @param type block type 136 * @param type block type
195 * @param query key for the block (hash), must match exactly
196 * @param block block data to validate 137 * @param block block data to validate
197 * @param block_size number of bytes in @a block 138 * @param block_size number of bytes in @a block
198 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 139 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
199 */ 140 */
200static enum GNUNET_GenericReturnValue 141static enum GNUNET_GenericReturnValue
201block_plugin_dht_check_block (void *cls, 142block_plugin_dht_check_block (void *cls,
202 enum GNUNET_BLOCK_Type type, 143 enum GNUNET_BLOCK_Type type,
203 const struct GNUNET_HashCode *query, 144 const void *block,
204 const void *block, 145 size_t block_size)
205 size_t block_size)
206{ 146{
207 const struct GNUNET_HELLO_Message *hello; 147 switch (type)
208 struct GNUNET_PeerIdentity pid;
209 const struct GNUNET_MessageHeader *msg;
210
211 if (type != GNUNET_BLOCK_TYPE_DHT_HELLO)
212 return GNUNET_SYSERR;
213 if (block_size < sizeof(struct GNUNET_MessageHeader))
214 {
215 GNUNET_break_op (0);
216 return GNUNET_NO;
217 }
218 msg = block;
219 if (block_size != ntohs (msg->size))
220 {
221 GNUNET_break_op (0);
222 return GNUNET_NO;
223 }
224 hello = block;
225 if (GNUNET_OK !=
226 GNUNET_HELLO_get_id (hello,
227 &pid))
228 { 148 {
229 GNUNET_break_op (0); 149 case GNUNET_BLOCK_TYPE_DHT_HELLO:
230 return GNUNET_NO; 150 {
151 const struct GNUNET_HELLO_Message *hello;
152 struct GNUNET_PeerIdentity pid;
153 const struct GNUNET_MessageHeader *msg;
154
155 if (block_size < sizeof(struct GNUNET_MessageHeader))
156 {
157 GNUNET_break_op (0);
158 return GNUNET_NO;
159 }
160 msg = block;
161 if (block_size != ntohs (msg->size))
162 {
163 GNUNET_break_op (0);
164 return GNUNET_NO;
165 }
166 hello = block;
167 if (GNUNET_OK !=
168 GNUNET_HELLO_get_id (hello,
169 &pid))
170 {
171 GNUNET_break_op (0);
172 return GNUNET_NO;
173 }
174 return GNUNET_OK;
175 }
176 case GNUNET_BLOCK_TYPE_DHT_URL_HELLO:
177 {
178 struct GNUNET_HELLO_Builder *b;
179 struct GNUNET_PeerIdentity pid;
180 struct GNUNET_HashCode h_pid;
181
182 b = GNUNET_HELLO_builder_from_block (block,
183 block_size);
184 if (NULL == b)
185 {
186 GNUNET_break (0);
187 return GNUNET_NO;
188 }
189 GNUNET_HELLO_builder_iterate (b,
190 &pid,
191 NULL, NULL);
192 GNUNET_CRYPTO_hash (&pid,
193 sizeof (pid),
194 &h_pid);
195 GNUNET_HELLO_builder_free (b);
196 return GNUNET_OK;
197 }
198 default:
199 GNUNET_break (0);
200 return GNUNET_SYSERR;
231 } 201 }
232 return GNUNET_OK;
233} 202}
234 203
235 204
@@ -251,49 +220,63 @@ block_plugin_dht_check_block (void *cls,
251 */ 220 */
252static enum GNUNET_BLOCK_ReplyEvaluationResult 221static enum GNUNET_BLOCK_ReplyEvaluationResult
253block_plugin_dht_check_reply ( 222block_plugin_dht_check_reply (
254 void *cls, 223 void *cls,
255 enum GNUNET_BLOCK_Type type, 224 enum GNUNET_BLOCK_Type type,
256 struct GNUNET_BLOCK_Group *group, 225 struct GNUNET_BLOCK_Group *group,
257 const struct GNUNET_HashCode *query, 226 const struct GNUNET_HashCode *query,
258 const void *xquery, 227 const void *xquery,
259 size_t xquery_size, 228 size_t xquery_size,
260 const void *reply_block, 229 const void *reply_block,
261 size_t reply_block_size) 230 size_t reply_block_size)
262{ 231{
263 const struct GNUNET_HELLO_Message *hello; 232 switch (type)
264 struct GNUNET_PeerIdentity pid;
265 const struct GNUNET_MessageHeader *msg;
266 struct GNUNET_HashCode phash;
267
268 if (type != GNUNET_BLOCK_TYPE_DHT_HELLO)
269 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
270 if (reply_block_size < sizeof(struct GNUNET_MessageHeader))
271 {
272 GNUNET_break_op (0);
273 return GNUNET_BLOCK_REPLY_INVALID;
274 }
275 msg = reply_block;
276 if (reply_block_size != ntohs (msg->size))
277 {
278 GNUNET_break_op (0);
279 return GNUNET_BLOCK_REPLY_INVALID;
280 }
281 hello = reply_block;
282 if (GNUNET_OK !=
283 GNUNET_HELLO_get_id (hello,
284 &pid))
285 { 233 {
286 GNUNET_break_op (0); 234 case GNUNET_BLOCK_TYPE_DHT_HELLO:
287 return GNUNET_BLOCK_REPLY_INVALID; 235 {
236 const struct GNUNET_MessageHeader *msg = reply_block;
237 const struct GNUNET_HELLO_Message *hello = reply_block;
238 struct GNUNET_PeerIdentity pid;
239 struct GNUNET_HashCode phash;
240
241 GNUNET_assert (reply_block_size >= sizeof(struct GNUNET_MessageHeader));
242 GNUNET_assert (reply_block_size == ntohs (msg->size));
243 GNUNET_assert (GNUNET_OK ==
244 GNUNET_HELLO_get_id (hello,
245 &pid));
246 GNUNET_CRYPTO_hash (&pid,
247 sizeof(pid),
248 &phash);
249 if (GNUNET_YES ==
250 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
251 &phash))
252 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
253 return GNUNET_BLOCK_REPLY_OK_MORE;
254 }
255 case GNUNET_BLOCK_TYPE_DHT_URL_HELLO:
256 {
257 struct GNUNET_HELLO_Builder *b;
258 struct GNUNET_PeerIdentity pid;
259 struct GNUNET_HashCode h_pid;
260
261 b = GNUNET_HELLO_builder_from_block (reply_block,
262 reply_block_size);
263 GNUNET_assert (NULL != b);
264 GNUNET_HELLO_builder_iterate (b,
265 &pid,
266 NULL, NULL);
267 GNUNET_CRYPTO_hash (&pid,
268 sizeof (pid),
269 &h_pid);
270 GNUNET_HELLO_builder_free (b);
271 if (GNUNET_YES ==
272 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
273 &h_pid))
274 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
275 return GNUNET_BLOCK_REPLY_OK_MORE;
276 }
277 default:
278 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
288 } 279 }
289 GNUNET_CRYPTO_hash (&pid,
290 sizeof(pid),
291 &phash);
292 if (GNUNET_YES ==
293 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
294 &phash))
295 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
296 return GNUNET_BLOCK_REPLY_OK_MORE;
297} 280}
298 281
299 282
@@ -315,41 +298,76 @@ block_plugin_dht_get_key (void *cls,
315 size_t block_size, 298 size_t block_size,
316 struct GNUNET_HashCode *key) 299 struct GNUNET_HashCode *key)
317{ 300{
318 const struct GNUNET_MessageHeader *msg; 301 switch (type)
319 const struct GNUNET_HELLO_Message *hello;
320 struct GNUNET_PeerIdentity *pid;
321
322 if (type != GNUNET_BLOCK_TYPE_DHT_HELLO)
323 return GNUNET_SYSERR;
324 if (block_size < sizeof(struct GNUNET_MessageHeader))
325 { 302 {
326 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, 303 case GNUNET_BLOCK_TYPE_DHT_HELLO:
327 "block-dht", 304 {
328 _ ("Block not of type %u\n"), 305 const struct GNUNET_MessageHeader *msg;
329 GNUNET_BLOCK_TYPE_DHT_HELLO); 306 const struct GNUNET_HELLO_Message *hello;
330 return GNUNET_NO; 307 struct GNUNET_PeerIdentity *pid;
331 } 308
332 msg = block; 309 if (block_size < sizeof(struct GNUNET_MessageHeader))
333 if (block_size != ntohs (msg->size)) 310 {
334 { 311 GNUNET_break_op (0);
335 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, 312 memset (key,
336 "block-dht", 313 0,
337 _ ("Size mismatch for block with type %u\n"), 314 sizeof (*key));
338 GNUNET_BLOCK_TYPE_DHT_HELLO); 315 return GNUNET_OK;
339 return GNUNET_NO; 316 }
340 } 317 msg = block;
341 hello = block; 318 if (block_size != ntohs (msg->size))
342 memset (key, 0, sizeof(*key)); 319 {
343 pid = (struct GNUNET_PeerIdentity *) key; 320 GNUNET_break_op (0);
344 if (GNUNET_OK != GNUNET_HELLO_get_id (hello, pid)) 321 memset (key,
345 { 322 0,
346 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, 323 sizeof (*key));
347 "block-dht", 324 return GNUNET_OK;
348 _ ("Block of type %u is malformed\n"), 325 }
349 GNUNET_BLOCK_TYPE_DHT_HELLO); 326 hello = block;
350 return GNUNET_NO; 327 memset (key,
328 0,
329 sizeof(*key));
330 pid = (struct GNUNET_PeerIdentity *) key;
331 if (GNUNET_OK !=
332 GNUNET_HELLO_get_id (hello,
333 pid))
334 {
335 GNUNET_break_op (0);
336 memset (key,
337 0,
338 sizeof (*key));
339 return GNUNET_OK;
340 }
341 return GNUNET_OK;
342 }
343 case GNUNET_BLOCK_TYPE_DHT_URL_HELLO:
344 {
345 struct GNUNET_HELLO_Builder *b;
346 struct GNUNET_PeerIdentity pid;
347
348 b = GNUNET_HELLO_builder_from_block (block,
349 block_size);
350 if (NULL == b)
351 {
352 GNUNET_break (0);
353 memset (key,
354 0,
355 sizeof (*key));
356 return GNUNET_OK;
357 }
358 GNUNET_HELLO_builder_iterate (b,
359 &pid,
360 NULL, NULL);
361 GNUNET_CRYPTO_hash (&pid,
362 sizeof (pid),
363 key);
364 GNUNET_HELLO_builder_free (b);
365 return GNUNET_OK;
366 }
367 default:
368 GNUNET_break (0);
369 return GNUNET_SYSERR;
351 } 370 }
352 return GNUNET_OK;
353} 371}
354 372
355 373
@@ -361,12 +379,12 @@ libgnunet_plugin_block_dht_init (void *cls)
361{ 379{
362 static enum GNUNET_BLOCK_Type types[] = { 380 static enum GNUNET_BLOCK_Type types[] = {
363 GNUNET_BLOCK_TYPE_DHT_HELLO, 381 GNUNET_BLOCK_TYPE_DHT_HELLO,
382 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
364 GNUNET_BLOCK_TYPE_ANY /* end of list */ 383 GNUNET_BLOCK_TYPE_ANY /* end of list */
365 }; 384 };
366 struct GNUNET_BLOCK_PluginFunctions *api; 385 struct GNUNET_BLOCK_PluginFunctions *api;
367 386
368 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 387 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
369 api->evaluate = &block_plugin_dht_evaluate;
370 api->get_key = &block_plugin_dht_get_key; 388 api->get_key = &block_plugin_dht_get_key;
371 api->check_query = &block_plugin_dht_check_query; 389 api->check_query = &block_plugin_dht_check_query;
372 api->check_block = &block_plugin_dht_check_block; 390 api->check_block = &block_plugin_dht_check_block;
diff --git a/src/dht/test_dht_topo.c b/src/dht/test_dht_topo.c
index eb7e80d3b..4830ba629 100644
--- a/src/dht/test_dht_topo.c
+++ b/src/dht/test_dht_topo.c
@@ -326,7 +326,7 @@ timeout_cb (void *cls)
326 * 326 *
327 * @param cls closure with our 'struct GetOperation' 327 * @param cls closure with our 'struct GetOperation'
328 * @param exp when will this value expire 328 * @param exp when will this value expire
329 * @param key key of the result 329 * @param query query hash
330 * @param get_path peers on reply path (or NULL if not recorded) 330 * @param get_path peers on reply path (or NULL if not recorded)
331 * @param get_path_length number of entries in @a get_path 331 * @param get_path_length number of entries in @a get_path
332 * @param put_path peers on the PUT path (or NULL if not recorded) 332 * @param put_path peers on the PUT path (or NULL if not recorded)
@@ -338,7 +338,7 @@ timeout_cb (void *cls)
338static void 338static void
339dht_get_handler (void *cls, 339dht_get_handler (void *cls,
340 struct GNUNET_TIME_Absolute exp, 340 struct GNUNET_TIME_Absolute exp,
341 const struct GNUNET_HashCode *key, 341 const struct GNUNET_HashCode *query,
342 const struct GNUNET_DHT_PathElement *get_path, 342 const struct GNUNET_DHT_PathElement *get_path,
343 unsigned int get_path_length, 343 unsigned int get_path_length,
344 const struct GNUNET_DHT_PathElement *put_path, 344 const struct GNUNET_DHT_PathElement *put_path,
@@ -359,8 +359,15 @@ dht_get_handler (void *cls,
359 GNUNET_break (0); 359 GNUNET_break (0);
360 return; 360 return;
361 } 361 }
362 GNUNET_CRYPTO_hash (key, 362 if (0 != GNUNET_memcmp (query,
363 sizeof(*key), 363 &get_op->key))
364 {
365 /* exact search should only yield exact results */
366 GNUNET_break (0);
367 return;
368 }
369 GNUNET_CRYPTO_hash (query,
370 sizeof(*query),
364 &want); 371 &want);
365 if (0 != memcmp (&want, 372 if (0 != memcmp (&want,
366 data, 373 data,
@@ -370,18 +377,21 @@ dht_get_handler (void *cls,
370 return; 377 return;
371 } 378 }
372 if (0 != 379 if (0 !=
373 GNUNET_DHT_verify_path (key, 380 GNUNET_DHT_verify_path (data,
374 data,
375 size, 381 size,
376 exp, 382 exp,
377 get_path,
378 get_path_length,
379 put_path, 383 put_path,
380 put_path_length, 384 put_path_length,
385 get_path,
386 get_path_length,
381 &get_op->me)) 387 &get_op->me))
382 { 388 {
389 GNUNET_break (0);
383 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 390 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
384 "Path signature verification failed!\n"); 391 "Path signature (%u/%u) verification failed for peer %s!\n",
392 get_path_length,
393 put_path_length,
394 GNUNET_i2s (&get_op->me));
385 } 395 }
386 else 396 else
387 { 397 {
diff --git a/src/dhtu/Makefile.am b/src/dhtu/Makefile.am
index 0e10721cd..ebffa9ecf 100644
--- a/src/dhtu/Makefile.am
+++ b/src/dhtu/Makefile.am
@@ -10,6 +10,10 @@ if USE_COVERAGE
10 XLIBS = -lgcov 10 XLIBS = -lgcov
11endif 11endif
12 12
13pkgcfg_DATA = \
14 dhtu.conf
15
16
13plugin_LTLIBRARIES = \ 17plugin_LTLIBRARIES = \
14 libgnunet_plugin_dhtu_gnunet.la \ 18 libgnunet_plugin_dhtu_gnunet.la \
15 libgnunet_plugin_dhtu_ip.la 19 libgnunet_plugin_dhtu_ip.la
@@ -67,6 +71,9 @@ test_dhtu_ip_LDADD = \
67check_PROGRAMS = \ 71check_PROGRAMS = \
68 test_dhtu_ip 72 test_dhtu_ip
69 73
74EXTRA_DIST = \
75 dhtu.conf
76
70if ENABLE_TEST_RUN 77if ENABLE_TEST_RUN
71AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 78AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
72TESTS = \ 79TESTS = \
diff --git a/src/dhtu/dhtu.conf b/src/dhtu/dhtu.conf
new file mode 100644
index 000000000..ea5ade752
--- /dev/null
+++ b/src/dhtu/dhtu.conf
@@ -0,0 +1,7 @@
1[dhtu-gnunet]
2ENABLED = YES
3
4[dhtu-ip]
5ENABLED = NO
6NSE = 4
7UDP_PORT = 6666
diff --git a/src/dhtu/plugin_dhtu_gnunet.c b/src/dhtu/plugin_dhtu_gnunet.c
index 2163af941..b072be2be 100644
--- a/src/dhtu/plugin_dhtu_gnunet.c
+++ b/src/dhtu/plugin_dhtu_gnunet.c
@@ -70,11 +70,6 @@ struct GNUNET_DHTU_Source
70{ 70{
71 71
72 /** 72 /**
73 * Hash of @e pid, position of this peer in the DHT overlay.
74 */
75 struct GNUNET_DHTU_HashKey id;
76
77 /**
78 * Application context for this source. 73 * Application context for this source.
79 */ 74 */
80 void *app_ctx; 75 void *app_ctx;
@@ -125,11 +120,6 @@ struct GNUNET_DHTU_Target
125 struct GNUNET_PeerIdentity pid; 120 struct GNUNET_PeerIdentity pid;
126 121
127 /** 122 /**
128 * Hash of @e pid, position of this peer in the DHT overlay.
129 */
130 struct GNUNET_DHTU_HashKey id;
131
132 /**
133 * Preference counter, length of the @a ph_head DLL. 123 * Preference counter, length of the @a ph_head DLL.
134 */ 124 */
135 unsigned int ph_count; 125 unsigned int ph_count;
@@ -240,27 +230,26 @@ hello_offered_cb (void *cls)
240 * Request creation of a session with a peer at the given @a address. 230 * Request creation of a session with a peer at the given @a address.
241 * 231 *
242 * @param cls closure (internal context for the plugin) 232 * @param cls closure (internal context for the plugin)
233 * @param pid target identity of the peer to connect to
243 * @param address target address to connect to 234 * @param address target address to connect to
244 */ 235 */
245static void 236static void
246ip_try_connect (void *cls, 237gnunet_try_connect (void *cls,
247 const char *address) 238 const struct GNUNET_PeerIdentity *pid,
239 const char *address)
248{ 240{
249 struct Plugin *plugin = cls; 241 struct Plugin *plugin = cls;
250 struct GNUNET_HELLO_Message *hello = NULL; 242 struct GNUNET_HELLO_Message *hello = NULL;
251 struct HelloHandle *hh; 243 struct HelloHandle *hh;
252 struct GNUNET_CRYPTO_EddsaPublicKey pubkey; 244 struct GNUNET_CRYPTO_EddsaPublicKey pubkey;
253 245
246 (void) pid; /* will be needed with future address URIs */
254 if (GNUNET_OK != 247 if (GNUNET_OK !=
255 GNUNET_HELLO_parse_uri (address, 248 GNUNET_HELLO_parse_uri (address,
256 &pubkey, 249 &pubkey,
257 &hello, 250 &hello,
258 &GPI_plugins_find)) 251 &GPI_plugins_find))
259 {
260 GNUNET_break (0);
261 return; 252 return;
262 }
263
264 hh = GNUNET_new (struct HelloHandle); 253 hh = GNUNET_new (struct HelloHandle);
265 hh->plugin = plugin; 254 hh->plugin = plugin;
266 GNUNET_CONTAINER_DLL_insert (plugin->hh_head, 255 GNUNET_CONTAINER_DLL_insert (plugin->hh_head,
@@ -283,8 +272,8 @@ ip_try_connect (void *cls,
283 * @param target connection to keep alive 272 * @param target connection to keep alive
284 */ 273 */
285static struct GNUNET_DHTU_PreferenceHandle * 274static struct GNUNET_DHTU_PreferenceHandle *
286ip_hold (void *cls, 275gnunet_hold (void *cls,
287 struct GNUNET_DHTU_Target *target) 276 struct GNUNET_DHTU_Target *target)
288{ 277{
289 struct Plugin *plugin = cls; 278 struct Plugin *plugin = cls;
290 struct GNUNET_DHTU_PreferenceHandle *ph; 279 struct GNUNET_DHTU_PreferenceHandle *ph;
@@ -312,7 +301,7 @@ ip_hold (void *cls,
312 * @param target connection to keep alive 301 * @param target connection to keep alive
313 */ 302 */
314static void 303static void
315ip_drop (struct GNUNET_DHTU_PreferenceHandle *ph) 304gnunet_drop (struct GNUNET_DHTU_PreferenceHandle *ph)
316{ 305{
317 struct GNUNET_DHTU_Target *target = ph->target; 306 struct GNUNET_DHTU_Target *target = ph->target;
318 struct Plugin *plugin = target->plugin; 307 struct Plugin *plugin = target->plugin;
@@ -350,12 +339,12 @@ ip_drop (struct GNUNET_DHTU_PreferenceHandle *ph)
350 * @param finished_cb_cls closure for @a finished_cb 339 * @param finished_cb_cls closure for @a finished_cb
351 */ 340 */
352static void 341static void
353ip_send (void *cls, 342gnunet_send (void *cls,
354 struct GNUNET_DHTU_Target *target, 343 struct GNUNET_DHTU_Target *target,
355 const void *msg, 344 const void *msg,
356 size_t msg_size, 345 size_t msg_size,
357 GNUNET_SCHEDULER_TaskCallback finished_cb, 346 GNUNET_SCHEDULER_TaskCallback finished_cb,
358 void *finished_cb_cls) 347 void *finished_cb_cls)
359{ 348{
360 struct GNUNET_MQ_Envelope *env; 349 struct GNUNET_MQ_Envelope *env;
361 struct GNUNET_MessageHeader *cmsg; 350 struct GNUNET_MessageHeader *cmsg;
@@ -394,12 +383,9 @@ core_connect_cb (void *cls,
394 target->plugin = plugin; 383 target->plugin = plugin;
395 target->mq = mq; 384 target->mq = mq;
396 target->pid = *peer; 385 target->pid = *peer;
397 GNUNET_CRYPTO_hash (peer,
398 sizeof (*peer),
399 &target->id.sha512);
400 plugin->env->connect_cb (plugin->env->cls, 386 plugin->env->connect_cb (plugin->env->cls,
401 target, 387 target,
402 &target->id, 388 &target->pid,
403 &target->app_ctx); 389 &target->app_ctx);
404 return target; 390 return target;
405} 391}
@@ -461,11 +447,7 @@ peerinfo_cb (void *cls,
461 &GPI_plugins_find); 447 &GPI_plugins_find);
462 if (NULL == addr) 448 if (NULL == addr)
463 return; 449 return;
464 GNUNET_CRYPTO_hash (peer,
465 sizeof (*peer),
466 &plugin->src.id.sha512);
467 plugin->env->address_add_cb (plugin->env->cls, 450 plugin->env->address_add_cb (plugin->env->cls,
468 &plugin->src.id,
469 addr, 451 addr,
470 &plugin->src, 452 &plugin->src,
471 &plugin->src.app_ctx); 453 &plugin->src.app_ctx);
@@ -584,6 +566,10 @@ libgnunet_plugin_dhtu_gnunet_done (void *cls)
584 } 566 }
585 if (NULL != plugin->nse) 567 if (NULL != plugin->nse)
586 GNUNET_NSE_disconnect (plugin->nse); 568 GNUNET_NSE_disconnect (plugin->nse);
569 plugin->env->network_size_cb (plugin->env->cls,
570 GNUNET_TIME_UNIT_FOREVER_ABS,
571 0.0,
572 0.0);
587 if (NULL != plugin->core) 573 if (NULL != plugin->core)
588 GNUNET_CORE_disconnect (plugin->core); 574 GNUNET_CORE_disconnect (plugin->core);
589 if (NULL != plugin->ats) 575 if (NULL != plugin->ats)
@@ -604,7 +590,7 @@ libgnunet_plugin_dhtu_gnunet_done (void *cls)
604 * @return the plugin's API 590 * @return the plugin's API
605 */ 591 */
606void * 592void *
607libgnunet_plugin_dhtu_ip_init (void *cls) 593libgnunet_plugin_dhtu_gnunet_init (void *cls)
608{ 594{
609 struct GNUNET_DHTU_PluginEnvironment *env = cls; 595 struct GNUNET_DHTU_PluginEnvironment *env = cls;
610 struct GNUNET_DHTU_PluginFunctions *api; 596 struct GNUNET_DHTU_PluginFunctions *api;
@@ -621,10 +607,10 @@ libgnunet_plugin_dhtu_ip_init (void *cls)
621 plugin->env = env; 607 plugin->env = env;
622 api = GNUNET_new (struct GNUNET_DHTU_PluginFunctions); 608 api = GNUNET_new (struct GNUNET_DHTU_PluginFunctions);
623 api->cls = plugin; 609 api->cls = plugin;
624 api->try_connect = &ip_try_connect; 610 api->try_connect = &gnunet_try_connect;
625 api->hold = &ip_hold; 611 api->hold = &gnunet_hold;
626 api->drop = &ip_drop; 612 api->drop = &gnunet_drop;
627 api->send = &ip_send; 613 api->send = &gnunet_send;
628 plugin->ats = GNUNET_ATS_connectivity_init (env->cfg); 614 plugin->ats = GNUNET_ATS_connectivity_init (env->cfg);
629 plugin->core = GNUNET_CORE_connect (env->cfg, 615 plugin->core = GNUNET_CORE_connect (env->cfg,
630 plugin, 616 plugin,
@@ -640,6 +626,7 @@ libgnunet_plugin_dhtu_ip_init (void *cls)
640 (NULL == plugin->nse) ) 626 (NULL == plugin->nse) )
641 { 627 {
642 GNUNET_break (0); 628 GNUNET_break (0);
629 GNUNET_free (api);
643 libgnunet_plugin_dhtu_gnunet_done (plugin); 630 libgnunet_plugin_dhtu_gnunet_done (plugin);
644 return NULL; 631 return NULL;
645 } 632 }
diff --git a/src/dhtu/plugin_dhtu_ip.c b/src/dhtu/plugin_dhtu_ip.c
index 8eec6294b..612d2c119 100644
--- a/src/dhtu/plugin_dhtu_ip.c
+++ b/src/dhtu/plugin_dhtu_ip.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V. 3 Copyright (C) 2021, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -56,17 +56,12 @@ struct GNUNET_DHTU_Source
56 struct GNUNET_DHTU_Source *prev; 56 struct GNUNET_DHTU_Source *prev;
57 57
58 /** 58 /**
59 * Position of this peer in the DHT.
60 */
61 struct GNUNET_DHTU_HashKey id;
62
63 /**
64 * Application context for this source. 59 * Application context for this source.
65 */ 60 */
66 void *app_ctx; 61 void *app_ctx;
67 62
68 /** 63 /**
69 * Address in URL form ("ip+udp://$IP:$PORT") 64 * Address in URL form ("ip+udp://$PID/$IP:$PORT")
70 */ 65 */
71 char *address; 66 char *address;
72 67
@@ -121,9 +116,9 @@ struct GNUNET_DHTU_Target
121 struct GNUNET_DHTU_PreferenceHandle *ph_tail; 116 struct GNUNET_DHTU_PreferenceHandle *ph_tail;
122 117
123 /** 118 /**
124 * Position of this peer in the DHT. 119 * Peer's identity.
125 */ 120 */
126 struct GNUNET_DHTU_HashKey id; 121 struct GNUNET_PeerIdentity pid;
127 122
128 /** 123 /**
129 * Target IP address. 124 * Target IP address.
@@ -217,14 +212,24 @@ struct Plugin
217 char *port; 212 char *port;
218 213
219 /** 214 /**
215 * My UDP socket.
216 */
217 struct GNUNET_NETWORK_Handle *sock;
218
219 /**
220 * My identity.
221 */
222 struct GNUNET_PeerIdentity my_id;
223
224 /**
220 * How often have we scanned for IPs? 225 * How often have we scanned for IPs?
221 */ 226 */
222 unsigned int scan_generation; 227 unsigned int scan_generation;
223 228
224 /** 229 /**
225 * My UDP socket. 230 * Port as a 16-bit value.
226 */ 231 */
227 struct GNUNET_NETWORK_Handle *sock; 232 uint16_t port16;
228}; 233};
229 234
230 235
@@ -232,18 +237,20 @@ struct Plugin
232 * Create a target to which we may send traffic. 237 * Create a target to which we may send traffic.
233 * 238 *
234 * @param plugin our plugin 239 * @param plugin our plugin
240 * @param pid presumed identity of the target
235 * @param addr target address 241 * @param addr target address
236 * @param addrlen number of bytes in @a addr 242 * @param addrlen number of bytes in @a addr
237 * @return new target object 243 * @return new target object
238 */ 244 */
239static struct GNUNET_DHTU_Target * 245static struct GNUNET_DHTU_Target *
240create_target (struct Plugin *plugin, 246create_target (struct Plugin *plugin,
247 const struct GNUNET_PeerIdentity *pid,
241 const struct sockaddr *addr, 248 const struct sockaddr *addr,
242 socklen_t addrlen) 249 socklen_t addrlen)
243{ 250{
244 struct GNUNET_DHTU_Target *dst; 251 struct GNUNET_DHTU_Target *dst;
245 252
246 if (MAX_DESTS > 253 if (MAX_DESTS <=
247 GNUNET_CONTAINER_multihashmap_size (plugin->dsts)) 254 GNUNET_CONTAINER_multihashmap_size (plugin->dsts))
248 { 255 {
249 struct GNUNET_HashCode key; 256 struct GNUNET_HashCode key;
@@ -275,42 +282,16 @@ create_target (struct Plugin *plugin,
275 } 282 }
276 dst = GNUNET_new (struct GNUNET_DHTU_Target); 283 dst = GNUNET_new (struct GNUNET_DHTU_Target);
277 dst->addrlen = addrlen; 284 dst->addrlen = addrlen;
285 dst->pid = *pid;
278 memcpy (&dst->addr, 286 memcpy (&dst->addr,
279 addr, 287 addr,
280 addrlen); 288 addrlen);
281 switch (addr->sa_family)
282 {
283 case AF_INET:
284 {
285 const struct sockaddr_in *s4 = (const struct sockaddr_in *) addr;
286
287 GNUNET_assert (sizeof (struct sockaddr_in) == addrlen);
288 GNUNET_CRYPTO_hash (&s4->sin_addr,
289 sizeof (struct in_addr),
290 &dst->id.sha512);
291 }
292 break;
293 case AF_INET6:
294 {
295 const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) addr;
296
297 GNUNET_assert (sizeof (struct sockaddr_in6) == addrlen);
298 GNUNET_CRYPTO_hash (&s6->sin6_addr,
299 sizeof (struct in6_addr),
300 &dst->id.sha512);
301 }
302 break;
303 default:
304 GNUNET_break (0);
305 GNUNET_free (dst);
306 return NULL;
307 }
308 GNUNET_CONTAINER_DLL_insert (plugin->dst_head, 289 GNUNET_CONTAINER_DLL_insert (plugin->dst_head,
309 plugin->dst_tail, 290 plugin->dst_tail,
310 dst); 291 dst);
311 plugin->env->connect_cb (plugin->env->cls, 292 plugin->env->connect_cb (plugin->env->cls,
312 dst, 293 dst,
313 &dst->id, 294 &dst->pid,
314 &dst->app_ctx); 295 &dst->app_ctx);
315 return dst; 296 return dst;
316} 297}
@@ -321,6 +302,7 @@ create_target (struct Plugin *plugin,
321 * create one! 302 * create one!
322 * 303 *
323 * @param plugin the plugin handle 304 * @param plugin the plugin handle
305 * @param pid presumed identity of the target
324 * @param src source target is from, or NULL if unknown 306 * @param src source target is from, or NULL if unknown
325 * @param addr socket address to find 307 * @param addr socket address to find
326 * @param addrlen number of bytes in @a addr 308 * @param addrlen number of bytes in @a addr
@@ -328,6 +310,7 @@ create_target (struct Plugin *plugin,
328 */ 310 */
329static struct GNUNET_DHTU_Target * 311static struct GNUNET_DHTU_Target *
330find_target (struct Plugin *plugin, 312find_target (struct Plugin *plugin,
313 const struct GNUNET_PeerIdentity *pid,
331 const void *addr, 314 const void *addr,
332 size_t addrlen) 315 size_t addrlen)
333{ 316{
@@ -342,6 +325,7 @@ find_target (struct Plugin *plugin,
342 if (NULL == dst) 325 if (NULL == dst)
343 { 326 {
344 dst = create_target (plugin, 327 dst = create_target (plugin,
328 pid,
345 (const struct sockaddr *) addr, 329 (const struct sockaddr *) addr,
346 addrlen); 330 addrlen);
347 GNUNET_assert (GNUNET_YES == 331 GNUNET_assert (GNUNET_YES ==
@@ -370,10 +354,12 @@ find_target (struct Plugin *plugin,
370 * Request creation of a session with a peer at the given @a address. 354 * Request creation of a session with a peer at the given @a address.
371 * 355 *
372 * @param cls closure (internal context for the plugin) 356 * @param cls closure (internal context for the plugin)
357 * @param pid identity of the target peer
373 * @param address target address to connect to 358 * @param address target address to connect to
374 */ 359 */
375static void 360static void
376ip_try_connect (void *cls, 361ip_try_connect (void *cls,
362 const struct GNUNET_PeerIdentity *pid,
377 const char *address) 363 const char *address)
378{ 364{
379 struct Plugin *plugin = cls; 365 struct Plugin *plugin = cls;
@@ -389,19 +375,13 @@ ip_try_connect (void *cls,
389 strncmp (address, 375 strncmp (address,
390 "ip+", 376 "ip+",
391 strlen ("ip+"))) 377 strlen ("ip+")))
392 {
393 GNUNET_break (0);
394 return; 378 return;
395 }
396 address += strlen ("ip+"); 379 address += strlen ("ip+");
397 if (0 != 380 if (0 !=
398 strncmp (address, 381 strncmp (address,
399 "udp://", 382 "udp://",
400 strlen ("udp://"))) 383 strlen ("udp://")))
401 {
402 GNUNET_break (0);
403 return; 384 return;
404 }
405 address += strlen ("udp://"); 385 address += strlen ("udp://");
406 addr = GNUNET_strdup (address); 386 addr = GNUNET_strdup (address);
407 colon = strchr (addr, ':'); 387 colon = strchr (addr, ':');
@@ -426,6 +406,7 @@ ip_try_connect (void *cls,
426 } 406 }
427 GNUNET_free (addr); 407 GNUNET_free (addr);
428 (void) find_target (plugin, 408 (void) find_target (plugin,
409 pid,
429 result->ai_addr, 410 result->ai_addr,
430 result->ai_addrlen); 411 result->ai_addrlen);
431 freeaddrinfo (result); 412 freeaddrinfo (result);
@@ -499,10 +480,17 @@ ip_send (void *cls,
499 void *finished_cb_cls) 480 void *finished_cb_cls)
500{ 481{
501 struct Plugin *plugin = cls; 482 struct Plugin *plugin = cls;
502 483 char buf[sizeof (plugin->my_id) + msg_size];
484
485 memcpy (buf,
486 &plugin->my_id,
487 sizeof (plugin->my_id));
488 memcpy (&buf[sizeof (plugin->my_id)],
489 msg,
490 msg_size);
503 GNUNET_NETWORK_socket_sendto (plugin->sock, 491 GNUNET_NETWORK_socket_sendto (plugin->sock,
504 msg, 492 buf,
505 msg_size, 493 sizeof (buf),
506 (const struct sockaddr *) &target->addr, 494 (const struct sockaddr *) &target->addr,
507 target->addrlen); 495 target->addrlen);
508 finished_cb (finished_cb_cls); 496 finished_cb (finished_cb_cls);
@@ -538,9 +526,6 @@ create_source (struct Plugin *plugin,
538 char buf[INET_ADDRSTRLEN]; 526 char buf[INET_ADDRSTRLEN];
539 527
540 GNUNET_assert (sizeof (struct sockaddr_in) == addrlen); 528 GNUNET_assert (sizeof (struct sockaddr_in) == addrlen);
541 GNUNET_CRYPTO_hash (&s4->sin_addr,
542 sizeof (struct in_addr),
543 &src->id.sha512);
544 GNUNET_asprintf (&src->address, 529 GNUNET_asprintf (&src->address,
545 "ip+udp://%s:%u", 530 "ip+udp://%s:%u",
546 inet_ntop (AF_INET, 531 inet_ntop (AF_INET,
@@ -556,9 +541,6 @@ create_source (struct Plugin *plugin,
556 char buf[INET6_ADDRSTRLEN]; 541 char buf[INET6_ADDRSTRLEN];
557 542
558 GNUNET_assert (sizeof (struct sockaddr_in6) == addrlen); 543 GNUNET_assert (sizeof (struct sockaddr_in6) == addrlen);
559 GNUNET_CRYPTO_hash (&s6->sin6_addr,
560 sizeof (struct in6_addr),
561 &src->id.sha512);
562 GNUNET_asprintf (&src->address, 544 GNUNET_asprintf (&src->address,
563 "ip+udp://[%s]:%u", 545 "ip+udp://[%s]:%u",
564 inet_ntop (AF_INET6, 546 inet_ntop (AF_INET6,
@@ -577,7 +559,6 @@ create_source (struct Plugin *plugin,
577 plugin->src_tail, 559 plugin->src_tail,
578 src); 560 src);
579 plugin->env->address_add_cb (plugin->env->cls, 561 plugin->env->address_add_cb (plugin->env->cls,
580 &src->id,
581 src->address, 562 src->address,
582 src, 563 src,
583 &src->app_ctx); 564 &src->app_ctx);
@@ -586,6 +567,101 @@ create_source (struct Plugin *plugin,
586 567
587 568
588/** 569/**
570 * Compare two addresses excluding the ports for equality. Only compares IP
571 * address. Must only be called on AF_INET or AF_INET6 addresses.
572 *
573 * @param a1 address to compare
574 * @param a2 address to compare
575 * @param alen number of bytes in @a a1 and @a a2
576 * @return 0 if @a a1 == @a a2.
577 */
578static int
579addrcmp_np (const struct sockaddr *a1,
580 const struct sockaddr *a2,
581 size_t alen)
582{
583 GNUNET_assert (a1->sa_family == a2->sa_family);
584 switch (a1->sa_family)
585 {
586 case AF_INET:
587 GNUNET_assert (sizeof (struct sockaddr_in) == alen);
588 {
589 const struct sockaddr_in *s1 = (const struct sockaddr_in *) a1;
590 const struct sockaddr_in *s2 = (const struct sockaddr_in *) a2;
591
592 if (s1->sin_addr.s_addr != s2->sin_addr.s_addr)
593 return 1;
594 break;
595 }
596 case AF_INET6:
597 GNUNET_assert (sizeof (struct sockaddr_in6) == alen);
598 {
599 const struct sockaddr_in6 *s1 = (const struct sockaddr_in6 *) a1;
600 const struct sockaddr_in6 *s2 = (const struct sockaddr_in6 *) a2;
601
602 if (0 != GNUNET_memcmp (&s1->sin6_addr,
603 &s2->sin6_addr))
604 return 1;
605 break;
606 }
607 default:
608 GNUNET_assert (0);
609 }
610 return 0;
611}
612
613
614/**
615 * Compare two addresses for equality. Only
616 * compares IP address and port. Must only be
617 * called on AF_INET or AF_INET6 addresses.
618 *
619 * @param a1 address to compare
620 * @param a2 address to compare
621 * @param alen number of bytes in @a a1 and @a a2
622 * @return 0 if @a a1 == @a a2.
623 */
624static int
625addrcmp (const struct sockaddr *a1,
626 const struct sockaddr *a2,
627 size_t alen)
628{
629 GNUNET_assert (a1->sa_family == a2->sa_family);
630 switch (a1->sa_family)
631 {
632 case AF_INET:
633 GNUNET_assert (sizeof (struct sockaddr_in) == alen);
634 {
635 const struct sockaddr_in *s1 = (const struct sockaddr_in *) a1;
636 const struct sockaddr_in *s2 = (const struct sockaddr_in *) a2;
637
638 if (s1->sin_port != s2->sin_port)
639 return 1;
640 if (s1->sin_addr.s_addr != s2->sin_addr.s_addr)
641 return 1;
642 break;
643 }
644 case AF_INET6:
645 GNUNET_assert (sizeof (struct sockaddr_in6) == alen);
646 {
647 const struct sockaddr_in6 *s1 = (const struct sockaddr_in6 *) a1;
648 const struct sockaddr_in6 *s2 = (const struct sockaddr_in6 *) a2;
649
650 if (s1->sin6_port != s2->sin6_port)
651 return 1;
652 if (0 != GNUNET_memcmp (&s1->sin6_addr,
653 &s2->sin6_addr))
654 return 1;
655 break;
656 }
657 default:
658 GNUNET_assert (0);
659 }
660 return 0;
661}
662
663
664/**
589 * Callback function invoked for each interface found. 665 * Callback function invoked for each interface found.
590 * 666 *
591 * @param cls closure 667 * @param cls closure
@@ -597,7 +673,7 @@ create_source (struct Plugin *plugin,
597 * @param addrlen length of the address 673 * @param addrlen length of the address
598 * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort 674 * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
599 */ 675 */
600static int 676static enum GNUNET_GenericReturnValue
601process_ifcs (void *cls, 677process_ifcs (void *cls,
602 const char *name, 678 const char *name,
603 int isDefault, 679 int isDefault,
@@ -614,17 +690,45 @@ process_ifcs (void *cls,
614 src = src->next) 690 src = src->next)
615 { 691 {
616 if ( (addrlen == src->addrlen) && 692 if ( (addrlen == src->addrlen) &&
617 (0 == memcmp (addr, 693 (0 == addrcmp_np (addr,
618 &src->addr, 694 (const struct sockaddr *) &src->addr,
619 addrlen)) ) 695 addrlen)) )
620 { 696 {
621 src->scan_generation = plugin->scan_generation; 697 src->scan_generation = plugin->scan_generation;
622 return GNUNET_OK; 698 return GNUNET_OK;
623 } 699 }
624 } 700 }
625 (void) create_source (plugin, 701 switch (addr->sa_family)
626 addr, 702 {
627 addrlen); 703 case AF_INET:
704 {
705 struct sockaddr_in v4;
706
707 GNUNET_assert (sizeof(v4) == addrlen);
708 memcpy (&v4,
709 addr,
710 addrlen);
711 v4.sin_port = htons (plugin->port16);
712 (void) create_source (plugin,
713 (const struct sockaddr *) &v4,
714 sizeof (v4));
715 break;
716 }
717 case AF_INET6:
718 {
719 struct sockaddr_in6 v6;
720
721 GNUNET_assert (sizeof(v6) == addrlen);
722 memcpy (&v6,
723 addr,
724 addrlen);
725 v6.sin6_port = htons (plugin->port16);
726 (void) create_source (plugin,
727 (const struct sockaddr *) &v6,
728 sizeof (v6));
729 break;
730 }
731 }
628 return GNUNET_OK; 732 return GNUNET_OK;
629} 733}
630 734
@@ -648,7 +752,7 @@ scan (void *cls)
648 src = next) 752 src = next)
649 { 753 {
650 next = src->next; 754 next = src->next;
651 if (src->scan_generation == plugin->scan_generation) 755 if (src->scan_generation >= plugin->scan_generation)
652 continue; 756 continue;
653 GNUNET_CONTAINER_DLL_remove (plugin->src_head, 757 GNUNET_CONTAINER_DLL_remove (plugin->src_head,
654 plugin->src_tail, 758 plugin->src_tail,
@@ -682,9 +786,9 @@ find_source (struct Plugin *plugin,
682 src = src->next) 786 src = src->next)
683 { 787 {
684 if ( (addrlen == src->addrlen) && 788 if ( (addrlen == src->addrlen) &&
685 (0 == memcmp (addr, 789 (0 == addrcmp (addr,
686 &src->addr, 790 (const struct sockaddr *) &src->addr,
687 addrlen)) ) 791 addrlen)) )
688 return src; 792 return src;
689 } 793 }
690 794
@@ -704,7 +808,8 @@ read_cb (void *cls)
704{ 808{
705 struct Plugin *plugin = cls; 809 struct Plugin *plugin = cls;
706 ssize_t ret; 810 ssize_t ret;
707 char buf[65536]; 811 const struct GNUNET_PeerIdentity *pid;
812 char buf[65536] GNUNET_ALIGN;
708 struct sockaddr_storage sa; 813 struct sockaddr_storage sa;
709 struct iovec iov = { 814 struct iovec iov = {
710 .iov_base = buf, 815 .iov_base = buf,
@@ -719,98 +824,120 @@ read_cb (void *cls)
719 .msg_control = ctl, 824 .msg_control = ctl,
720 .msg_controllen = sizeof (ctl) 825 .msg_controllen = sizeof (ctl)
721 }; 826 };
827 struct GNUNET_DHTU_Target *dst = NULL;
828 struct GNUNET_DHTU_Source *src = NULL;
722 829
723 ret = recvmsg (GNUNET_NETWORK_get_fd (plugin->sock), 830 ret = recvmsg (GNUNET_NETWORK_get_fd (plugin->sock),
724 &mh, 831 &mh,
725 MSG_DONTWAIT); 832 MSG_DONTWAIT);
726 if (ret >= 0) 833 plugin->read_task = GNUNET_SCHEDULER_add_read_net (
834 GNUNET_TIME_UNIT_FOREVER_REL,
835 plugin->sock,
836 &read_cb,
837 plugin);
838 if (ret < 0)
839 return; /* read failure, hopefully EAGAIN */
840 if (ret < sizeof (*pid))
841 {
842 GNUNET_break_op (0);
843 return;
844 }
845 /* find IP where we received message */
846 for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mh);
847 NULL != cmsg;
848 cmsg = CMSG_NXTHDR (&mh,
849 cmsg))
727 { 850 {
728 struct GNUNET_DHTU_Target *dst = NULL; 851 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
729 struct GNUNET_DHTU_Source *src = NULL; 852 "Got CMSG level %u (%d/%d), type %u (%d/%d)\n",
730 struct cmsghdr *cmsg; 853 cmsg->cmsg_level,
731 854 (cmsg->cmsg_level == IPPROTO_IP),
732 /* find IP where we received message */ 855 (cmsg->cmsg_level == IPPROTO_IPV6),
733 for (cmsg = CMSG_FIRSTHDR (&mh); 856 cmsg->cmsg_type,
734 NULL != cmsg; 857 (cmsg->cmsg_type == IP_PKTINFO),
735 cmsg = CMSG_NXTHDR (&mh, 858 (cmsg->cmsg_type == IPV6_PKTINFO));
736 cmsg)) 859 if ( (cmsg->cmsg_level == IPPROTO_IP) &&
860 (cmsg->cmsg_type == IP_PKTINFO) )
737 { 861 {
738 if ( (cmsg->cmsg_level == IPPROTO_IP) && 862 if (CMSG_LEN (sizeof (struct in_pktinfo)) ==
739 (cmsg->cmsg_type == IP_PKTINFO) ) 863 cmsg->cmsg_len)
740 { 864 {
741 if (CMSG_LEN (sizeof (struct in_pktinfo)) == 865 struct in_pktinfo pi;
742 cmsg->cmsg_len) 866
867 memcpy (&pi,
868 CMSG_DATA (cmsg),
869 sizeof (pi));
743 { 870 {
744 struct in_pktinfo pi; 871 struct sockaddr_in sa = {
745 872 .sin_family = AF_INET,
746 memcpy (&pi, 873 .sin_addr = pi.ipi_addr,
747 CMSG_DATA (cmsg), 874 .sin_port = htons (plugin->port16)
748 sizeof (pi)); 875 };
749 { 876
750 struct sockaddr_in sa = { 877 src = find_source (plugin,
751 .sin_family = AF_INET, 878 &sa,
752 .sin_addr = pi.ipi_addr 879 sizeof (sa));
753 }; 880 /* For sources we discovered by reading,
754 881 force the generation far into the future */
755 src = find_source (plugin, 882 src->scan_generation = plugin->scan_generation + 60;
756 &sa,
757 sizeof (sa));
758 }
759 break;
760 } 883 }
761 else 884 break;
762 GNUNET_break (0);
763 } 885 }
764 if ( (cmsg->cmsg_level == IPPROTO_IPV6) && 886 else
765 (cmsg->cmsg_type == IPV6_RECVPKTINFO) ) 887 GNUNET_break (0);
888 }
889 if ( (cmsg->cmsg_level == IPPROTO_IPV6) &&
890 (cmsg->cmsg_type == IPV6_PKTINFO) )
891 {
892 if (CMSG_LEN (sizeof (struct in6_pktinfo)) ==
893 cmsg->cmsg_len)
766 { 894 {
767 if (CMSG_LEN (sizeof (struct in6_pktinfo)) == 895 struct in6_pktinfo pi;
768 cmsg->cmsg_len) 896
897 memcpy (&pi,
898 CMSG_DATA (cmsg),
899 sizeof (pi));
769 { 900 {
770 struct in6_pktinfo pi; 901 struct sockaddr_in6 sa = {
771 902 .sin6_family = AF_INET6,
772 memcpy (&pi, 903 .sin6_addr = pi.ipi6_addr,
773 CMSG_DATA (cmsg), 904 .sin6_port = htons (plugin->port16),
774 sizeof (pi)); 905 .sin6_scope_id = pi.ipi6_ifindex
775 { 906 };
776 struct sockaddr_in6 sa = { 907
777 .sin6_family = AF_INET6, 908 src = find_source (plugin,
778 .sin6_addr = pi.ipi6_addr, 909 &sa,
779 .sin6_scope_id = pi.ipi6_ifindex 910 sizeof (sa));
780 }; 911 /* For sources we discovered by reading,
781 912 force the generation far into the future */
782 src = find_source (plugin, 913 src->scan_generation = plugin->scan_generation + 60;
783 &sa, 914 break;
784 sizeof (sa));
785 break;
786 }
787 } 915 }
788 else
789 GNUNET_break (0);
790 } 916 }
791 } 917 else
792 dst = find_target (plugin, 918 GNUNET_break (0);
793 &sa,
794 mh.msg_namelen);
795 if ( (NULL == src) ||
796 (NULL == dst) )
797 {
798 GNUNET_break (0);
799 }
800 else
801 {
802 plugin->env->receive_cb (plugin->env->cls,
803 dst->app_ctx,
804 src->app_ctx,
805 buf,
806 ret);
807 } 919 }
808 } 920 }
809 plugin->read_task = GNUNET_SCHEDULER_add_read_net ( 921 if (NULL == src)
810 GNUNET_TIME_UNIT_FOREVER_REL, 922 {
811 plugin->sock, 923 GNUNET_break (0);
812 &read_cb, 924 return;
813 plugin); 925 }
926 pid = (const struct GNUNET_PeerIdentity *) buf;
927 dst = find_target (plugin,
928 pid,
929 &sa,
930 mh.msg_namelen);
931 if (NULL == dst)
932 {
933 GNUNET_break (0);
934 return;
935 }
936 plugin->env->receive_cb (plugin->env->cls,
937 &dst->app_ctx,
938 &src->app_ctx,
939 &buf[sizeof(*pid)],
940 ret - sizeof (*pid));
814} 941}
815 942
816 943
@@ -874,6 +1001,14 @@ libgnunet_plugin_dhtu_ip_init (void *cls)
874 plugin = GNUNET_new (struct Plugin); 1001 plugin = GNUNET_new (struct Plugin);
875 plugin->env = env; 1002 plugin->env = env;
876 plugin->port = port; 1003 plugin->port = port;
1004 plugin->port16 = (uint16_t) nport;
1005 if (GNUNET_OK !=
1006 GNUNET_CRYPTO_get_peer_identity (env->cfg,
1007 &plugin->my_id))
1008 {
1009 GNUNET_free (plugin);
1010 return NULL;
1011 }
877 af = AF_INET6; 1012 af = AF_INET6;
878 sock = socket (af, 1013 sock = socket (af,
879 SOCK_DGRAM, 1014 SOCK_DGRAM,
@@ -1017,9 +1152,18 @@ libgnunet_plugin_dhtu_ip_done (void *cls)
1017 GNUNET_free (src->address); 1152 GNUNET_free (src->address);
1018 GNUNET_free (src); 1153 GNUNET_free (src);
1019 } 1154 }
1155 plugin->env->network_size_cb (plugin->env->cls,
1156 GNUNET_TIME_UNIT_FOREVER_ABS,
1157 0.0,
1158 0.0);
1020 GNUNET_CONTAINER_multihashmap_destroy (plugin->dsts); 1159 GNUNET_CONTAINER_multihashmap_destroy (plugin->dsts);
1160 if (NULL != plugin->read_task)
1161 {
1162 GNUNET_SCHEDULER_cancel (plugin->read_task);
1163 plugin->read_task = NULL;
1164 }
1021 GNUNET_SCHEDULER_cancel (plugin->scan_task); 1165 GNUNET_SCHEDULER_cancel (plugin->scan_task);
1022 GNUNET_break (0 == 1166 GNUNET_break (GNUNET_OK ==
1023 GNUNET_NETWORK_socket_close (plugin->sock)); 1167 GNUNET_NETWORK_socket_close (plugin->sock));
1024 GNUNET_free (plugin->port); 1168 GNUNET_free (plugin->port);
1025 GNUNET_free (plugin); 1169 GNUNET_free (plugin);
diff --git a/src/dns/plugin_block_dns.c b/src/dns/plugin_block_dns.c
index d3eb7d2b9..a596beb28 100644
--- a/src/dns/plugin_block_dns.c
+++ b/src/dns/plugin_block_dns.c
@@ -90,93 +90,6 @@ block_plugin_dns_create_group (void *cls,
90 90
91 91
92/** 92/**
93 * Function called to validate a reply or a request. For
94 * request evaluation, simply pass "NULL" for the reply_block.
95 *
96 * @param cls closure
97 * @param ctx block context
98 * @param type block type
99 * @param bg group to evaluate against
100 * @param eo control flags
101 * @param query original query (hash)
102 * @param xquery extended query data (can be NULL, depending on type)
103 * @param xquery_size number of bytes in @a xquery
104 * @param reply_block response to validate
105 * @param reply_block_size number of bytes in @a reply_block
106 * @return characterization of result
107 */
108static enum GNUNET_BLOCK_EvaluationResult
109block_plugin_dns_evaluate (void *cls,
110 struct GNUNET_BLOCK_Context *ctx,
111 enum GNUNET_BLOCK_Type type,
112 struct GNUNET_BLOCK_Group *bg,
113 enum GNUNET_BLOCK_EvaluationOptions eo,
114 const struct GNUNET_HashCode *query,
115 const void *xquery,
116 size_t xquery_size,
117 const void *reply_block,
118 size_t reply_block_size)
119{
120 const struct GNUNET_DNS_Advertisement *ad;
121 struct GNUNET_HashCode phash;
122
123 switch (type)
124 {
125 case GNUNET_BLOCK_TYPE_DNS:
126 if (0 != xquery_size)
127 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
128
129 if (NULL == reply_block)
130 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
131
132 if (sizeof(struct GNUNET_DNS_Advertisement) != reply_block_size)
133 {
134 GNUNET_break_op (0);
135 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
136 }
137 ad = reply_block;
138
139 if (ntohl (ad->purpose.size) !=
140 sizeof(struct GNUNET_DNS_Advertisement)
141 - sizeof(struct GNUNET_CRYPTO_EddsaSignature))
142 {
143 GNUNET_break_op (0);
144 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
145 }
146 if (0 ==
147 GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh
148 (ad->expiration_time)).
149 rel_value_us)
150 {
151 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
152 "DNS advertisement has expired\n");
153 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
154 }
155 if (GNUNET_OK !=
156 GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_DNS_RECORD,
157 &ad->purpose,
158 &ad->signature,
159 &ad->peer.public_key))
160 {
161 GNUNET_break_op (0);
162 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
163 }
164 GNUNET_CRYPTO_hash (reply_block,
165 reply_block_size,
166 &phash);
167 if (GNUNET_YES ==
168 GNUNET_BLOCK_GROUP_bf_test_and_set (bg,
169 &phash))
170 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
171 return GNUNET_BLOCK_EVALUATION_OK_MORE;
172
173 default:
174 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
175 }
176}
177
178
179/**
180 * Function called to validate a query. 93 * Function called to validate a query.
181 * 94 *
182 * @param cls closure 95 * @param cls closure
@@ -198,9 +111,13 @@ block_plugin_dns_check_query (void *cls,
198 { 111 {
199 case GNUNET_BLOCK_TYPE_DNS: 112 case GNUNET_BLOCK_TYPE_DNS:
200 if (0 != xquery_size) 113 if (0 != xquery_size)
201 return GNUNET_NO; 114 {
115 GNUNET_break_op (0);
116 return GNUNET_NO;
117 }
202 return GNUNET_OK; 118 return GNUNET_OK;
203 default: 119 default:
120 GNUNET_break (0);
204 return GNUNET_SYSERR; 121 return GNUNET_SYSERR;
205 } 122 }
206} 123}
@@ -211,17 +128,15 @@ block_plugin_dns_check_query (void *cls,
211 * 128 *
212 * @param cls closure 129 * @param cls closure
213 * @param type block type 130 * @param type block type
214 * @param query key for the block (hash), must match exactly
215 * @param block block data to validate 131 * @param block block data to validate
216 * @param block_size number of bytes in @a block 132 * @param block_size number of bytes in @a block
217 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 133 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
218 */ 134 */
219static enum GNUNET_GenericReturnValue 135static enum GNUNET_GenericReturnValue
220block_plugin_dns_check_block (void *cls, 136block_plugin_dns_check_block (void *cls,
221 enum GNUNET_BLOCK_Type type, 137 enum GNUNET_BLOCK_Type type,
222 const struct GNUNET_HashCode *query, 138 const void *block,
223 const void *block, 139 size_t block_size)
224 size_t block_size)
225{ 140{
226 const struct GNUNET_DNS_Advertisement *ad; 141 const struct GNUNET_DNS_Advertisement *ad;
227 142
@@ -260,6 +175,7 @@ block_plugin_dns_check_block (void *cls,
260 } 175 }
261 return GNUNET_OK; 176 return GNUNET_OK;
262 default: 177 default:
178 GNUNET_break (0);
263 return GNUNET_SYSERR; 179 return GNUNET_SYSERR;
264 } 180 }
265} 181}
@@ -283,14 +199,14 @@ block_plugin_dns_check_block (void *cls,
283 */ 199 */
284static enum GNUNET_BLOCK_ReplyEvaluationResult 200static enum GNUNET_BLOCK_ReplyEvaluationResult
285block_plugin_dns_check_reply ( 201block_plugin_dns_check_reply (
286 void *cls, 202 void *cls,
287 enum GNUNET_BLOCK_Type type, 203 enum GNUNET_BLOCK_Type type,
288 struct GNUNET_BLOCK_Group *group, 204 struct GNUNET_BLOCK_Group *group,
289 const struct GNUNET_HashCode *query, 205 const struct GNUNET_HashCode *query,
290 const void *xquery, 206 const void *xquery,
291 size_t xquery_size, 207 size_t xquery_size,
292 const void *reply_block, 208 const void *reply_block,
293 size_t reply_block_size) 209 size_t reply_block_size)
294{ 210{
295 struct GNUNET_HashCode phash; 211 struct GNUNET_HashCode phash;
296 212
@@ -306,6 +222,7 @@ block_plugin_dns_check_reply (
306 return GNUNET_BLOCK_REPLY_OK_DUPLICATE; 222 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
307 return GNUNET_BLOCK_REPLY_OK_MORE; 223 return GNUNET_BLOCK_REPLY_OK_MORE;
308 default: 224 default:
225 GNUNET_break (0);
309 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED; 226 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
310 } 227 }
311} 228}
@@ -329,8 +246,12 @@ block_plugin_dns_get_key (void *cls,
329 size_t block_size, 246 size_t block_size,
330 struct GNUNET_HashCode *key) 247 struct GNUNET_HashCode *key)
331{ 248{
332 /* we cannot extract a key from a block of this type */ 249 if (GNUNET_BLOCK_TYPE_DNS != type)
333 return GNUNET_SYSERR; 250 {
251 GNUNET_break (0);
252 return GNUNET_SYSERR;
253 }
254 return GNUNET_NO;
334} 255}
335 256
336 257
@@ -347,7 +268,6 @@ libgnunet_plugin_block_dns_init (void *cls)
347 struct GNUNET_BLOCK_PluginFunctions *api; 268 struct GNUNET_BLOCK_PluginFunctions *api;
348 269
349 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 270 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
350 api->evaluate = &block_plugin_dns_evaluate;
351 api->get_key = &block_plugin_dns_get_key; 271 api->get_key = &block_plugin_dns_get_key;
352 api->check_query = &block_plugin_dns_check_query; 272 api->check_query = &block_plugin_dns_check_query;
353 api->check_block = &block_plugin_dns_check_block; 273 api->check_block = &block_plugin_dns_check_block;
diff --git a/src/fs/fs_file_information.c b/src/fs/fs_file_information.c
index 3324abd58..c5faa14d4 100644
--- a/src/fs/fs_file_information.c
+++ b/src/fs/fs_file_information.c
@@ -57,7 +57,7 @@ GNUNET_FS_file_information_get_id (struct GNUNET_FS_FileInformation *s)
57 * @return "filename" field of the structure (can be NULL) 57 * @return "filename" field of the structure (can be NULL)
58 */ 58 */
59const char * 59const char *
60GNUNET_FS_file_information_get_filename (struct GNUNET_FS_FileInformation *s) 60GNUNET_FS_file_information_get_filename (const struct GNUNET_FS_FileInformation *s)
61{ 61{
62 return s->filename; 62 return s->filename;
63} 63}
diff --git a/src/fs/fs_uri.c b/src/fs/fs_uri.c
index 73ea5d60d..2d5566b54 100644
--- a/src/fs/fs_uri.c
+++ b/src/fs/fs_uri.c
@@ -653,18 +653,24 @@ GNUNET_FS_uri_parse (const char *uri, char **emsg)
653 *emsg = GNUNET_strdup (_ ("invalid argument")); 653 *emsg = GNUNET_strdup (_ ("invalid argument"));
654 return NULL; 654 return NULL;
655 } 655 }
656 if (NULL == emsg) 656 /**
657 emsg = &msg; 657 * FIXME: Do we want to log this?
658 *emsg = NULL; 658 */
659 if ((NULL != (ret = uri_chk_parse (uri, emsg))) || 659 msg = NULL;
660 (NULL != (ret = uri_ksk_parse (uri, emsg))) || 660 if (NULL != (ret = uri_chk_parse (uri, &msg)))
661 (NULL != (ret = uri_sks_parse (uri, emsg))) || 661 return ret;
662 (NULL != (ret = uri_loc_parse (uri, emsg)))) 662 GNUNET_free (msg);
663 if (NULL != (ret = uri_ksk_parse (uri, &msg)))
664 return ret;
665 GNUNET_free (msg);
666 if (NULL != (ret = uri_sks_parse (uri, &msg)))
667 return ret;
668 GNUNET_free (msg);
669 if (NULL != (ret = uri_loc_parse (uri, &msg)))
663 return ret; 670 return ret;
664 if (NULL == *emsg) 671 GNUNET_free (msg);
672 if (NULL != emsg)
665 *emsg = GNUNET_strdup (_ ("Unrecognized URI type")); 673 *emsg = GNUNET_strdup (_ ("Unrecognized URI type"));
666 if (emsg == &msg)
667 GNUNET_free (msg);
668 return NULL; 674 return NULL;
669} 675}
670 676
diff --git a/src/fs/gnunet-search.c b/src/fs/gnunet-search.c
index 3bf013650..7e2e4d2a6 100644
--- a/src/fs/gnunet-search.c
+++ b/src/fs/gnunet-search.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V. 3 Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -24,10 +24,57 @@
24 * @author Krista Bennett 24 * @author Krista Bennett
25 * @author James Blackwell 25 * @author James Blackwell
26 * @author Igor Wronsky 26 * @author Igor Wronsky
27 * @author madmurphy
27 */ 28 */
29#include <ctype.h>
30#include <inttypes.h>
31#include <limits.h>
28#include "platform.h" 32#include "platform.h"
29#include "gnunet_fs_service.h" 33#include "gnunet_fs_service.h"
30 34
35
36#define GNUNET_SEARCH_log(kind, ...) \
37 GNUNET_log_from(kind, "gnunet-search", __VA_ARGS__)
38
39
40/* The default settings that we use for the printed output */
41
42#define DEFAULT_DIR_FORMAT "#%n:\ngnunet-download -o \"%f\" -R %u\n\n"
43#define HELP_DEFAULT_DIR_FORMAT "#%n:\\ngnunet-download -o \"%f\" -R %u\\n\\n"
44#define DEFAULT_FILE_FORMAT "#%n:\ngnunet-download -o \"%f\" %u\n\n"
45#define HELP_DEFAULT_FILE_FORMAT "#%n:\\ngnunet-download -o \"%f\" %u\\n\\n"
46#define VERB_DEFAULT_DIR_FORMAT DEFAULT_DIR_FORMAT "%a\n"
47#define VERB_DEFAULT_FILE_FORMAT DEFAULT_FILE_FORMAT "%a\n"
48
49#if HAVE_LIBEXTRACTOR
50#define DEFAULT_META_FORMAT " %t: %p\n"
51#define HELP_DEFAULT_META_FORMAT " %t: %p\\n"
52#define HELP_EXTRACTOR_TEXTADD ", %t"
53#else
54#define DEFAULT_META_FORMAT " MetaType #%i: %p\n"
55#define HELP_DEFAULT_META_FORMAT " MetaType #%i: %p\\n"
56#define HELP_EXTRACTOR_TEXTADD ""
57#endif
58
59#define GENERIC_DIRECTORY_NAME "collection"
60#define GENERIC_FILE_NAME "no-name"
61#define GENERIC_FILE_MIMETYPE "application/octet-stream"
62
63
64enum GNUNET_SEARCH_MetadataPrinterFlags {
65 METADATA_PRINTER_FLAG_NONE = 0,
66 METADATA_PRINTER_FLAG_ONE_RUN = 1,
67 METADATA_PRINTER_FLAG_HAVE_TYPE = 2
68};
69
70
71struct GNUNET_SEARCH_MetadataPrinterInfo {
72 unsigned int counter;
73 unsigned int flags;
74 int type;
75};
76
77
31static int ret; 78static int ret;
32 79
33static const struct GNUNET_CONFIGURATION_Handle *cfg; 80static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -38,6 +85,12 @@ static struct GNUNET_FS_SearchContext *sc;
38 85
39static char *output_filename; 86static char *output_filename;
40 87
88static char *format_string;
89
90static char *dir_format_string;
91
92static char *meta_format_string;
93
41static struct GNUNET_FS_DirectoryBuilder *db; 94static struct GNUNET_FS_DirectoryBuilder *db;
42 95
43static unsigned int anonymity = 1; 96static unsigned int anonymity = 1;
@@ -53,16 +106,79 @@ static unsigned int results;
53 106
54static unsigned int verbose; 107static unsigned int verbose;
55 108
109static int bookmark_only;
110
56static int local_only; 111static int local_only;
57 112
113static int silent_mode;
114
58static struct GNUNET_SCHEDULER_Task *tt; 115static struct GNUNET_SCHEDULER_Task *tt;
59 116
60 117
61/** 118/**
119 * Print the escape sequence at the beginning of a string.
120 *
121 * @param esc a string that **must** begin with a backslash (the function only
122 * assumes that it does, but does not check)
123 * @return the fragment that follows what has been printed
124 * @author madmurphy
125 *
126 * If `"\\nfoo"` is passed as argument, this function prints a new line and
127 * returns `"foo"`
128 */
129static const char *
130print_escape_sequence (const char *const esc)
131{
132 unsigned int probe;
133 const char * cursor = esc + 1;
134 char tmp;
135 switch (*cursor)
136 {
137 /* Trivia */
138 case '\\': putchar ('\\'); return cursor + 1;
139 case 'a': putchar ('\a'); return cursor + 1;
140 case 'b': putchar ('\b'); return cursor + 1;
141 case 'e': putchar ('\x1B'); return cursor + 1;
142 case 'f': putchar ('\f'); return cursor + 1;
143 case 'n': putchar ('\n'); return cursor + 1;
144 case 'r': putchar ('\r'); return cursor + 1;
145 case 't': putchar ('\t'); return cursor + 1;
146 case 'v': putchar ('\v'); return cursor + 1;
147
148 /* Possibly hexadecimal code point */
149 case 'x':
150 probe = 0;
151 while (probe < 256 && isxdigit((tmp = *++cursor)))
152 probe = (probe << 4) + tmp - (tmp > 96 ? 87 : tmp > 64 ? 55 : 48);
153 goto maybe_codepoint;
154
155 /* Possibly octal code point */
156 case '0': case '1': case '2': case '3':
157 case '4': case '5': case '6': case '7':
158 probe = *cursor++ - 48;
159 do probe = (probe << 3) + *cursor++ - 48;
160 while (probe < 256 && cursor < esc + 4 && *cursor > 47 && *cursor < 56);
161 goto maybe_codepoint;
162
163 /* Boredom */
164 case '\0': putchar ('\\'); return cursor;
165 default: printf ("\\%c", *cursor); return cursor + 1;
166 }
167
168maybe_codepoint:
169 if (probe < 256)
170 putchar (probe);
171 else
172 fwrite (esc, 1, cursor - esc, stdout);
173 return cursor;
174}
175
176
177/**
62 * Type of a function that libextractor calls for each 178 * Type of a function that libextractor calls for each
63 * meta data item found. 179 * meta data item found.
64 * 180 *
65 * @param cls closure (user-defined, unused) 181 * @param cls closure (user-defined, used for the iteration info)
66 * @param plugin_name name of the plugin that produced this value; 182 * @param plugin_name name of the plugin that produced this value;
67 * special values can be used (e.g. '&lt;zlib&gt;' for zlib being 183 * special values can be used (e.g. '&lt;zlib&gt;' for zlib being
68 * used in the main libextractor library and yielding 184 * used in the main libextractor library and yielding
@@ -76,33 +192,228 @@ static struct GNUNET_SCHEDULER_Task *tt;
76 * @return 0 to continue extracting, 1 to abort 192 * @return 0 to continue extracting, 1 to abort
77 */ 193 */
78static int 194static int
79item_printer (void *cls, 195item_printer (void *const cls,
80 const char *plugin_name, 196 const char *const plugin_name,
81 enum EXTRACTOR_MetaType type, 197 const enum EXTRACTOR_MetaType type,
82 enum EXTRACTOR_MetaFormat format, 198 const enum EXTRACTOR_MetaFormat format,
83 const char *data_mime_type, 199 const char *const data_mime_type,
84 const char *data, 200 const char *const data,
85 size_t data_size) 201 const size_t data_size)
86{ 202{
87 if ((format != EXTRACTOR_METAFORMAT_UTF8) && 203#define info ((struct GNUNET_SEARCH_MetadataPrinterInfo *) cls)
88 (format != EXTRACTOR_METAFORMAT_C_STRING)) 204 if ((format != EXTRACTOR_METAFORMAT_UTF8 &&
205 format != EXTRACTOR_METAFORMAT_C_STRING) ||
206 type == EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME)
89 return 0; 207 return 0;
90 if (type == EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME) 208 info->counter++;
209 if ((info->flags & METADATA_PRINTER_FLAG_HAVE_TYPE) && type != info->type)
91 return 0; 210 return 0;
211
212 const char *cursor = meta_format_string;
213 const char *next_spec = strchr(cursor, '%');
214 const char *next_esc = strchr(cursor, '\\');
215
216parse_format:
217
218 /* If an escape sequence exists before the next format specifier... */
219 if (next_esc && (!next_spec || next_esc < next_spec))
220 {
221 if (next_esc > cursor)
222 fwrite (cursor, 1, next_esc - cursor, stdout);
223
224 cursor = print_escape_sequence (next_esc);
225 next_esc = strchr(cursor, '\\');
226 goto parse_format;
227 }
228
229 /* If a format specifier exists before the next escape sequence... */
230 if (next_spec && (!next_esc || next_spec < next_esc))
231 {
232 if (next_spec > cursor)
233 fwrite (cursor, 1, next_spec - cursor, stdout);
234
235 switch (*++next_spec)
236 {
237 case '%': putchar('%'); break;
238 case 'i': printf ("%d", type); break;
239 case 'l': printf ("%lu", (long unsigned int) data_size); break;
240 case 'n': printf ("%u", info->counter); break;
241 case 'p': printf ("%s", data); break;
92#if HAVE_LIBEXTRACTOR 242#if HAVE_LIBEXTRACTOR
93 printf ("\t%20s: %s\n", 243 case 't':
94 dgettext (LIBEXTRACTOR_GETTEXT_DOMAIN, 244 printf ("%s",
95 EXTRACTOR_metatype_to_string (type)), 245 dgettext (LIBEXTRACTOR_GETTEXT_DOMAIN,
96 data); 246 EXTRACTOR_metatype_to_string (type)));
97#else 247 break;
98 printf ("\t%20d: %s\n", type, data);
99#endif 248#endif
100 return 0; 249 case 'w': printf ("%s", plugin_name); break;
250 case '\0': putchar('%'); return 0;
251 default: printf ("%%%c", *next_spec); break;
252 }
253 cursor = next_spec + 1;
254 next_spec = strchr(cursor, '%');
255 goto parse_format;
256 }
257
258 if (*cursor)
259 printf ("%s", cursor);
260
261 return info->flags & METADATA_PRINTER_FLAG_ONE_RUN;
262#undef info
263}
264
265
266/**
267 * Print a search result according to the current formats
268 *
269 * @param filename the filename for this result
270 * @param uri the `struct GNUNET_FS_Uri` this result refers to
271 * @param metadata the `struct GNUNET_CONTAINER_MetaData` associated with this
272 result
273 * @param resultnum the result number
274 * @param is_directory GNUNET_YES if this is a directory, otherwise GNUNET_NO
275 * @author madmurphy
276 */
277static void
278print_search_result (const char *const filename,
279 const struct GNUNET_FS_Uri *const uri,
280 const struct GNUNET_CONTAINER_MetaData *const metadata,
281 const unsigned int resultnum,
282 const int is_directory)
283{
284
285 const char *cursor = GNUNET_YES == is_directory ?
286 dir_format_string
287 : format_string;
288
289 const char *next_spec = strchr(cursor, '%');
290 const char *next_esc = strchr(cursor, '\\');
291 char *placeholder;
292 struct GNUNET_SEARCH_MetadataPrinterInfo info;
293
294parse_format:
295 /* If an escape sequence exists before the next format specifier... */
296 if (next_esc && (!next_spec || next_esc < next_spec))
297 {
298 if (next_esc > cursor)
299 fwrite (cursor, 1, next_esc - cursor, stdout);
300
301 cursor = print_escape_sequence (next_esc);
302 next_esc = strchr(cursor, '\\');
303 goto parse_format;
304 }
305
306 /* If a format specifier exists before the next escape sequence... */
307 if (next_spec && (!next_esc || next_spec < next_esc))
308 {
309 if (next_spec > cursor)
310 fwrite (cursor, 1, next_spec - cursor, stdout);
311
312 switch (*++next_spec)
313 {
314 /* All metadata fields */
315 case 'a':
316 info.flags = METADATA_PRINTER_FLAG_NONE;
317
318iterate_meta:
319 info.counter = 0;
320 GNUNET_CONTAINER_meta_data_iterate (metadata, &item_printer, &info);
321 break;
322 /* File's name */
323 case 'f':
324 if (GNUNET_YES == is_directory)
325 {
326 printf ("%s%s", filename, GNUNET_FS_DIRECTORY_EXT);
327 break;
328 }
329 printf ("%s", filename);
330 break;
331 /* Only the first metadata field */
332 case 'j':
333 info.flags = METADATA_PRINTER_FLAG_ONE_RUN;
334 goto iterate_meta;
335 /* File name's length */
336 case 'l':
337 printf ("%lu",
338 (long unsigned int) ( GNUNET_YES == is_directory ?
339 strlen(filename) +
340 (sizeof(GNUNET_FS_DIRECTORY_EXT) - 1)
341 :
342 strlen(filename)));
343 break;
344 /* File's mime type */
345 case 'm':
346 if (GNUNET_YES == is_directory)
347 {
348 printf ("%s", GNUNET_FS_DIRECTORY_MIME);
349 break;
350 }
351 placeholder = GNUNET_CONTAINER_meta_data_get_by_type (
352 metadata,
353 EXTRACTOR_METATYPE_MIMETYPE);
354 printf ("%s", placeholder ? placeholder : GENERIC_FILE_MIMETYPE);
355 GNUNET_free (placeholder);
356 break;
357 /* Result number */
358 case 'n': printf ("%u", resultnum); break;
359 /* File's size */
360 case 's':
361 printf ("%" PRIu64, GNUNET_FS_uri_chk_get_file_size (uri));
362 break;
363 /* File's URI */
364 case 'u':
365 placeholder = GNUNET_FS_uri_to_string (uri);
366 printf ("%s", placeholder);
367 GNUNET_free (placeholder);
368 break;
369
370 /* We can add as many cases as we want here... */
371
372 /* Handle `%123#a` and `%123#j` (e.g. `%5#j` is a book title) */
373 case '0': case '1': case '2': case '3': case '4':
374 case '5': case '6': case '7': case '8': case '9':
375 cursor = next_spec;
376 info.type = *cursor - 48;
377 while (isdigit(*++cursor) && info.type < (INT_MAX - *cursor + 48) / 10)
378 info.type = info.type * 10 + *cursor - 48;
379 if (info.type == 0 || *cursor != '#')
380 goto not_a_specifier;
381 switch (*++cursor)
382 {
383 /* All metadata fields of type `info.type` */
384 case 'a':
385 next_spec = cursor;
386 info.flags = METADATA_PRINTER_FLAG_HAVE_TYPE;
387 goto iterate_meta;
388
389 /* Only the first metadata field of type `info.type` */
390 case 'j':
391 next_spec = cursor;
392 info.flags = METADATA_PRINTER_FLAG_HAVE_TYPE |
393 METADATA_PRINTER_FLAG_ONE_RUN;
394 goto iterate_meta;
395 }
396 goto not_a_specifier;
397
398 /* All other cases */
399 case '%': putchar('%'); break;
400 case '\0': putchar('%'); return;
401
402not_a_specifier:
403 default: printf ("%%%c", *next_spec); break;
404 }
405 cursor = next_spec + 1;
406 next_spec = strchr(cursor, '%');
407 goto parse_format;
408 }
409
410 if (*cursor)
411 printf ("%s", cursor);
101} 412}
102 413
103 414
104static void 415static void
105clean_task (void *cls) 416clean_task (void *const cls)
106{ 417{
107 size_t dsize; 418 size_t dsize;
108 void *ddata; 419 void *ddata;
@@ -126,9 +437,10 @@ clean_task (void *cls)
126 GNUNET_DISK_PERM_USER_READ 437 GNUNET_DISK_PERM_USER_READ
127 | GNUNET_DISK_PERM_USER_WRITE)) 438 | GNUNET_DISK_PERM_USER_WRITE))
128 { 439 {
129 fprintf (stderr, 440 GNUNET_SEARCH_log(GNUNET_ERROR_TYPE_ERROR,
130 _ ("Failed to write directory with search results to `%s'\n"), 441 _ ("Failed to write directory with search results to "
131 output_filename); 442 "`%s'\n"),
443 output_filename);
132 } 444 }
133 GNUNET_free (ddata); 445 GNUNET_free (ddata);
134 GNUNET_free (output_filename); 446 GNUNET_free (output_filename);
@@ -149,11 +461,11 @@ clean_task (void *cls)
149 * field in the GNUNET_FS_ProgressInfo struct. 461 * field in the GNUNET_FS_ProgressInfo struct.
150 */ 462 */
151static void * 463static void *
152progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) 464progress_cb (void *const cls,
465 const struct GNUNET_FS_ProgressInfo *const info)
153{ 466{
154 static unsigned int cnt; 467 static unsigned int cnt;
155 int is_directory; 468 int is_directory;
156 char *uri;
157 char *filename; 469 char *filename;
158 470
159 switch (info->status) 471 switch (info->status)
@@ -162,13 +474,17 @@ progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info)
162 break; 474 break;
163 475
164 case GNUNET_FS_STATUS_SEARCH_RESULT: 476 case GNUNET_FS_STATUS_SEARCH_RESULT:
477 if (silent_mode)
478 break;
479
165 if (db != NULL) 480 if (db != NULL)
166 GNUNET_FS_directory_builder_add (db, 481 GNUNET_FS_directory_builder_add (
167 info->value.search.specifics.result.uri, 482 db,
168 info->value.search.specifics.result.meta, 483 info->value.search.specifics.result.uri,
169 NULL); 484 info->value.search.specifics.result.meta,
170 uri = GNUNET_FS_uri_to_string (info->value.search.specifics.result.uri); 485 NULL);
171 printf ("#%u:\n", ++cnt); 486
487 cnt++;
172 filename = GNUNET_CONTAINER_meta_data_get_by_type ( 488 filename = GNUNET_CONTAINER_meta_data_get_by_type (
173 info->value.search.specifics.result.meta, 489 info->value.search.specifics.result.meta,
174 EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); 490 EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME);
@@ -179,45 +495,37 @@ progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info)
179 while ((filename[0] != '\0') && ('/' == filename[strlen (filename) - 1])) 495 while ((filename[0] != '\0') && ('/' == filename[strlen (filename) - 1]))
180 filename[strlen (filename) - 1] = '\0'; 496 filename[strlen (filename) - 1] = '\0';
181 GNUNET_DISK_filename_canonicalize (filename); 497 GNUNET_DISK_filename_canonicalize (filename);
182 if (GNUNET_YES == is_directory)
183 printf ("gnunet-download -o \"%s%s\" -R %s\n",
184 filename,
185 GNUNET_FS_DIRECTORY_EXT,
186 uri);
187 else
188 printf ("gnunet-download -o \"%s\" %s\n", filename, uri);
189 } 498 }
190 else if (GNUNET_YES == is_directory) 499 print_search_result ( filename ?
191 printf ("gnunet-download -o \"collection%s\" -R %s\n", 500 filename
192 GNUNET_FS_DIRECTORY_EXT, 501 : is_directory ?
193 uri); 502 GENERIC_DIRECTORY_NAME
194 else 503 :
195 printf ("gnunet-download %s\n", uri); 504 GENERIC_FILE_NAME,
196 if (verbose) 505 info->value.search.specifics.result.uri,
197 GNUNET_CONTAINER_meta_data_iterate (info->value.search.specifics.result 506 info->value.search.specifics.result.meta,
198 .meta, 507 cnt,
199 &item_printer, 508 is_directory);
200 NULL);
201 printf ("\n");
202 fflush (stdout); 509 fflush (stdout);
203 GNUNET_free (filename); 510 GNUNET_free (filename);
204 GNUNET_free (uri);
205 results++; 511 results++;
206 if ((results_limit > 0) && (results >= results_limit)) 512 if ((results_limit > 0) && (results >= results_limit))
513 {
207 GNUNET_SCHEDULER_shutdown (); 514 GNUNET_SCHEDULER_shutdown ();
515 /* otherwise the function might keep printing results for a while... */
516 silent_mode = GNUNET_YES;
517 }
208 break; 518 break;
209 519
210 case GNUNET_FS_STATUS_SEARCH_UPDATE: 520 case GNUNET_FS_STATUS_SEARCH_UPDATE:
211 break;
212
213 case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED: 521 case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED:
214 /* ignore */ 522 /* ignore */
215 break; 523 break;
216 524
217 case GNUNET_FS_STATUS_SEARCH_ERROR: 525 case GNUNET_FS_STATUS_SEARCH_ERROR:
218 fprintf (stderr, 526 GNUNET_SEARCH_log(GNUNET_ERROR_TYPE_ERROR,
219 _ ("Error searching: %s.\n"), 527 _ ("Error searching: %s.\n"),
220 info->value.search.specifics.error.message); 528 info->value.search.specifics.error.message);
221 GNUNET_SCHEDULER_shutdown (); 529 GNUNET_SCHEDULER_shutdown ();
222 break; 530 break;
223 531
@@ -226,7 +534,9 @@ progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info)
226 break; 534 break;
227 535
228 default: 536 default:
229 fprintf (stderr, _ ("Unexpected status: %d\n"), info->status); 537 GNUNET_SEARCH_log(GNUNET_ERROR_TYPE_ERROR,
538 _ ("Unexpected status: %d\n"),
539 info->status);
230 break; 540 break;
231 } 541 }
232 return NULL; 542 return NULL;
@@ -234,7 +544,7 @@ progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info)
234 544
235 545
236static void 546static void
237shutdown_task (void *cls) 547shutdown_task (void *const cls)
238{ 548{
239 if (sc != NULL) 549 if (sc != NULL)
240 { 550 {
@@ -245,9 +555,10 @@ shutdown_task (void *cls)
245 555
246 556
247static void 557static void
248timeout_task (void *cls) 558timeout_task (void *const cls)
249{ 559{
250 tt = NULL; 560 tt = NULL;
561 silent_mode = GNUNET_YES;
251 GNUNET_SCHEDULER_shutdown (); 562 GNUNET_SCHEDULER_shutdown ();
252} 563}
253 564
@@ -258,18 +569,47 @@ timeout_task (void *cls)
258 * @param cls closure 569 * @param cls closure
259 * @param args remaining command-line arguments 570 * @param args remaining command-line arguments
260 * @param cfgfile name of the configuration file used (for saving, can be NULL!) 571 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
261 * @param c configuration 572 * @param cfgarg configuration
262 */ 573 */
263static void 574static void
264run (void *cls, 575run (void *const cls,
265 char *const *args, 576 char *const *const args,
266 const char *cfgfile, 577 const char *const cfgfile,
267 const struct GNUNET_CONFIGURATION_Handle *c) 578 const struct GNUNET_CONFIGURATION_Handle *const cfgarg)
268{ 579{
269 struct GNUNET_FS_Uri *uri; 580 struct GNUNET_FS_Uri *uri;
270 unsigned int argc; 581 unsigned int argc;
271 enum GNUNET_FS_SearchOptions options; 582 enum GNUNET_FS_SearchOptions options;
272 583
584 if (silent_mode && bookmark_only)
585 {
586 fprintf (stderr,
587 _ ("Conflicting options --bookmark-only and --silent.\n"));
588 ret = 1;
589 return;
590 }
591 if (bookmark_only && output_filename)
592 {
593 fprintf (stderr,
594 _ ("Conflicting options --bookmark-only and --output.\n"));
595 ret = 1;
596 return;
597 }
598 if (silent_mode && !output_filename)
599 {
600 fprintf (stderr, _ ("An output file is mandatory for silent mode.\n"));
601 ret = 1;
602 return;
603 }
604 if (NULL == dir_format_string)
605 dir_format_string = format_string ? format_string
606 : verbose ? VERB_DEFAULT_DIR_FORMAT
607 : DEFAULT_DIR_FORMAT;
608 if (NULL == format_string)
609 format_string = verbose ? VERB_DEFAULT_FILE_FORMAT
610 : DEFAULT_FILE_FORMAT;
611 if (NULL == meta_format_string)
612 meta_format_string = DEFAULT_META_FORMAT;
273 argc = 0; 613 argc = 0;
274 while (NULL != args[argc]) 614 while (NULL != args[argc])
275 argc++; 615 argc++;
@@ -282,7 +622,27 @@ run (void *cls,
282 ret = 1; 622 ret = 1;
283 return; 623 return;
284 } 624 }
285 cfg = c; 625 if (!GNUNET_FS_uri_test_ksk (uri) && !GNUNET_FS_uri_test_sks (uri))
626 {
627 fprintf (stderr,
628 "%s",
629 _ ("Invalid URI. Valid URIs for searching are keyword query "
630 "URIs\n(\"gnunet://fs/ksk/...\") and namespace content URIs "
631 "(\"gnunet://fs/sks/...\").\n"));
632 GNUNET_FS_uri_destroy (uri);
633 ret = 1;
634 return;
635 }
636 if (bookmark_only)
637 {
638 char * bmstr = GNUNET_FS_uri_to_string (uri);
639 printf ("%s\n", bmstr);
640 GNUNET_free (bmstr);
641 GNUNET_FS_uri_destroy (uri);
642 ret = 0;
643 return;
644 }
645 cfg = cfgarg;
286 ctx = GNUNET_FS_start (cfg, 646 ctx = GNUNET_FS_start (cfg,
287 "gnunet-search", 647 "gnunet-search",
288 &progress_cb, 648 &progress_cb,
@@ -291,7 +651,7 @@ run (void *cls,
291 GNUNET_FS_OPTIONS_END); 651 GNUNET_FS_OPTIONS_END);
292 if (NULL == ctx) 652 if (NULL == ctx)
293 { 653 {
294 fprintf (stderr, _ ("Could not initialize `%s' subsystem.\n"), "FS"); 654 fprintf (stderr, _ ("Could not initialize the `%s` subsystem.\n"), "FS");
295 GNUNET_FS_uri_destroy (uri); 655 GNUNET_FS_uri_destroy (uri);
296 ret = 1; 656 ret = 1;
297 return; 657 return;
@@ -321,18 +681,59 @@ run (void *cls,
321 * 681 *
322 * @param argc number of arguments from the command line 682 * @param argc number of arguments from the command line
323 * @param argv command line arguments 683 * @param argv command line arguments
324 * @return 0 ok, 1 on error 684 * @return 0 ok, an error number on error
325 */ 685 */
326int 686int
327main (int argc, char *const *argv) 687main (int argc, char *const *argv)
328{ 688{
329 struct GNUNET_GETOPT_CommandLineOption options[] = 689 struct GNUNET_GETOPT_CommandLineOption options[] =
330 { GNUNET_GETOPT_option_uint ('a', 690 { GNUNET_GETOPT_option_uint (
331 "anonymity", 691 'a',
332 "LEVEL", 692 "anonymity",
333 gettext_noop ( 693 "LEVEL",
334 "set the desired LEVEL of receiver-anonymity"), 694 gettext_noop ("set the desired LEVEL of receiver-anonymity (default: "
335 &anonymity), 695 "1)"),
696 &anonymity),
697 GNUNET_GETOPT_option_flag (
698 'b',
699 "bookmark-only",
700 gettext_noop ("do not search, print only the URI that points to this "
701 "search"),
702 &bookmark_only),
703 GNUNET_GETOPT_option_string (
704 'F',
705 "dir-printf",
706 "FORMAT",
707 gettext_noop ("write search results for directories according to "
708 "FORMAT; accepted placeholders are: %a, %f, %j, %l, %m, "
709 "%n, %s; defaults to the value of --printf when omitted "
710 "or to `" HELP_DEFAULT_DIR_FORMAT "` if --printf is "
711 "omitted too"),
712 &dir_format_string),
713 GNUNET_GETOPT_option_string (
714 'f',
715 "printf",
716 "FORMAT",
717 gettext_noop ("write search results according to FORMAT; accepted "
718 "placeholders are: %a, %f, %j, %l, %m, %n, %s; defaults "
719 "to `" HELP_DEFAULT_FILE_FORMAT "` when omitted"),
720 &format_string),
721 GNUNET_GETOPT_option_string (
722 'i',
723 "iter-printf",
724 "FORMAT",
725 gettext_noop ("when the %a or %j placeholders appear in --printf or "
726 "--dir-printf, list each metadata property according to "
727 "FORMAT; accepted placeholders are: %i, %l, %n, %p"
728 HELP_EXTRACTOR_TEXTADD ", %w; defaults to `"
729 HELP_DEFAULT_META_FORMAT "` when omitted"),
730 &meta_format_string),
731 GNUNET_GETOPT_option_uint ('N',
732 "results",
733 "VALUE",
734 gettext_noop ("automatically terminate search "
735 "after VALUE results are found"),
736 &results_limit),
336 GNUNET_GETOPT_option_flag ( 737 GNUNET_GETOPT_option_flag (
337 'n', 738 'n',
338 "no-network", 739 "no-network",
@@ -341,39 +742,49 @@ main (int argc, char *const *argv)
341 GNUNET_GETOPT_option_string ( 742 GNUNET_GETOPT_option_string (
342 'o', 743 'o',
343 "output", 744 "output",
344 "PREFIX", 745 "FILENAME",
345 gettext_noop ("write search results to file starting with PREFIX"), 746 gettext_noop ("create a GNUnet directory with search results at "
747 "FILENAME (e.g. `gnunet-search --output=commons"
748 GNUNET_FS_DIRECTORY_EXT " commons`)"),
346 &output_filename), 749 &output_filename),
750 GNUNET_GETOPT_option_flag (
751 's',
752 "silent",
753 gettext_noop ("silent mode (requires the --output argument)"),
754 &silent_mode),
347 GNUNET_GETOPT_option_relative_time ( 755 GNUNET_GETOPT_option_relative_time (
348 't', 756 't',
349 "timeout", 757 "timeout",
350 "DELAY", 758 "DELAY",
351 gettext_noop ("automatically terminate search after DELAY"), 759 gettext_noop ("automatically terminate search after DELAY; the value "
760 "given must be a number followed by a space and a time "
761 "unit, for example \"500 ms\"; without a unit it defaults "
762 "to microseconds - 1000000 = 1 second; if 0 or omitted "
763 "it means to wait for CTRL-C"),
352 &timeout), 764 &timeout),
353 GNUNET_GETOPT_option_verbose (&verbose), 765 GNUNET_GETOPT_option_increment_uint (
354 GNUNET_GETOPT_option_uint ('N', 766 'V',
355 "results", 767 "verbose",
356 "VALUE", 768 gettext_noop ("be verbose (append \"%a\\n\" to the default --printf and "
357 gettext_noop ("automatically terminate search " 769 "--dir-printf arguments - ignored when these are provided "
358 "after VALUE results are found"), 770 "by the user)"),
359 &results_limit), 771 &verbose),
360 GNUNET_GETOPT_OPTION_END }; 772 GNUNET_GETOPT_OPTION_END };
361 773
362 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 774 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
363 return 2; 775 return 12;
364 776
365 ret = 777 if (GNUNET_SYSERR ==
366 (GNUNET_OK == 778 GNUNET_PROGRAM_run (argc,
367 GNUNET_PROGRAM_run (argc, 779 argv,
368 argv, 780 "gnunet-search [OPTIONS] KEYWORD1 KEYWORD2 ...",
369 "gnunet-search [OPTIONS] KEYWORD", 781 gettext_noop ("Search for files that have been "
370 gettext_noop ( 782 "published on GNUnet\n"),
371 "Search GNUnet for files that were published on GNUnet"),
372 options, 783 options,
373 &run, 784 &run,
374 NULL)) 785 NULL))
375 ? ret 786 ret = 1;
376 : 1; 787
377 GNUNET_free_nz ((void *) argv); 788 GNUNET_free_nz ((void *) argv);
378 return ret; 789 return ret;
379} 790}
diff --git a/src/fs/gnunet-service-fs_pr.c b/src/fs/gnunet-service-fs_pr.c
index beb29a506..154c454ca 100644
--- a/src/fs/gnunet-service-fs_pr.c
+++ b/src/fs/gnunet-service-fs_pr.c
@@ -247,7 +247,8 @@ static unsigned long long max_pending_requests = (32 * 1024);
247 * @param pr request for which the BF is to be recomputed 247 * @param pr request for which the BF is to be recomputed
248 */ 248 */
249static void 249static void
250refresh_bloomfilter (enum GNUNET_BLOCK_Type type, struct GSF_PendingRequest *pr) 250refresh_bloomfilter (enum GNUNET_BLOCK_Type type,
251 struct GSF_PendingRequest *pr)
251{ 252{
252 if (NULL != pr->bg) 253 if (NULL != pr->bg)
253 { 254 {
@@ -406,7 +407,7 @@ GSF_pending_request_create_ (enum GSF_PendingRequestOptions options,
406 break; /* let the request live briefly... */ 407 break; /* let the request live briefly... */
407 if (NULL != dpr->rh) 408 if (NULL != dpr->rh)
408 dpr->rh (dpr->rh_cls, 409 dpr->rh (dpr->rh_cls,
409 GNUNET_BLOCK_EVALUATION_REQUEST_VALID, 410 GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED,
410 dpr, 411 dpr,
411 UINT32_MAX, 412 UINT32_MAX,
412 GNUNET_TIME_UNIT_FOREVER_ABS, 413 GNUNET_TIME_UNIT_FOREVER_ABS,
@@ -557,7 +558,10 @@ GSF_pending_request_get_message_ (struct GSF_PendingRequest *pr)
557 k++; 558 k++;
558 } 559 }
559 if (GNUNET_OK != 560 if (GNUNET_OK !=
560 GNUNET_BLOCK_group_serialize (pr->bg, &bf_nonce, &bf_data, &bf_size)) 561 GNUNET_BLOCK_group_serialize (pr->bg,
562 &bf_nonce,
563 &bf_data,
564 &bf_size))
561 { 565 {
562 bf_size = 0; 566 bf_size = 0;
563 bf_data = NULL; 567 bf_data = NULL;
@@ -765,11 +769,6 @@ struct ProcessReplyClosure
765 enum GNUNET_BLOCK_Type type; 769 enum GNUNET_BLOCK_Type type;
766 770
767 /** 771 /**
768 * Control flags for evaluation.
769 */
770 enum GNUNET_BLOCK_EvaluationOptions eo;
771
772 /**
773 * How much was this reply worth to us? 772 * How much was this reply worth to us?
774 */ 773 */
775 uint32_t priority; 774 uint32_t priority;
@@ -850,7 +849,6 @@ process_reply (void *cls,
850 case GNUNET_BLOCK_REPLY_OK_MORE: 849 case GNUNET_BLOCK_REPLY_OK_MORE:
851 update_request_performance_data (prq, pr); 850 update_request_performance_data (prq, pr);
852 break; 851 break;
853
854 case GNUNET_BLOCK_REPLY_OK_LAST: 852 case GNUNET_BLOCK_REPLY_OK_LAST:
855 /* short cut: stop processing early, no BF-update, etc. */ 853 /* short cut: stop processing early, no BF-update, etc. */
856 update_request_performance_data (prq, pr); 854 update_request_performance_data (prq, pr);
@@ -885,7 +883,6 @@ process_reply (void *cls,
885 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
886 "Duplicate response, discarding.\n"); 884 "Duplicate response, discarding.\n");
887 return GNUNET_YES; /* duplicate */ 885 return GNUNET_YES; /* duplicate */
888
889 case GNUNET_BLOCK_REPLY_IRRELEVANT: 886 case GNUNET_BLOCK_REPLY_IRRELEVANT:
890 GNUNET_STATISTICS_update (GSF_stats, 887 GNUNET_STATISTICS_update (GSF_stats,
891 "# irrelevant replies discarded", 888 "# irrelevant replies discarded",
@@ -894,8 +891,6 @@ process_reply (void *cls,
894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
895 "Irrelevant response, ignoring.\n"); 892 "Irrelevant response, ignoring.\n");
896 return GNUNET_YES; 893 return GNUNET_YES;
897 case GNUNET_BLOCK_REPLY_INVALID:
898 return GNUNET_YES;
899 case GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED: 894 case GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED:
900 GNUNET_break (0); /* bad installation? */ 895 GNUNET_break (0); /* bad installation? */
901 return GNUNET_NO; 896 return GNUNET_NO;
@@ -1127,8 +1122,9 @@ handle_dht_reply (void *cls,
1127 prq.expiration); 1122 prq.expiration);
1128 prq.size = size; 1123 prq.size = size;
1129 prq.type = type; 1124 prq.type = type;
1130 prq.eo = GNUNET_BLOCK_EO_NONE; 1125 process_reply (&prq,
1131 process_reply (&prq, key, pr); 1126 key,
1127 pr);
1132 if ((GNUNET_YES == active_to_migration) && 1128 if ((GNUNET_YES == active_to_migration) &&
1133 (GNUNET_NO == test_put_load_too_high (prq.priority))) 1129 (GNUNET_NO == test_put_load_too_high (prq.priority)))
1134 { 1130 {
@@ -1229,6 +1225,15 @@ cadet_reply_proc (void *cls,
1229 struct GNUNET_HashCode query; 1225 struct GNUNET_HashCode query;
1230 1226
1231 pr->cadet_request = NULL; 1227 pr->cadet_request = NULL;
1228 if (GNUNET_OK !=
1229 GNUNET_BLOCK_check_block (GSF_block_ctx,
1230 type,
1231 data,
1232 data_size))
1233 {
1234 GNUNET_break_op (0);
1235 return;
1236 }
1232 if (GNUNET_BLOCK_TYPE_ANY == type) 1237 if (GNUNET_BLOCK_TYPE_ANY == type)
1233 { 1238 {
1234 GNUNET_break (NULL == data); 1239 GNUNET_break (NULL == data);
@@ -1247,7 +1252,11 @@ cadet_reply_proc (void *cls,
1247 return; 1252 return;
1248 } 1253 }
1249 if (GNUNET_YES != 1254 if (GNUNET_YES !=
1250 GNUNET_BLOCK_get_key (GSF_block_ctx, type, data, data_size, &query)) 1255 GNUNET_BLOCK_get_key (GSF_block_ctx,
1256 type,
1257 data,
1258 data_size,
1259 &query))
1251 { 1260 {
1252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1261 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1253 "Failed to derive key for block of type %d\n", 1262 "Failed to derive key for block of type %d\n",
@@ -1268,8 +1277,9 @@ cadet_reply_proc (void *cls,
1268 prq.expiration); 1277 prq.expiration);
1269 prq.size = data_size; 1278 prq.size = data_size;
1270 prq.type = type; 1279 prq.type = type;
1271 prq.eo = GNUNET_BLOCK_EO_NONE; 1280 process_reply (&prq,
1272 process_reply (&prq, &query, pr); 1281 &query,
1282 pr);
1273} 1283}
1274 1284
1275 1285
@@ -1611,7 +1621,11 @@ called_from_on_demand:
1611 prq.expiration = expiration; 1621 prq.expiration = expiration;
1612 prq.size = size; 1622 prq.size = size;
1613 if (GNUNET_OK != 1623 if (GNUNET_OK !=
1614 GNUNET_BLOCK_get_key (GSF_block_ctx, type, data, size, &query)) 1624 GNUNET_BLOCK_get_key (GSF_block_ctx,
1625 type,
1626 data,
1627 size,
1628 &query))
1615 { 1629 {
1616 GNUNET_break (0); 1630 GNUNET_break (0);
1617 GNUNET_DATASTORE_remove (GSF_dsh, 1631 GNUNET_DATASTORE_remove (GSF_dsh,
@@ -1631,8 +1645,9 @@ called_from_on_demand:
1631 prq.anonymity_level = anonymity; 1645 prq.anonymity_level = anonymity;
1632 if ((0 == old_rf) && (0 == pr->public_data.results_found)) 1646 if ((0 == old_rf) && (0 == pr->public_data.results_found))
1633 GSF_update_datastore_delay_ (pr->public_data.start_time); 1647 GSF_update_datastore_delay_ (pr->public_data.start_time);
1634 prq.eo = GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO; 1648 process_reply (&prq,
1635 process_reply (&prq, key, pr); 1649 key,
1650 pr);
1636 pr->local_result = prq.eval; 1651 pr->local_result = prq.eval;
1637 if (GNUNET_BLOCK_REPLY_OK_LAST == prq.eval) 1652 if (GNUNET_BLOCK_REPLY_OK_LAST == prq.eval)
1638 { 1653 {
@@ -1720,7 +1735,8 @@ GSF_local_lookup_ (struct GSF_PendingRequest *pr,
1720 * @param put the actual message 1735 * @param put the actual message
1721 */ 1736 */
1722void 1737void
1723handle_p2p_put (void *cls, const struct PutMessage *put) 1738handle_p2p_put (void *cls,
1739 const struct PutMessage *put)
1724{ 1740{
1725 struct GSF_ConnectedPeer *cp = cls; 1741 struct GSF_ConnectedPeer *cp = cls;
1726 uint16_t msize; 1742 uint16_t msize;
@@ -1746,7 +1762,20 @@ handle_p2p_put (void *cls, const struct PutMessage *put)
1746 GNUNET_TIME_UNIT_YEARS), 1762 GNUNET_TIME_UNIT_YEARS),
1747 expiration); 1763 expiration);
1748 if (GNUNET_OK != 1764 if (GNUNET_OK !=
1749 GNUNET_BLOCK_get_key (GSF_block_ctx, type, &put[1], dsize, &query)) 1765 GNUNET_BLOCK_check_block (GSF_block_ctx,
1766 type,
1767 &put[1],
1768 dsize))
1769 {
1770 GNUNET_break_op (0);
1771 return;
1772 }
1773 if (GNUNET_OK !=
1774 GNUNET_BLOCK_get_key (GSF_block_ctx,
1775 type,
1776 &put[1],
1777 dsize,
1778 &query))
1750 { 1779 {
1751 GNUNET_break_op (0); 1780 GNUNET_break_op (0);
1752 return; 1781 return;
@@ -1764,7 +1793,6 @@ handle_p2p_put (void *cls, const struct PutMessage *put)
1764 prq.priority = 0; 1793 prq.priority = 0;
1765 prq.anonymity_level = UINT32_MAX; 1794 prq.anonymity_level = UINT32_MAX;
1766 prq.request_found = GNUNET_NO; 1795 prq.request_found = GNUNET_NO;
1767 prq.eo = GNUNET_BLOCK_EO_NONE;
1768 GNUNET_CONTAINER_multihashmap_get_multiple (pr_map, 1796 GNUNET_CONTAINER_multihashmap_get_multiple (pr_map,
1769 &query, 1797 &query,
1770 &process_reply, 1798 &process_reply,
diff --git a/src/fs/plugin_block_fs.c b/src/fs/plugin_block_fs.c
index 43380b3b6..029f95bc5 100644
--- a/src/fs/plugin_block_fs.c
+++ b/src/fs/plugin_block_fs.c
@@ -111,110 +111,6 @@ block_plugin_fs_create_group (void *cls,
111 111
112 112
113/** 113/**
114 * Function called to validate a reply or a request. For
115 * request evaluation, simply pass "NULL" for the reply_block.
116 * Note that it is assumed that the reply has already been
117 * matched to the key (and signatures checked) as it would
118 * be done with the #GNUNET_BLOCK_get_key() function.
119 *
120 * @param cls closure
121 * @param ctx block context
122 * @param type block type
123 * @param bg group to use for evaluation
124 * @param eo control flags
125 * @param query original query (hash)
126 * @param xquery extrended query data (can be NULL, depending on type)
127 * @param xquery_size number of bytes in @a xquery
128 * @param reply_block response to validate
129 * @param reply_block_size number of bytes in @a reply_block
130 * @return characterization of result
131 */
132static enum GNUNET_BLOCK_EvaluationResult
133block_plugin_fs_evaluate (void *cls,
134 struct GNUNET_BLOCK_Context *ctx,
135 enum GNUNET_BLOCK_Type type,
136 struct GNUNET_BLOCK_Group *bg,
137 enum GNUNET_BLOCK_EvaluationOptions eo,
138 const struct GNUNET_HashCode *query,
139 const void *xquery,
140 size_t xquery_size,
141 const void *reply_block,
142 size_t reply_block_size)
143{
144 const struct UBlock *ub;
145 struct GNUNET_HashCode hc;
146 struct GNUNET_HashCode chash;
147
148 switch (type)
149 {
150 case GNUNET_BLOCK_TYPE_FS_DBLOCK:
151 case GNUNET_BLOCK_TYPE_FS_IBLOCK:
152 if (0 != xquery_size)
153 {
154 GNUNET_break_op (0);
155 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
156 }
157 if (NULL == reply_block)
158 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
159 return GNUNET_BLOCK_EVALUATION_OK_LAST;
160
161 case GNUNET_BLOCK_TYPE_FS_UBLOCK:
162 if (0 != xquery_size)
163 {
164 GNUNET_break_op (0);
165 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
166 }
167 if (NULL == reply_block)
168 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
169
170 if (reply_block_size < sizeof(struct UBlock))
171 {
172 GNUNET_break_op (0);
173 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
174 }
175 ub = reply_block;
176 GNUNET_CRYPTO_hash (&ub->verification_key,
177 sizeof(ub->verification_key),
178 &hc);
179 if (0 != memcmp (&hc,
180 query,
181 sizeof(struct GNUNET_HashCode)))
182 {
183 GNUNET_break_op (0);
184 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
185 }
186 if (reply_block_size != ntohl (ub->purpose.size) + sizeof(struct
187 GNUNET_CRYPTO_EcdsaSignature))
188 {
189 GNUNET_break_op (0);
190 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
191 }
192 if ((0 == (eo & GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO)) &&
193 (GNUNET_OK !=
194 GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK,
195 &ub->purpose,
196 &ub->signature,
197 &ub->verification_key)))
198 {
199 GNUNET_break_op (0);
200 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
201 }
202 GNUNET_CRYPTO_hash (reply_block,
203 reply_block_size,
204 &chash);
205 if (GNUNET_YES ==
206 GNUNET_BLOCK_GROUP_bf_test_and_set (bg,
207 &chash))
208 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
209 return GNUNET_BLOCK_EVALUATION_OK_MORE;
210
211 default:
212 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
213 }
214}
215
216
217/**
218 * Function called to obtain the key for a block. 114 * Function called to obtain the key for a block.
219 * 115 *
220 * @param cls closure 116 * @param cls closure
@@ -245,8 +141,11 @@ block_plugin_fs_get_key (void *cls,
245 case GNUNET_BLOCK_TYPE_FS_UBLOCK: 141 case GNUNET_BLOCK_TYPE_FS_UBLOCK:
246 if (block_size < sizeof(struct UBlock)) 142 if (block_size < sizeof(struct UBlock))
247 { 143 {
248 GNUNET_break (0); 144 GNUNET_break_op (0);
249 return GNUNET_SYSERR; 145 memset (key,
146 0,
147 sizeof (*key));
148 return GNUNET_OK;
250 } 149 }
251 ub = block; 150 ub = block;
252 GNUNET_CRYPTO_hash (&ub->verification_key, 151 GNUNET_CRYPTO_hash (&ub->verification_key,
@@ -290,6 +189,7 @@ block_plugin_fs_check_query (void *cls,
290 } 189 }
291 return GNUNET_OK; 190 return GNUNET_OK;
292 default: 191 default:
192 GNUNET_break (0);
293 return GNUNET_SYSERR; 193 return GNUNET_SYSERR;
294 } 194 }
295} 195}
@@ -300,7 +200,6 @@ block_plugin_fs_check_query (void *cls,
300 * 200 *
301 * @param cls closure 201 * @param cls closure
302 * @param type block type 202 * @param type block type
303 * @param query key for the block (hash), must match exactly
304 * @param block block data to validate 203 * @param block block data to validate
305 * @param block_size number of bytes in @a block 204 * @param block_size number of bytes in @a block
306 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 205 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
@@ -308,7 +207,6 @@ block_plugin_fs_check_query (void *cls,
308static enum GNUNET_GenericReturnValue 207static enum GNUNET_GenericReturnValue
309block_plugin_fs_check_block (void *cls, 208block_plugin_fs_check_block (void *cls,
310 enum GNUNET_BLOCK_Type type, 209 enum GNUNET_BLOCK_Type type,
311 const struct GNUNET_HashCode *query,
312 const void *block, 210 const void *block,
313 size_t block_size) 211 size_t block_size)
314{ 212{
@@ -346,6 +244,7 @@ block_plugin_fs_check_block (void *cls,
346 return GNUNET_OK; 244 return GNUNET_OK;
347 } 245 }
348 default: 246 default:
247 GNUNET_break (0);
349 return GNUNET_SYSERR; 248 return GNUNET_SYSERR;
350 } 249 }
351} 250}
@@ -396,6 +295,7 @@ block_plugin_fs_check_reply (void *cls,
396 return GNUNET_BLOCK_REPLY_OK_MORE; 295 return GNUNET_BLOCK_REPLY_OK_MORE;
397 } 296 }
398 default: 297 default:
298 GNUNET_break (0);
399 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED; 299 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
400 } 300 }
401} 301}
@@ -416,7 +316,6 @@ libgnunet_plugin_block_fs_init (void *cls)
416 struct GNUNET_BLOCK_PluginFunctions *api; 316 struct GNUNET_BLOCK_PluginFunctions *api;
417 317
418 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 318 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
419 api->evaluate = &block_plugin_fs_evaluate;
420 api->get_key = &block_plugin_fs_get_key; 319 api->get_key = &block_plugin_fs_get_key;
421 api->create_group = &block_plugin_fs_create_group; 320 api->create_group = &block_plugin_fs_create_group;
422 api->check_query = &block_plugin_fs_check_query; 321 api->check_query = &block_plugin_fs_check_query;
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
index 315b4dbf3..d49e0c5c8 100644
--- a/src/gns/Makefile.am
+++ b/src/gns/Makefile.am
@@ -155,6 +155,7 @@ gnunet_dns2gns_LDADD = \
155 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ 155 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
156 libgnunetgns.la \ 156 libgnunetgns.la \
157 $(top_builddir)/src/util/libgnunetutil.la \ 157 $(top_builddir)/src/util/libgnunetutil.la \
158 $(USE_VPN) \
158 $(top_builddir)/src/identity/libgnunetidentity.la \ 159 $(top_builddir)/src/identity/libgnunetidentity.la \
159 $(GN_LIBINTL) 160 $(GN_LIBINTL)
160 161
@@ -218,7 +219,6 @@ gnunet_service_gns_LDADD = \
218 $(top_builddir)/src/dht/libgnunetdht.la \ 219 $(top_builddir)/src/dht/libgnunetdht.la \
219 $(top_builddir)/src/namecache/libgnunetnamecache.la \ 220 $(top_builddir)/src/namecache/libgnunetnamecache.la \
220 $(LIBIDN) $(LIBIDN2) \ 221 $(LIBIDN) $(LIBIDN2) \
221 $(USE_VPN) \
222 $(GN_LIBINTL) 222 $(GN_LIBINTL)
223 223
224 224
@@ -270,8 +270,7 @@ check_SCRIPTS = \
270 test_gns_rel_expiration.sh\ 270 test_gns_rel_expiration.sh\
271 test_gns_soa_lookup.sh\ 271 test_gns_soa_lookup.sh\
272 test_gns_revocation.sh\ 272 test_gns_revocation.sh\
273 test_gns_cname_lookup.sh\ 273 test_gns_redirect_lookup.sh
274 test_proxy.sh
275 274
276if HAVE_GNUTLS 275if HAVE_GNUTLS
277if HAVE_LIBGNURL 276if HAVE_LIBGNURL
@@ -292,7 +291,26 @@ EXTRA_DIST = \
292 zonefiles/J7POEUT41A8PBFS7KVVDRF88GBOU4HK8PSU5QKVLVE3R9T91E99G.zkey \ 291 zonefiles/J7POEUT41A8PBFS7KVVDRF88GBOU4HK8PSU5QKVLVE3R9T91E99G.zkey \
293 zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey \ 292 zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey \
294 zonefiles/test_zonekey \ 293 zonefiles/test_zonekey \
295 $(check_SCRIPTS) \ 294 test_gns_lookup.sh \
295 test_gns_config_lookup.sh \
296 test_gns_ipv6_lookup.sh\
297 test_gns_txt_lookup.sh\
298 test_gns_caa_lookup.sh\
299 test_gns_mx_lookup.sh \
300 test_gns_gns2dns_lookup.sh \
301 test_gns_gns2dns_zkey_lookup.sh \
302 test_gns_gns2dns_cname_lookup.sh \
303 test_gns_dht_lookup.sh\
304 test_gns_delegated_lookup.sh \
305 test_gns_at_lookup.sh\
306 test_gns_zkey_lookup.sh\
307 test_gns_rel_expiration.sh\
308 test_gns_soa_lookup.sh\
309 test_gns_revocation.sh\
310 test_gns_redirect_lookup.sh\
311 test_proxy.sh\
312 test_plugin_rest_gns.sh\
313 test_proxy.sh \
296 $(pkgdata_DATA) \ 314 $(pkgdata_DATA) \
297 test_gnunet_gns.sh.in 315 test_gnunet_gns.sh.in
298 316
diff --git a/src/gns/gnunet-bcd.c b/src/gns/gnunet-bcd.c
index 83efcfba5..60fe25945 100644
--- a/src/gns/gnunet-bcd.c
+++ b/src/gns/gnunet-bcd.c
@@ -419,6 +419,8 @@ create_response (void *cls,
419 "\\def\\gpglineone{%s}\n\\def\\gpglinetwo{%s}\n", 419 "\\def\\gpglineone{%s}\n\\def\\gpglinetwo{%s}\n",
420 line1, 420 line1,
421 line2); 421 line2);
422 GNUNET_free (line1);
423 GNUNET_free (line2);
422 } 424 }
423 425
424 fprintf (deffile, 426 fprintf (deffile,
diff --git a/src/gns/gnunet-dns2gns.c b/src/gns/gnunet-dns2gns.c
index 06f4c9841..46659cdda 100644
--- a/src/gns/gnunet-dns2gns.c
+++ b/src/gns/gnunet-dns2gns.c
@@ -27,6 +27,7 @@
27#include <gnunet_dnsparser_lib.h> 27#include <gnunet_dnsparser_lib.h>
28#include <gnunet_gns_service.h> 28#include <gnunet_gns_service.h>
29#include <gnunet_dnsstub_lib.h> 29#include <gnunet_dnsstub_lib.h>
30#include "gnunet_vpn_service.h"
30#include "gns.h" 31#include "gns.h"
31 32
32/** 33/**
@@ -35,6 +36,46 @@
35#define TIMEOUT GNUNET_TIME_UNIT_MINUTES 36#define TIMEOUT GNUNET_TIME_UNIT_MINUTES
36 37
37/** 38/**
39 * Default timeout for VPN redirections.
40 */
41#define VPN_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
42
43
44struct Request;
45
46/**
47 * Closure for #vpn_allocation_cb.
48 */
49struct VpnContext
50{
51 /**
52 * Which resolution process are we processing.
53 */
54 struct Request *request;
55
56 /**
57 * Handle to the VPN request that we were performing.
58 */
59 struct GNUNET_VPN_RedirectionRequest *vpn_request;
60
61 /**
62 * Number of records serialized in @e rd_data.
63 */
64 unsigned int rd_count;
65
66 /**
67 * Serialized records.
68 */
69 char *rd_data;
70
71 /**
72 * Number of bytes in @e rd_data.
73 */
74 ssize_t rd_data_size;
75};
76
77
78/**
38 * Data kept per request. 79 * Data kept per request.
39 */ 80 */
40struct Request 81struct Request
@@ -72,6 +113,11 @@ struct Request
72 struct GNUNET_SCHEDULER_Task *timeout_task; 113 struct GNUNET_SCHEDULER_Task *timeout_task;
73 114
74 /** 115 /**
116 * Vpn resulution context
117 */
118 struct VpnContext *vpn_ctx;
119
120 /**
75 * Original UDP request message. 121 * Original UDP request message.
76 */ 122 */
77 char *udp_msg; 123 char *udp_msg;
@@ -90,6 +136,7 @@ struct Request
90 * ID of the original request. 136 * ID of the original request.
91 */ 137 */
92 uint16_t original_request_id; 138 uint16_t original_request_id;
139
93}; 140};
94 141
95/** 142/**
@@ -109,6 +156,11 @@ static struct in6_addr address6;
109struct GNUNET_GNS_Handle *gns; 156struct GNUNET_GNS_Handle *gns;
110 157
111/** 158/**
159 * Our handle to the vpn service
160 */
161static struct GNUNET_VPN_Handle *vpn_handle;
162
163/**
112 * Stub resolver 164 * Stub resolver
113 */ 165 */
114struct GNUNET_DNSSTUB_Context *dns_stub; 166struct GNUNET_DNSSTUB_Context *dns_stub;
@@ -183,6 +235,11 @@ do_shutdown (void *cls)
183 GNUNET_GNS_disconnect (gns); 235 GNUNET_GNS_disconnect (gns);
184 gns = NULL; 236 gns = NULL;
185 } 237 }
238 if (NULL != vpn_handle)
239 {
240 GNUNET_VPN_disconnect (vpn_handle);
241 vpn_handle = NULL;
242 }
186 if (NULL != dns_stub) 243 if (NULL != dns_stub)
187 { 244 {
188 GNUNET_DNSSTUB_stop (dns_stub); 245 GNUNET_DNSSTUB_stop (dns_stub);
@@ -269,6 +326,7 @@ static void
269do_timeout (void *cls) 326do_timeout (void *cls)
270{ 327{
271 struct Request *request = cls; 328 struct Request *request = cls;
329 struct VpnContext *vpn_ctx;
272 330
273 if (NULL != request->packet) 331 if (NULL != request->packet)
274 GNUNET_DNSPARSER_free_packet (request->packet); 332 GNUNET_DNSPARSER_free_packet (request->packet);
@@ -277,6 +335,12 @@ do_timeout (void *cls)
277 if (NULL != request->dns_lookup) 335 if (NULL != request->dns_lookup)
278 GNUNET_DNSSTUB_resolve_cancel (request->dns_lookup); 336 GNUNET_DNSSTUB_resolve_cancel (request->dns_lookup);
279 GNUNET_free (request->udp_msg); 337 GNUNET_free (request->udp_msg);
338 if (NULL != (vpn_ctx = request->vpn_ctx))
339 {
340 GNUNET_VPN_cancel_request (vpn_ctx->vpn_request);
341 GNUNET_free (vpn_ctx->rd_data);
342 GNUNET_free (vpn_ctx);
343 }
280 GNUNET_free (request); 344 GNUNET_free (request);
281} 345}
282 346
@@ -321,6 +385,79 @@ dns_result_processor (void *cls,
321 send_response (request); 385 send_response (request);
322} 386}
323 387
388/**
389 * Callback invoked from the VPN service once a redirection is
390 * available. Provides the IP address that can now be used to
391 * reach the requested destination. Replaces the "VPN" record
392 * with the respective A/AAAA record and continues processing.
393 *
394 * @param cls closure
395 * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error;
396 * will match 'result_af' from the request
397 * @param address IP address (struct in_addr or struct in_addr6, depending on 'af')
398 * that the VPN allocated for the redirection;
399 * traffic to this IP will now be redirected to the
400 * specified target peer; NULL on error
401 */
402static void
403vpn_allocation_cb (void *cls,
404 int af,
405 const void *address)
406{
407 struct VpnContext *vpn_ctx = cls;
408 struct Request *request = vpn_ctx->request;
409 struct GNUNET_GNSRECORD_Data rd[vpn_ctx->rd_count];
410 unsigned int i;
411
412 vpn_ctx->vpn_request = NULL;
413 request->vpn_ctx = NULL;
414 GNUNET_assert (GNUNET_OK ==
415 GNUNET_GNSRECORD_records_deserialize (
416 (size_t) vpn_ctx->rd_data_size,
417 vpn_ctx->rd_data,
418 vpn_ctx->rd_count,
419 rd));
420 for (i = 0; i < vpn_ctx->rd_count; i++)
421 {
422 if (GNUNET_GNSRECORD_TYPE_VPN == rd[i].record_type)
423 {
424 switch (af)
425 {
426 case AF_INET:
427 rd[i].record_type = GNUNET_DNSPARSER_TYPE_A;
428 rd[i].data_size = sizeof(struct in_addr);
429 rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (
430 VPN_TIMEOUT).abs_value_us;
431 rd[i].flags = 0;
432 rd[i].data = address;
433 break;
434
435 case AF_INET6:
436 rd[i].record_type = GNUNET_DNSPARSER_TYPE_AAAA;
437 rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (
438 VPN_TIMEOUT).abs_value_us;
439 rd[i].flags = 0;
440 rd[i].data = address;
441 rd[i].data_size = sizeof(struct in6_addr);
442 break;
443
444 default:
445 GNUNET_assert (0);
446 }
447 break;
448 }
449 }
450 GNUNET_assert (i < vpn_ctx->rd_count);
451 if (0 == vpn_ctx->rd_count)
452 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
453 _ ("VPN returned empty result for `%s'\n"),
454 request->packet->queries[0].name);
455 send_response (request);
456 GNUNET_free (vpn_ctx->rd_data);
457 GNUNET_free (vpn_ctx);
458}
459
460
324 461
325/** 462/**
326 * Iterator called on obtained result for a GNS lookup. 463 * Iterator called on obtained result for a GNS lookup.
@@ -339,6 +476,11 @@ result_processor (void *cls,
339 struct Request *request = cls; 476 struct Request *request = cls;
340 struct GNUNET_DNSPARSER_Packet *packet; 477 struct GNUNET_DNSPARSER_Packet *packet;
341 struct GNUNET_DNSPARSER_Record rec; 478 struct GNUNET_DNSPARSER_Record rec;
479 struct VpnContext *vpn_ctx;
480 const struct GNUNET_TUN_GnsVpnRecord *vpn;
481 const char *vname;
482 struct GNUNET_HashCode vhash;
483 int af;
342 484
343 request->lookup = NULL; 485 request->lookup = NULL;
344 if (GNUNET_NO == was_gns) 486 if (GNUNET_NO == was_gns)
@@ -415,6 +557,67 @@ result_processor (void *cls,
415 packet->num_answers, 557 packet->num_answers,
416 rec); 558 rec);
417 break; 559 break;
560 case GNUNET_GNSRECORD_TYPE_VPN:
561 if ((GNUNET_DNSPARSER_TYPE_A != request->packet->queries[0].type) &&
562 (GNUNET_DNSPARSER_TYPE_AAAA != request->packet->queries[0].type))
563 break;
564 af = (GNUNET_DNSPARSER_TYPE_A == request->packet->queries[0].type) ? AF_INET :
565 AF_INET6;
566 if (sizeof(struct GNUNET_TUN_GnsVpnRecord) >
567 rd[i].data_size)
568 {
569 GNUNET_break_op (0);
570 break;
571 }
572 vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
573 vname = (const char *) &vpn[1];
574 if ('\0' != vname[rd[i].data_size - 1 - sizeof(struct
575 GNUNET_TUN_GnsVpnRecord)
576 ])
577 {
578 GNUNET_break_op (0);
579 break;
580 }
581 GNUNET_TUN_service_name_to_hash (vname,
582 &vhash);
583 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
584 "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n",
585 GNUNET_i2s (&vpn->peer),
586 vname,
587 (int) af,
588 (int) ntohs (vpn->proto));
589 vpn_ctx = GNUNET_new (struct VpnContext);
590 request->vpn_ctx = vpn_ctx;
591 vpn_ctx->request = request;
592 vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
593 rd);
594 if (vpn_ctx->rd_data_size < 0)
595 {
596 GNUNET_break_op (0);
597 GNUNET_free (vpn_ctx);
598 break;
599 }
600 vpn_ctx->rd_data = GNUNET_malloc ((size_t) vpn_ctx->rd_data_size);
601 vpn_ctx->rd_count = rd_count;
602 GNUNET_assert (vpn_ctx->rd_data_size ==
603 GNUNET_GNSRECORD_records_serialize (rd_count,
604 rd,
605 (size_t) vpn_ctx
606 ->rd_data_size,
607 vpn_ctx->rd_data));
608 vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
609 af,
610 ntohs (
611 vpn->proto),
612 &vpn->peer,
613 &vhash,
614 GNUNET_TIME_relative_to_absolute (
615 VPN_TIMEOUT),
616 &
617 vpn_allocation_cb,
618 vpn_ctx);
619 return;
620
418 621
419 default: 622 default:
420 /* skip */ 623 /* skip */
@@ -641,6 +844,8 @@ run (void *cls,
641 NULL); 844 NULL);
642 if (NULL == (gns = GNUNET_GNS_connect (cfg))) 845 if (NULL == (gns = GNUNET_GNS_connect (cfg)))
643 return; 846 return;
847 if (NULL == (vpn_handle = GNUNET_VPN_connect (cfg)))
848 return;
644 GNUNET_assert (NULL != (dns_stub = GNUNET_DNSSTUB_start (128))); 849 GNUNET_assert (NULL != (dns_stub = GNUNET_DNSSTUB_start (128)));
645 if (GNUNET_OK != 850 if (GNUNET_OK !=
646 GNUNET_DNSSTUB_add_dns_ip (dns_stub, 851 GNUNET_DNSSTUB_add_dns_ip (dns_stub,
@@ -649,6 +854,8 @@ run (void *cls,
649 GNUNET_DNSSTUB_stop (dns_stub); 854 GNUNET_DNSSTUB_stop (dns_stub);
650 GNUNET_GNS_disconnect (gns); 855 GNUNET_GNS_disconnect (gns);
651 gns = NULL; 856 gns = NULL;
857 GNUNET_VPN_disconnect (vpn_handle);
858 vpn_handle = NULL;
652 return; 859 return;
653 } 860 }
654 861
@@ -750,6 +957,8 @@ run (void *cls,
750 { 957 {
751 GNUNET_GNS_disconnect (gns); 958 GNUNET_GNS_disconnect (gns);
752 gns = NULL; 959 gns = NULL;
960 GNUNET_VPN_disconnect (vpn_handle);
961 vpn_handle = NULL;
753 GNUNET_DNSSTUB_stop (dns_stub); 962 GNUNET_DNSSTUB_stop (dns_stub);
754 dns_stub = NULL; 963 dns_stub = NULL;
755 return; 964 return;
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c
index 5833f4d0b..b28236fed 100644
--- a/src/gns/gnunet-service-gns.c
+++ b/src/gns/gnunet-service-gns.c
@@ -420,15 +420,11 @@ handle_lookup (void *cls,
420 const struct LookupMessage *sh_msg) 420 const struct LookupMessage *sh_msg)
421{ 421{
422 struct GnsClient *gc = cls; 422 struct GnsClient *gc = cls;
423 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 1];
424 struct ClientLookupHandle *clh; 423 struct ClientLookupHandle *clh;
425 char *nameptr = name; 424 const char *name;
426 const char *utf_in;
427 425
428 GNUNET_SERVICE_client_continue (gc->client); 426 GNUNET_SERVICE_client_continue (gc->client);
429 utf_in = (const char *) &sh_msg[1]; 427 name = (const char *) &sh_msg[1];
430 GNUNET_STRINGS_utf8_tolower (utf_in,
431 nameptr);
432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 428 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
433 "Received LOOKUP `%s' message\n", 429 "Received LOOKUP `%s' message\n",
434 name); 430 name);
diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c
index 51e650b4f..72b228f33 100644
--- a/src/gns/gnunet-service-gns_resolver.c
+++ b/src/gns/gnunet-service-gns_resolver.c
@@ -52,7 +52,6 @@
52#include "gns.h" 52#include "gns.h"
53#include "gnunet-service-gns.h" 53#include "gnunet-service-gns.h"
54#include "gnunet-service-gns_resolver.h" 54#include "gnunet-service-gns_resolver.h"
55#include "gnunet_vpn_service.h"
56 55
57 56
58/** 57/**
@@ -68,11 +67,6 @@
68 GNUNET_TIME_UNIT_SECONDS, 15) 67 GNUNET_TIME_UNIT_SECONDS, 15)
69 68
70/** 69/**
71 * Default timeout for VPN redirections.
72 */
73#define VPN_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
74
75/**
76 * DHT replication level 70 * DHT replication level
77 */ 71 */
78#define DHT_GNS_REPLICATION_LEVEL 10 72#define DHT_GNS_REPLICATION_LEVEL 10
@@ -255,38 +249,6 @@ struct DnsResult
255 249
256 250
257/** 251/**
258 * Closure for #vpn_allocation_cb.
259 */
260struct VpnContext
261{
262 /**
263 * Which resolution process are we processing.
264 */
265 struct GNS_ResolverHandle *rh;
266
267 /**
268 * Handle to the VPN request that we were performing.
269 */
270 struct GNUNET_VPN_RedirectionRequest *vpn_request;
271
272 /**
273 * Number of records serialized in @e rd_data.
274 */
275 unsigned int rd_count;
276
277 /**
278 * Serialized records.
279 */
280 char *rd_data;
281
282 /**
283 * Number of bytes in @e rd_data.
284 */
285 ssize_t rd_data_size;
286};
287
288
289/**
290 * Handle to a currently pending resolution. On result (positive or 252 * Handle to a currently pending resolution. On result (positive or
291 * negative) the #GNS_ResultProcessor is called. 253 * negative) the #GNS_ResultProcessor is called.
292 */ 254 */
@@ -322,10 +284,6 @@ struct GNS_ResolverHandle
322 */ 284 */
323 struct GNUNET_DHT_GetHandle *get_handle; 285 struct GNUNET_DHT_GetHandle *get_handle;
324 286
325 /**
326 * Handle to a VPN request, NULL if none is active.
327 */
328 struct VpnContext *vpn_ctx;
329 287
330 /** 288 /**
331 * Socket for a DNS request, NULL if none is active. 289 * Socket for a DNS request, NULL if none is active.
@@ -463,11 +421,6 @@ struct CacheOps
463static struct GNUNET_NAMECACHE_Handle *namecache_handle; 421static struct GNUNET_NAMECACHE_Handle *namecache_handle;
464 422
465/** 423/**
466 * Our handle to the vpn service
467 */
468static struct GNUNET_VPN_Handle *vpn_handle;
469
470/**
471 * Resolver handle to the dht 424 * Resolver handle to the dht
472 */ 425 */
473static struct GNUNET_DHT_Handle *dht_handle; 426static struct GNUNET_DHT_Handle *dht_handle;
@@ -1235,16 +1188,16 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh)
1235 1188
1236 1189
1237/** 1190/**
1238 * We encountered a CNAME record during our resolution. 1191 * We encountered a REDIRECT record during our resolution.
1239 * Merge it into our chain. 1192 * Merge it into our chain.
1240 * 1193 *
1241 * @param rh resolution we are performing 1194 * @param rh resolution we are performing
1242 * @param cname value of the cname record we got for the current 1195 * @param rname value of the redirect record we got for the current
1243 * authority chain tail 1196 * authority chain tail
1244 */ 1197 */
1245static void 1198static void
1246handle_gns_cname_result (struct GNS_ResolverHandle *rh, 1199handle_gns_redirect_result (struct GNS_ResolverHandle *rh,
1247 const char *cname) 1200 const char *rname)
1248{ 1201{
1249 size_t nlen; 1202 size_t nlen;
1250 char *res; 1203 char *res;
@@ -1253,14 +1206,17 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh,
1253 int af; 1206 int af;
1254 struct GNUNET_IDENTITY_PublicKey zone; 1207 struct GNUNET_IDENTITY_PublicKey zone;
1255 1208
1256 nlen = strlen (cname); 1209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1257 tld = GNS_get_tld (cname); 1210 "Handling GNS REDIRECT result `%s'\n",
1211 rname);
1212 nlen = strlen (rname);
1213 tld = GNS_get_tld (rname);
1258 if (0 == strcmp ("+", tld)) 1214 if (0 == strcmp ("+", tld))
1259 { 1215 {
1260 /* CNAME resolution continues relative to current domain */ 1216 /* REDIRECT resolution continues relative to current domain */
1261 if (0 == rh->name_resolution_pos) 1217 if (0 == rh->name_resolution_pos)
1262 { 1218 {
1263 res = GNUNET_strndup (cname, nlen - 2); 1219 res = GNUNET_strndup (rname, nlen - 2);
1264 rh->name_resolution_pos = nlen - 2; 1220 rh->name_resolution_pos = nlen - 2;
1265 } 1221 }
1266 else 1222 else
@@ -1270,7 +1226,7 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh,
1270 (int) rh->name_resolution_pos, 1226 (int) rh->name_resolution_pos,
1271 rh->name, 1227 rh->name,
1272 (int) (nlen - 2), 1228 (int) (nlen - 2),
1273 cname); 1229 rname);
1274 rh->name_resolution_pos = strlen (res); 1230 rh->name_resolution_pos = strlen (res);
1275 } 1231 }
1276 GNUNET_free (rh->name); 1232 GNUNET_free (rh->name);
@@ -1291,13 +1247,13 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh,
1291 } 1247 }
1292 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)) 1248 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1293 { 1249 {
1294 /* CNAME resolution continues relative to current domain */ 1250 /* REDIRECT resolution continues relative to current domain */
1295 if (0 == rh->name_resolution_pos) 1251 if (0 == rh->name_resolution_pos)
1296 { 1252 {
1297 GNUNET_asprintf (&res, 1253 GNUNET_asprintf (&res,
1298 "%.*s", 1254 "%.*s",
1299 (int) (strlen (cname) - (strlen (tld) + 1)), 1255 (int) (strlen (rname) - (strlen (tld) + 1)),
1300 cname); 1256 rname);
1301 } 1257 }
1302 else 1258 else
1303 { 1259 {
@@ -1305,8 +1261,8 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh,
1305 "%.*s.%.*s", 1261 "%.*s.%.*s",
1306 (int) rh->name_resolution_pos, 1262 (int) rh->name_resolution_pos,
1307 rh->name, 1263 rh->name,
1308 (int) (strlen (cname) - (strlen (tld) + 1)), 1264 (int) (strlen (rname) - (strlen (tld) + 1)),
1309 cname); 1265 rname);
1310 } 1266 }
1311 rh->name_resolution_pos = strlen (res); 1267 rh->name_resolution_pos = strlen (res);
1312 GNUNET_free (rh->name); 1268 GNUNET_free (rh->name);
@@ -1326,18 +1282,62 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh,
1326 } 1282 }
1327 1283
1328 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1284 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1329 "Got CNAME `%s' from GNS for `%s'\n", 1285 "Got REDIRECT `%s' from GNS for `%s'\n",
1330 cname, 1286 rname,
1331 rh->name); 1287 rh->name);
1332 if (NULL != rh->std_resolve) 1288 if (NULL != rh->std_resolve)
1333 { 1289 {
1334 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1290 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1335 "Multiple CNAME results from GNS resolving `%s'! Not really allowed...\n", 1291 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1336 rh->name); 1292 rh->name);
1337 GNUNET_RESOLVER_request_cancel (rh->std_resolve); 1293 GNUNET_RESOLVER_request_cancel (rh->std_resolve);
1338 } 1294 }
1339 /* name is absolute, go to DNS */ 1295 /* name is absolute, go to DNS */
1340 GNUNET_free (rh->name); 1296 GNUNET_free (rh->name);
1297 rh->name = GNUNET_strdup (rname);
1298 rh->name_resolution_pos = strlen (rh->name);
1299 switch (rh->record_type)
1300 {
1301 case GNUNET_DNSPARSER_TYPE_A:
1302 af = AF_INET;
1303 break;
1304
1305 case GNUNET_DNSPARSER_TYPE_AAAA:
1306 af = AF_INET6;
1307 break;
1308
1309 default:
1310 af = AF_UNSPEC;
1311 break;
1312 }
1313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1314 "Doing standard DNS lookup for `%s'\n",
1315 rh->name);
1316
1317 rh->std_resolve = GNUNET_RESOLVER_ip_get (rh->name,
1318 af,
1319 DNS_LOOKUP_TIMEOUT,
1320 &handle_dns_result,
1321 rh);
1322}
1323
1324
1325
1326/**
1327 * We encountered a CNAME record during our resolution.
1328 * Merge it into our chain.
1329 *
1330 * @param rh resolution we are performing
1331 * @param cname value of the cname record we got for the current
1332 * authority chain tail
1333 */
1334static void
1335handle_gns_cname_result (struct GNS_ResolverHandle *rh,
1336 const char *cname)
1337{
1338 int af;
1339
1340 GNUNET_free (rh->name);
1341 rh->name = GNUNET_strdup (cname); 1341 rh->name = GNUNET_strdup (cname);
1342 rh->name_resolution_pos = strlen (rh->name); 1342 rh->name_resolution_pos = strlen (rh->name);
1343 switch (rh->record_type) 1343 switch (rh->record_type)
@@ -1379,80 +1379,6 @@ handle_gns_resolution_result (void *cls,
1379 const struct GNUNET_GNSRECORD_Data *rd); 1379 const struct GNUNET_GNSRECORD_Data *rd);
1380 1380
1381 1381
1382/**
1383 * Callback invoked from the VPN service once a redirection is
1384 * available. Provides the IP address that can now be used to
1385 * reach the requested destination. Replaces the "VPN" record
1386 * with the respective A/AAAA record and continues processing.
1387 *
1388 * @param cls closure
1389 * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error;
1390 * will match 'result_af' from the request
1391 * @param address IP address (struct in_addr or struct in_addr6, depending on 'af')
1392 * that the VPN allocated for the redirection;
1393 * traffic to this IP will now be redirected to the
1394 * specified target peer; NULL on error
1395 */
1396static void
1397vpn_allocation_cb (void *cls,
1398 int af,
1399 const void *address)
1400{
1401 struct VpnContext *vpn_ctx = cls;
1402 struct GNS_ResolverHandle *rh = vpn_ctx->rh;
1403 struct GNUNET_GNSRECORD_Data rd[vpn_ctx->rd_count];
1404 unsigned int i;
1405
1406 vpn_ctx->vpn_request = NULL;
1407 rh->vpn_ctx = NULL;
1408 GNUNET_assert (GNUNET_OK ==
1409 GNUNET_GNSRECORD_records_deserialize (
1410 (size_t) vpn_ctx->rd_data_size,
1411 vpn_ctx->rd_data,
1412 vpn_ctx->rd_count,
1413 rd));
1414 for (i = 0; i < vpn_ctx->rd_count; i++)
1415 {
1416 if (GNUNET_GNSRECORD_TYPE_VPN == rd[i].record_type)
1417 {
1418 switch (af)
1419 {
1420 case AF_INET:
1421 rd[i].record_type = GNUNET_DNSPARSER_TYPE_A;
1422 rd[i].data_size = sizeof(struct in_addr);
1423 rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (
1424 VPN_TIMEOUT).abs_value_us;
1425 rd[i].flags = 0;
1426 rd[i].data = address;
1427 break;
1428
1429 case AF_INET6:
1430 rd[i].record_type = GNUNET_DNSPARSER_TYPE_AAAA;
1431 rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (
1432 VPN_TIMEOUT).abs_value_us;
1433 rd[i].flags = 0;
1434 rd[i].data = address;
1435 rd[i].data_size = sizeof(struct in6_addr);
1436 break;
1437
1438 default:
1439 GNUNET_assert (0);
1440 }
1441 break;
1442 }
1443 }
1444 GNUNET_assert (i < vpn_ctx->rd_count);
1445 if (0 == vpn_ctx->rd_count)
1446 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1447 _ ("VPN returned empty result for `%s'\n"),
1448 rh->name);
1449 handle_gns_resolution_result (rh,
1450 vpn_ctx->rd_count,
1451 rd);
1452 GNUNET_free (vpn_ctx->rd_data);
1453 GNUNET_free (vpn_ctx);
1454}
1455
1456 1382
1457/** 1383/**
1458 * We have resolved one or more of the nameservers for a 1384 * We have resolved one or more of the nameservers for a
@@ -1653,6 +1579,20 @@ handle_gns2dns_ip (void *cls,
1653 ac->authority_info.dns_authority.found = GNUNET_YES; 1579 ac->authority_info.dns_authority.found = GNUNET_YES;
1654} 1580}
1655 1581
1582/**
1583 * We found a REDIRECT record, perform recursive resolution on it.
1584 *
1585 * @param rh resolution handle
1586 * @param rd record with CNAME to resolve recursively
1587 */
1588static void
1589recursive_redirect_resolution (struct GNS_ResolverHandle *rh,
1590 const struct GNUNET_GNSRECORD_Data *rd)
1591{
1592 handle_gns_redirect_result (rh,
1593 rd->data);
1594}
1595
1656 1596
1657/** 1597/**
1658 * We found a CNAME record, perform recursive resolution on it. 1598 * We found a CNAME record, perform recursive resolution on it.
@@ -1956,11 +1896,6 @@ handle_gns_resolution_result (void *cls,
1956{ 1896{
1957 struct GNS_ResolverHandle *rh = cls; 1897 struct GNS_ResolverHandle *rh = cls;
1958 char *cname; 1898 char *cname;
1959 struct VpnContext *vpn_ctx;
1960 const struct GNUNET_TUN_GnsVpnRecord *vpn;
1961 const char *vname;
1962 struct GNUNET_HashCode vhash;
1963 int af;
1964 char scratch[UINT16_MAX]; 1899 char scratch[UINT16_MAX];
1965 size_t scratch_off; 1900 size_t scratch_off;
1966 size_t scratch_start; 1901 size_t scratch_start;
@@ -2006,8 +1941,18 @@ handle_gns_resolution_result (void *cls,
2006 GNUNET_free (cname); 1941 GNUNET_free (cname);
2007 return; 1942 return;
2008 } 1943 }
2009 /* If A/AAAA was requested, but we got a VPN 1944 if ((rd_count > 0) &&
2010 record, we convert it to A/AAAA using GNUnet VPN */ 1945 (GNUNET_GNSRECORD_TYPE_REDIRECT == rd[0].record_type) &&
1946 (GNUNET_GNSRECORD_TYPE_REDIRECT != rh->record_type))
1947 {
1948 handle_gns_redirect_result (rh,
1949 rd[0].data);
1950 return;
1951 }
1952
1953
1954 /* If A/AAAA was requested,
1955 * but we got a GNS2DNS record */
2011 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) || 1956 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2012 (GNUNET_DNSPARSER_TYPE_AAAA == rh->record_type)) 1957 (GNUNET_DNSPARSER_TYPE_AAAA == rh->record_type))
2013 { 1958 {
@@ -2015,69 +1960,6 @@ handle_gns_resolution_result (void *cls,
2015 { 1960 {
2016 switch (rd[i].record_type) 1961 switch (rd[i].record_type)
2017 { 1962 {
2018 case GNUNET_GNSRECORD_TYPE_VPN:
2019 {
2020 af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET :
2021 AF_INET6;
2022 if (sizeof(struct GNUNET_TUN_GnsVpnRecord) >
2023 rd[i].data_size)
2024 {
2025 GNUNET_break_op (0);
2026 fail_resolution (rh);
2027 return;
2028 }
2029 vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
2030 vname = (const char *) &vpn[1];
2031 if ('\0' != vname[rd[i].data_size - 1 - sizeof(struct
2032 GNUNET_TUN_GnsVpnRecord)
2033 ])
2034 {
2035 GNUNET_break_op (0);
2036 fail_resolution (rh);
2037 return;
2038 }
2039 GNUNET_TUN_service_name_to_hash (vname,
2040 &vhash);
2041 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2042 "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n",
2043 GNUNET_i2s (&vpn->peer),
2044 vname,
2045 (int) af,
2046 (int) ntohs (vpn->proto));
2047 vpn_ctx = GNUNET_new (struct VpnContext);
2048 rh->vpn_ctx = vpn_ctx;
2049 vpn_ctx->rh = rh;
2050 vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
2051 rd);
2052 if (vpn_ctx->rd_data_size < 0)
2053 {
2054 GNUNET_break_op (0);
2055 GNUNET_free (vpn_ctx);
2056 fail_resolution (rh);
2057 return;
2058 }
2059 vpn_ctx->rd_data = GNUNET_malloc ((size_t) vpn_ctx->rd_data_size);
2060 vpn_ctx->rd_count = rd_count;
2061 GNUNET_assert (vpn_ctx->rd_data_size ==
2062 GNUNET_GNSRECORD_records_serialize (rd_count,
2063 rd,
2064 (size_t) vpn_ctx
2065 ->rd_data_size,
2066 vpn_ctx->rd_data));
2067 vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
2068 af,
2069 ntohs (
2070 vpn->proto),
2071 &vpn->peer,
2072 &vhash,
2073 GNUNET_TIME_relative_to_absolute (
2074 VPN_TIMEOUT),
2075 &
2076 vpn_allocation_cb,
2077 vpn_ctx);
2078 return;
2079 }
2080
2081 case GNUNET_GNSRECORD_TYPE_GNS2DNS: 1963 case GNUNET_GNSRECORD_TYPE_GNS2DNS:
2082 { 1964 {
2083 /* delegation to DNS */ 1965 /* delegation to DNS */
@@ -2117,6 +1999,23 @@ handle_gns_resolution_result (void *cls,
2117 so we can free it afterwards. */ 1999 so we can free it afterwards. */
2118 switch (rd[i].record_type) 2000 switch (rd[i].record_type)
2119 { 2001 {
2002 case GNUNET_GNSRECORD_TYPE_REDIRECT:
2003 {
2004 char *rname;
2005 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2006 rname = translate_dot_plus (rh, rname);
2007 GNUNET_break (NULL != rname);
2008 scratch_start = scratch_off;
2009 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2010 scratch_off += strlen (rname) + 1;
2011 GNUNET_assert (rd_off < rd_count);
2012 rd_new[rd_off].data = &scratch[scratch_start];
2013 rd_new[rd_off].data_size = scratch_off - scratch_start;
2014 rd_off++;
2015 GNUNET_free (rname);
2016 }
2017 break;
2018
2120 case GNUNET_DNSPARSER_TYPE_CNAME: 2019 case GNUNET_DNSPARSER_TYPE_CNAME:
2121 { 2020 {
2122 char *cname; 2021 char *cname;
@@ -2380,6 +2279,12 @@ handle_gns_resolution_result (void *cls,
2380 2279
2381 switch (rd[0].record_type) 2280 switch (rd[0].record_type)
2382 { 2281 {
2282 case GNUNET_GNSRECORD_TYPE_REDIRECT:
2283 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2284 recursive_redirect_resolution (rh,
2285 &rd[0]);
2286 return;
2287
2383 case GNUNET_DNSPARSER_TYPE_CNAME: 2288 case GNUNET_DNSPARSER_TYPE_CNAME:
2384 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */ 2289 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2385 recursive_cname_resolution (rh, 2290 recursive_cname_resolution (rh,
@@ -2393,15 +2298,21 @@ handle_gns_resolution_result (void *cls,
2393 &rd[0]); 2298 &rd[0]);
2394 return; 2299 return;
2395 2300
2396 default: 2301 case GNUNET_GNSRECORD_TYPE_GNS2DNS:
2397 if (GNUNET_OK == 2302 if (GNUNET_OK ==
2398 recursive_gns2dns_resolution (rh, 2303 recursive_gns2dns_resolution (rh,
2399 rd_count, 2304 rd_count,
2400 rd)) 2305 rd))
2401 return; 2306 return;
2402 break; 2307 break;
2308 default:
2309 if (GNUNET_YES != GNUNET_GNSRECORD_is_critical (rd[0].record_type))
2310 return;
2311 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2312 _ ("Unable to process critical delegation record\n"));
2313 break;
2403 } 2314 }
2404fail: 2315 fail:
2405 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2316 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2406 _ ("GNS lookup recursion failed (no delegation record found)\n")); 2317 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2407 fail_resolution (rh); 2318 fail_resolution (rh);
@@ -2618,6 +2529,13 @@ handle_namecache_block_response (void *cls,
2618 2529
2619 GNUNET_assert (NULL != rh->namecache_qe); 2530 GNUNET_assert (NULL != rh->namecache_qe);
2620 rh->namecache_qe = NULL; 2531 rh->namecache_qe = NULL;
2532 if (NULL == block)
2533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2534 "No block found\n");
2535 else
2536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2537 "Got block with expiration %s\n",
2538 GNUNET_STRINGS_absolute_time_to_string (GNUNET_GNSRECORD_block_get_expiration (block)));
2621 if (((GNUNET_GNS_LO_DEFAULT == rh->options) || 2539 if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2622 ((GNUNET_GNS_LO_LOCAL_MASTER == rh->options) && 2540 ((GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2623 (ac != rh->ac_head))) && 2541 (ac != rh->ac_head))) &&
@@ -2916,7 +2834,6 @@ GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh)
2916{ 2834{
2917 struct DnsResult *dr; 2835 struct DnsResult *dr;
2918 struct AuthorityChain *ac; 2836 struct AuthorityChain *ac;
2919 struct VpnContext *vpn_ctx;
2920 2837
2921 GNUNET_CONTAINER_DLL_remove (rlh_head, 2838 GNUNET_CONTAINER_DLL_remove (rlh_head,
2922 rlh_tail, 2839 rlh_tail,
@@ -2981,12 +2898,6 @@ GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh)
2981 GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node); 2898 GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node);
2982 rh->dht_heap_node = NULL; 2899 rh->dht_heap_node = NULL;
2983 } 2900 }
2984 if (NULL != (vpn_ctx = rh->vpn_ctx))
2985 {
2986 GNUNET_VPN_cancel_request (vpn_ctx->vpn_request);
2987 GNUNET_free (vpn_ctx->rd_data);
2988 GNUNET_free (vpn_ctx);
2989 }
2990 if (NULL != rh->namecache_qe) 2901 if (NULL != rh->namecache_qe)
2991 { 2902 {
2992 GNUNET_NAMECACHE_cancel (rh->namecache_qe); 2903 GNUNET_NAMECACHE_cancel (rh->namecache_qe);
@@ -3046,7 +2957,6 @@ GNS_resolver_init (struct GNUNET_NAMECACHE_Handle *nc,
3046 if (GNUNET_YES == disable_cache) 2957 if (GNUNET_YES == disable_cache)
3047 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2958 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3048 "Namecache disabled\n"); 2959 "Namecache disabled\n");
3049 vpn_handle = GNUNET_VPN_connect (cfg);
3050} 2960}
3051 2961
3052 2962
@@ -3077,8 +2987,6 @@ GNS_resolver_done ()
3077 } 2987 }
3078 GNUNET_CONTAINER_heap_destroy (dht_lookup_heap); 2988 GNUNET_CONTAINER_heap_destroy (dht_lookup_heap);
3079 dht_lookup_heap = NULL; 2989 dht_lookup_heap = NULL;
3080 GNUNET_VPN_disconnect (vpn_handle);
3081 vpn_handle = NULL;
3082 dht_handle = NULL; 2990 dht_handle = NULL;
3083 namecache_handle = NULL; 2991 namecache_handle = NULL;
3084} 2992}
diff --git a/src/gns/plugin_block_gns.c b/src/gns/plugin_block_gns.c
index 407754a8c..fd9c99cb4 100644
--- a/src/gns/plugin_block_gns.c
+++ b/src/gns/plugin_block_gns.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2010-2013 GNUnet e.V. 3 Copyright (C) 2010-2013, 2021, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -92,98 +92,16 @@ block_plugin_gns_create_group (void *cls,
92 92
93 93
94/** 94/**
95 * Function called to validate a reply or a request. For
96 * request evaluation, simply pass "NULL" for the reply_block.
97 * Note that it is assumed that the reply has already been
98 * matched to the key (and signatures checked) as it would
99 * be done with the "get_key" function.
100 *
101 * @param cls closure
102 * @param ctx block context
103 * @param type block type
104 * @param bg block group to use for evaluation
105 * @param eo control flags
106 * @param query original query (hash)
107 * @param xquery extrended query data (can be NULL, depending on @a type)
108 * @param xquery_size number of bytes in @a xquery
109 * @param reply_block response to validate
110 * @param reply_block_size number of bytes in @a reply_block
111 * @return characterization of result
112 */
113static enum GNUNET_BLOCK_EvaluationResult
114block_plugin_gns_evaluate (void *cls,
115 struct GNUNET_BLOCK_Context *ctx,
116 enum GNUNET_BLOCK_Type type,
117 struct GNUNET_BLOCK_Group *bg,
118 enum GNUNET_BLOCK_EvaluationOptions eo,
119 const struct GNUNET_HashCode *query,
120 const void *xquery,
121 size_t xquery_size,
122 const void *reply_block,
123 size_t reply_block_size)
124{
125 const struct GNUNET_GNSRECORD_Block *block;
126 struct GNUNET_HashCode h;
127 struct GNUNET_HashCode chash;
128
129 if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD)
130 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
131 if (NULL == reply_block)
132 {
133 if (0 != xquery_size)
134 {
135 GNUNET_break_op (0);
136 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
137 }
138 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
139 }
140
141 /* this is a reply */
142 if (reply_block_size < sizeof(struct GNUNET_GNSRECORD_Block))
143 {
144 GNUNET_break_op (0);
145 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
146 }
147 block = reply_block;
148 if (GNUNET_GNSRECORD_block_get_size (block) > reply_block_size)
149 {
150 GNUNET_break_op (0);
151 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
152 }
153 GNUNET_GNSRECORD_query_from_block (block,
154 &h);
155 if (0 != GNUNET_memcmp (&h, query))
156 {
157 GNUNET_break_op (0);
158 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
159 }
160 if (GNUNET_OK !=
161 GNUNET_GNSRECORD_block_verify (block))
162 {
163 GNUNET_break_op (0);
164 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
165 }
166 GNUNET_CRYPTO_hash (reply_block,
167 reply_block_size,
168 &chash);
169 if (GNUNET_YES ==
170 GNUNET_BLOCK_GROUP_bf_test_and_set (bg,
171 &chash))
172 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
173 return GNUNET_BLOCK_EVALUATION_OK_MORE;
174}
175
176
177/**
178 * Function called to obtain the key for a block. 95 * Function called to obtain the key for a block.
96 * If the @a block is malformed, the function should
97 * zero-out @a key and return #GNUNET_OK.
179 * 98 *
180 * @param cls closure 99 * @param cls closure
181 * @param type block type 100 * @param type block type
182 * @param reply_block block to get the key for 101 * @param reply_block block to get the key for
183 * @param reply_block_size number of bytes in @a reply_block 102 * @param reply_block_size number of bytes in @a reply_block
184 * @param key set to the key (query) for the given block 103 * @param key set to the key (query) for the given block
185 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 104 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported, #GNUNET_NO if extracting a key from a block of this type does not work
186 * (or if extracting a key from a block of this type does not work)
187 */ 105 */
188static enum GNUNET_GenericReturnValue 106static enum GNUNET_GenericReturnValue
189block_plugin_gns_get_key (void *cls, 107block_plugin_gns_get_key (void *cls,
@@ -194,12 +112,18 @@ block_plugin_gns_get_key (void *cls,
194{ 112{
195 const struct GNUNET_GNSRECORD_Block *block; 113 const struct GNUNET_GNSRECORD_Block *block;
196 114
197 if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD) 115 if (GNUNET_BLOCK_TYPE_GNS_NAMERECORD != type)
116 {
117 GNUNET_break (0);
198 return GNUNET_SYSERR; 118 return GNUNET_SYSERR;
119 }
199 if (reply_block_size < sizeof(struct GNUNET_GNSRECORD_Block)) 120 if (reply_block_size < sizeof(struct GNUNET_GNSRECORD_Block))
200 { 121 {
201 GNUNET_break_op (0); 122 GNUNET_break_op (0);
202 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; 123 memset (key,
124 0,
125 sizeof (*key));
126 return GNUNET_OK;
203 } 127 }
204 block = reply_block; 128 block = reply_block;
205 GNUNET_GNSRECORD_query_from_block (block, 129 GNUNET_GNSRECORD_query_from_block (block,
@@ -227,8 +151,11 @@ block_plugin_gns_check_query (void *cls,
227 const void *xquery, 151 const void *xquery,
228 size_t xquery_size) 152 size_t xquery_size)
229{ 153{
230 if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD) 154 if (GNUNET_BLOCK_TYPE_GNS_NAMERECORD != type)
155 {
156 GNUNET_break (0);
231 return GNUNET_SYSERR; 157 return GNUNET_SYSERR;
158 }
232 if (0 != xquery_size) 159 if (0 != xquery_size)
233 { 160 {
234 GNUNET_break_op (0); 161 GNUNET_break_op (0);
@@ -243,7 +170,6 @@ block_plugin_gns_check_query (void *cls,
243 * 170 *
244 * @param cls closure 171 * @param cls closure
245 * @param type block type 172 * @param type block type
246 * @param query key for the block (hash), must match exactly
247 * @param block block data to validate 173 * @param block block data to validate
248 * @param block_size number of bytes in @a block 174 * @param block_size number of bytes in @a block
249 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 175 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
@@ -251,14 +177,16 @@ block_plugin_gns_check_query (void *cls,
251static enum GNUNET_GenericReturnValue 177static enum GNUNET_GenericReturnValue
252block_plugin_gns_check_block (void *cls, 178block_plugin_gns_check_block (void *cls,
253 enum GNUNET_BLOCK_Type type, 179 enum GNUNET_BLOCK_Type type,
254 const struct GNUNET_HashCode *query,
255 const void *block, 180 const void *block,
256 size_t block_size) 181 size_t block_size)
257{ 182{
258 const struct GNUNET_GNSRECORD_Block *gblock; 183 const struct GNUNET_GNSRECORD_Block *gblock;
259 184
260 if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD) 185 if (GNUNET_BLOCK_TYPE_GNS_NAMERECORD != type)
186 {
187 GNUNET_break (0);
261 return GNUNET_SYSERR; 188 return GNUNET_SYSERR;
189 }
262 if (block_size < sizeof(struct GNUNET_GNSRECORD_Block)) 190 if (block_size < sizeof(struct GNUNET_GNSRECORD_Block))
263 { 191 {
264 GNUNET_break_op (0); 192 GNUNET_break_op (0);
@@ -306,23 +234,16 @@ block_plugin_gns_check_reply (void *cls,
306 const void *reply_block, 234 const void *reply_block,
307 size_t reply_block_size) 235 size_t reply_block_size)
308{ 236{
309 const struct GNUNET_GNSRECORD_Block *block; 237 const struct GNUNET_GNSRECORD_Block *block = reply_block;
310 struct GNUNET_HashCode chash; 238 struct GNUNET_HashCode chash;
311 239
312 if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD) 240 if (GNUNET_BLOCK_TYPE_GNS_NAMERECORD != type)
313 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
314 /* this is a reply */
315 if (reply_block_size < sizeof(struct GNUNET_GNSRECORD_Block))
316 { 241 {
317 GNUNET_break_op (0); 242 GNUNET_break (0);
318 return GNUNET_BLOCK_REPLY_INVALID; 243 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
319 }
320 block = reply_block;
321 if (GNUNET_GNSRECORD_block_get_size (block) > reply_block_size)
322 {
323 GNUNET_break_op (0);
324 return GNUNET_BLOCK_REPLY_INVALID;
325 } 244 }
245 GNUNET_assert (reply_block_size >= sizeof(struct GNUNET_GNSRECORD_Block));
246 GNUNET_assert (GNUNET_GNSRECORD_block_get_size (block) > reply_block_size);
326 GNUNET_CRYPTO_hash (reply_block, 247 GNUNET_CRYPTO_hash (reply_block,
327 reply_block_size, 248 reply_block_size,
328 &chash); 249 &chash);
@@ -347,7 +268,6 @@ libgnunet_plugin_block_gns_init (void *cls)
347 struct GNUNET_BLOCK_PluginFunctions *api; 268 struct GNUNET_BLOCK_PluginFunctions *api;
348 269
349 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 270 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
350 api->evaluate = &block_plugin_gns_evaluate;
351 api->get_key = &block_plugin_gns_get_key; 271 api->get_key = &block_plugin_gns_get_key;
352 api->create_group = &block_plugin_gns_create_group; 272 api->create_group = &block_plugin_gns_create_group;
353 api->check_query = &block_plugin_gns_check_query; 273 api->check_query = &block_plugin_gns_check_query;
diff --git a/src/gns/plugin_gnsrecord_gns.c b/src/gns/plugin_gnsrecord_gns.c
index 391144925..dc7ffa9b2 100644
--- a/src/gns/plugin_gnsrecord_gns.c
+++ b/src/gns/plugin_gnsrecord_gns.c
@@ -64,8 +64,7 @@ gns_value_to_string (void *cls,
64 return GNUNET_IDENTITY_public_key_to_string (&pk); 64 return GNUNET_IDENTITY_public_key_to_string (&pk);
65 65
66 case GNUNET_GNSRECORD_TYPE_NICK: 66 case GNUNET_GNSRECORD_TYPE_NICK:
67 return GNUNET_strndup (data, data_size); 67 case GNUNET_GNSRECORD_TYPE_REDIRECT:
68
69 case GNUNET_GNSRECORD_TYPE_LEHO: 68 case GNUNET_GNSRECORD_TYPE_LEHO:
70 return GNUNET_strndup (data, data_size); 69 return GNUNET_strndup (data, data_size);
71 70
@@ -133,7 +132,9 @@ gns_value_to_string (void *cls,
133 GNUNET_free (ival); 132 GNUNET_free (ival);
134 return box_str; 133 return box_str;
135 } 134 }
136 135 case GNUNET_GNSRECORD_TYPE_TOMBSTONE: {
136 return GNUNET_strdup (_("This is a memento of an older block for internal maintenance."));
137 }
137 default: 138 default:
138 return NULL; 139 return NULL;
139 } 140 }
@@ -184,16 +185,13 @@ gns_string_to_value (void *cls,
184 if (record_type != type) 185 if (record_type != type)
185 { 186 {
186 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 187 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
187 _("Record type does not match parsed record type\n")); 188 _ ("Record type does not match parsed record type\n"));
188 return GNUNET_SYSERR; 189 return GNUNET_SYSERR;
189 } 190 }
190 return GNUNET_OK; 191 return GNUNET_OK;
191 192
192 case GNUNET_GNSRECORD_TYPE_NICK: 193 case GNUNET_GNSRECORD_TYPE_NICK:
193 *data = GNUNET_strdup (s); 194 case GNUNET_GNSRECORD_TYPE_REDIRECT:
194 *data_size = strlen (s);
195 return GNUNET_OK;
196
197 case GNUNET_GNSRECORD_TYPE_LEHO: 195 case GNUNET_GNSRECORD_TYPE_LEHO:
198 *data = GNUNET_strdup (s); 196 *data = GNUNET_strdup (s);
199 *data_size = strlen (s); 197 *data_size = strlen (s);
@@ -301,6 +299,12 @@ gns_string_to_value (void *cls,
301 GNUNET_free (bval); 299 GNUNET_free (bval);
302 return GNUNET_OK; 300 return GNUNET_OK;
303 } 301 }
302 case GNUNET_GNSRECORD_TYPE_TOMBSTONE: {
303 *data_size = 0;
304 *data = NULL;
305 return GNUNET_OK;
306 }
307
304 308
305 default: 309 default:
306 return GNUNET_SYSERR; 310 return GNUNET_SYSERR;
@@ -317,12 +321,16 @@ static struct
317 const char *name; 321 const char *name;
318 uint32_t number; 322 uint32_t number;
319} gns_name_map[] = { { "PKEY", GNUNET_GNSRECORD_TYPE_PKEY }, 323} gns_name_map[] = { { "PKEY", GNUNET_GNSRECORD_TYPE_PKEY },
320 { "EDKEY", GNUNET_GNSRECORD_TYPE_PKEY }, 324 { "EDKEY", GNUNET_GNSRECORD_TYPE_EDKEY },
321 { "NICK", GNUNET_GNSRECORD_TYPE_NICK }, 325 { "NICK", GNUNET_GNSRECORD_TYPE_NICK },
322 { "LEHO", GNUNET_GNSRECORD_TYPE_LEHO }, 326 { "LEHO", GNUNET_GNSRECORD_TYPE_LEHO },
323 { "VPN", GNUNET_GNSRECORD_TYPE_VPN }, 327 { "VPN", GNUNET_GNSRECORD_TYPE_VPN },
324 { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS }, 328 { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
325 { "BOX", GNUNET_GNSRECORD_TYPE_BOX }, 329 { "BOX", GNUNET_GNSRECORD_TYPE_BOX },
330 { "REDIRECT", GNUNET_GNSRECORD_TYPE_REDIRECT },
331 /* Tombstones should never be added manually
332 * so this makes sense, kind of */
333 { "\u271E", GNUNET_GNSRECORD_TYPE_TOMBSTONE },
326 { NULL, UINT32_MAX } }; 334 { NULL, UINT32_MAX } };
327 335
328 336
@@ -365,6 +373,19 @@ gns_number_to_typename (void *cls, uint32_t type)
365} 373}
366 374
367 375
376static enum GNUNET_GenericReturnValue
377gns_is_critical (void *cls, uint32_t type)
378{
379 return ((type == GNUNET_GNSRECORD_TYPE_PKEY) ||
380 (type == GNUNET_GNSRECORD_TYPE_EDKEY) ||
381 (type == GNUNET_GNSRECORD_TYPE_GNS2DNS) ||
382 (type == GNUNET_GNSRECORD_TYPE_REDIRECT) ?
383 GNUNET_YES : GNUNET_NO);
384}
385
386
387
388
368/** 389/**
369 * Entry point for the plugin. 390 * Entry point for the plugin.
370 * 391 *
@@ -381,6 +402,7 @@ libgnunet_plugin_gnsrecord_gns_init (void *cls)
381 api->string_to_value = &gns_string_to_value; 402 api->string_to_value = &gns_string_to_value;
382 api->typename_to_number = &gns_typename_to_number; 403 api->typename_to_number = &gns_typename_to_number;
383 api->number_to_typename = &gns_number_to_typename; 404 api->number_to_typename = &gns_number_to_typename;
405 api->is_critical = &gns_is_critical;
384 return api; 406 return api;
385} 407}
386 408
diff --git a/src/gns/test_gns_cname_lookup.sh b/src/gns/test_gns_cname_lookup.sh
deleted file mode 100755
index 3a189e1e2..000000000
--- a/src/gns/test_gns_cname_lookup.sh
+++ /dev/null
@@ -1,99 +0,0 @@
1#!/bin/sh
2# This file is in the public domain.
3trap "gnunet-arm -e -c test_gns_lookup.conf" INT
4
5LOCATION=$(which gnunet-config)
6if [ -z $LOCATION ]
7then
8 LOCATION="gnunet-config"
9fi
10$LOCATION --version 1> /dev/null
11if test $? != 0
12then
13 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
14 exit 77
15fi
16
17# permissive DNS resolver we will use for the test
18DNS_RESOLVER="8.8.8.8"
19if ! nslookup gnunet.org $DNS_RESOLVER > /dev/null 2>&1
20then
21 echo "Cannot reach DNS, skipping test"
22 exit 77
23fi
24
25
26rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
27
28TEST_IP_PLUS="127.0.0.1"
29TEST_IP_DNS="131.159.74.67"
30TEST_RECORD_CNAME_SERVER="server"
31TEST_RECORD_CNAME_PLUS="server.+"
32TEST_RECORD_CNAME_DNS="gnunet.org"
33TEST_RECORD_NAME_SERVER="server"
34TEST_RECORD_NAME_PLUS="www"
35TEST_RECORD_NAME_ZKEY="www2"
36TEST_RECORD_NAME_DNS="www3"
37MY_EGO="myego"
38TEST_DOMAIN_PLUS="www.$MY_EGO"
39TEST_DOMAIN_ZKEY="www2.$MY_EGO"
40TEST_DOMAIN_DNS="www3.$MY_EGO"
41which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 15"
42
43gnunet-arm -s -c test_gns_lookup.conf
44gnunet-identity -C $MY_EGO -c test_gns_lookup.conf
45MY_EGO_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep ${MY_EGO} | awk '{print $3}')
46TEST_RECORD_CNAME_ZKEY="server.${MY_EGO_PKEY}"
47gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME_DNS -t CNAME -V $TEST_RECORD_CNAME_DNS -e never -c test_gns_lookup.conf
48gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME_PLUS -t CNAME -V $TEST_RECORD_CNAME_PLUS -e never -c test_gns_lookup.conf
49gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME_ZKEY -t CNAME -V $TEST_RECORD_CNAME_ZKEY -e never -c test_gns_lookup.conf
50gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_CNAME_SERVER -t A -V $TEST_IP_PLUS -e never -c test_gns_lookup.conf
51RES_CNAME=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_PLUS -t A -c test_gns_lookup.conf`
52RES_CNAME_RAW=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_PLUS -t CNAME -c test_gns_lookup.conf`
53RES_CNAME_ZKEY=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_ZKEY -t A -c test_gns_lookup.conf`
54RES_CNAME_DNS=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_DNS -t A -c test_gns_lookup.conf | grep $TEST_IP_DNS`
55
56TESTEGOZONE=`gnunet-identity -c test_gns_lookup.conf -d | awk '{print $3}'`
57gnunet-namestore -p -z $MY_EGO -d -n $TEST_RECORD_NAME_DNS -t CNAME -V $TEST_RECORD_CNAME_DNS -e never -c test_gns_lookup.conf
58gnunet-namestore -p -z $MY_EGO -d -n $TEST_RECORD_NAME_PLUS -t CNAME -V $TEST_RECORD_CNAME_PLUS -e never -c test_gns_lookup.conf
59gnunet-namestore -p -z $MY_EGO -d -n $TEST_RECORD_NAME_ZKEY -t CNAME -V $TEST_RECORD_CNAME_ZKEY -e never -c test_gns_lookup.conf
60gnunet-namestore -p -z $MY_EGO -d -n $TEST_RECORD_CNAME_SERVER -t A -V $TEST_IP_PLUS -e never -c test_gns_lookup.conf
61gnunet-identity -D $MY_EGO -c test_gns_lookup.conf
62gnunet-arm -e -c test_gns_lookup.conf
63rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
64
65# make cmp case-insensitive by converting to lower case first
66RES_CNAME_RAW=`echo $RES_CNAME_RAW | tr [A-Z] [a-z]`
67TESTEGOZONE=`echo $TESTEGOZONE | tr [A-Z] [a-z]`
68if [ "$RES_CNAME_RAW" = "server.$TESTEGOZONE" ]
69then
70 echo "PASS: CNAME resolution from GNS"
71else
72 echo "FAIL: CNAME resolution from GNS, got $RES_CNAME_RAW, expected server.$TESTEGOZONE."
73 exit 1
74fi
75
76if [ "$RES_CNAME" = "$TEST_IP_PLUS" ]
77then
78 echo "PASS: IP resolution from GNS (.+)"
79else
80 echo "FAIL: IP resolution from GNS (.+), got $RES_CNAME, expected $TEST_IP_PLUS."
81 exit 1
82fi
83
84if [ "$RES_CNAME_ZKEY" = "$TEST_IP_PLUS" ]
85then
86 echo "PASS: IP resolution from GNS (.zkey)"
87else
88 echo "FAIL: IP resolution from GNS (.zkey), got $RES_CNAME, expected $TEST_IP_PLUS."
89 exit 1
90fi
91
92if echo "$RES_CNAME_DNS" | grep "$TEST_IP_DNS" > /dev/null
93then
94 echo "PASS: IP resolution from DNS"
95 exit 0
96else
97 echo "FAIL: IP resolution from DNS, got $RES_CNAME_DNS, expected $TEST_IP_DNS."
98 exit 1
99fi
diff --git a/src/gns/test_gns_gns2dns_cname_lookup.sh b/src/gns/test_gns_gns2dns_cname_lookup.sh
index ce1afacf4..9315f6b2f 100755
--- a/src/gns/test_gns_gns2dns_cname_lookup.sh
+++ b/src/gns/test_gns_gns2dns_cname_lookup.sh
@@ -16,9 +16,11 @@ fi
16 16
17rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` 17rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
18# IP address of 'www.gnunet.org' 18# IP address of 'www.gnunet.org'
19TEST_IP="131.159.74.67" 19TEST_IP="147.87.255.218"
20# IP address of 'gnunet.org'
21TEST_IPALT="131.159.74.67"
20# IPv6 address of 'gnunet.org' 22# IPv6 address of 'gnunet.org'
21TEST_IP6="2001:4ca0:2001:42:225:90ff:fe6b:d60" 23TEST_IP6="2a07:6b47:100:464::9357:ffdb"
22 24
23# main label used during resolution 25# main label used during resolution
24TEST_RECORD_NAME="homepage" 26TEST_RECORD_NAME="homepage"
@@ -46,7 +48,7 @@ TEST_DOMAIN="www.${TEST_RECORD_NAME}.$MY_EGO"
46which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 15" 48which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 15"
47 49
48gnunet-arm -s -c test_gns_lookup.conf 50gnunet-arm -s -c test_gns_lookup.conf
49OUT=`$DO_TIMEOUT gnunet-resolver -c test_gns_lookup.conf gnunet.org` 51OUT=`$DO_TIMEOUT gnunet-resolver -c test_gns_lookup.conf www.gnunet.org`
50echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found ($OUT), skipping test"; exit 77; } 52echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found ($OUT), skipping test"; exit 77; }
51echo $OUT | grep $TEST_IP6 - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found ($OUT), skipping test"; exit 77; } 53echo $OUT | grep $TEST_IP6 - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found ($OUT), skipping test"; exit 77; }
52 54
@@ -59,6 +61,7 @@ gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECOR
59gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS2 -e never -c test_gns_lookup.conf 61gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS2 -e never -c test_gns_lookup.conf
60gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS3 -e never -c test_gns_lookup.conf 62gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS3 -e never -c test_gns_lookup.conf
61 63
64gnunet-namestore -z $MY_EGO -D -c test_gns_lookup.conf
62 65
63echo "EGOs:" 66echo "EGOs:"
64gnunet-identity -d 67gnunet-identity -d
diff --git a/src/gns/test_gns_gns2dns_lookup.sh b/src/gns/test_gns_gns2dns_lookup.sh
index dcad594b3..240e441a4 100755
--- a/src/gns/test_gns_gns2dns_lookup.sh
+++ b/src/gns/test_gns_gns2dns_lookup.sh
@@ -17,9 +17,11 @@ rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
17# IP address of 'docs.gnunet.org' 17# IP address of 'docs.gnunet.org'
18TEST_IP_ALT2="147.87.255.218" 18TEST_IP_ALT2="147.87.255.218"
19# IP address of 'www.gnunet.org' 19# IP address of 'www.gnunet.org'
20TEST_IP="131.159.74.67" 20TEST_IP="147.87.255.218"
21# IP address of 'gnunet.org'
22TEST_IP_ALT="131.159.74.67"
21# IPv6 address of 'gnunet.org' 23# IPv6 address of 'gnunet.org'
22TEST_IP6="2001:4ca0:2001:42:225:90ff:fe6b:d60" 24TEST_IP6="2a07:6b47:100:464::9357:ffdb"
23# permissive DNS resolver we will use for the test 25# permissive DNS resolver we will use for the test
24TEST_IP_GNS2DNS="8.8.8.8" 26TEST_IP_GNS2DNS="8.8.8.8"
25 27
@@ -49,7 +51,7 @@ which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 15"
49 51
50gnunet-arm -s -c test_gns_lookup.conf 52gnunet-arm -s -c test_gns_lookup.conf
51 53
52OUT=`$DO_TIMEOUT gnunet-resolver -c test_gns_lookup.conf gnunet.org` 54OUT=`$DO_TIMEOUT gnunet-resolver -c test_gns_lookup.conf www.gnunet.org`
53echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found ($OUT), skipping test"; exit 77; } 55echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found ($OUT), skipping test"; exit 77; }
54echo $OUT | grep $TEST_IP6 - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found ($OUT), skipping test"; exit 77; } 56echo $OUT | grep $TEST_IP6 - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found ($OUT), skipping test"; exit 77; }
55 57
@@ -69,7 +71,7 @@ gnunet-identity -d
69# lookup 'www.gnunet.org', IPv4 71# lookup 'www.gnunet.org', IPv4
70RES_IP=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN -t A -c test_gns_lookup.conf` 72RES_IP=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN -t A -c test_gns_lookup.conf`
71# lookup 'www.gnunet.org', IPv6 73# lookup 'www.gnunet.org', IPv6
72RES_IP6=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN -t AAAA -c test_gns_lookup.conf` 74RES_IP6=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN -t AAAA -c test_gns_lookup.conf | head -n1`
73# lookup 'gnunet.org', IPv4 75# lookup 'gnunet.org', IPv4
74RES_IP_ALT=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_ALT -t A -c test_gns_lookup.conf` 76RES_IP_ALT=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_ALT -t A -c test_gns_lookup.conf`
75# lookup 'docs.gnunet.org', IPv4 77# lookup 'docs.gnunet.org', IPv4
@@ -91,7 +93,7 @@ else
91 ret=1 93 ret=1
92fi 94fi
93 95
94if [ "$RES_IP6" = "$TEST_IP6" ] 96if [ "${RES_IP6%?}" = "${TEST_IP6%?}" ]
95then 97then
96 echo "PASS: Resolved $TEST_DOMAIN to $RES_IP6." 98 echo "PASS: Resolved $TEST_DOMAIN to $RES_IP6."
97else 99else
@@ -99,7 +101,7 @@ else
99 ret=1 101 ret=1
100fi 102fi
101 103
102if echo "$RES_IP_ALT" | grep "$TEST_IP" > /dev/null 104if echo "$RES_IP_ALT" | grep "$TEST_IP_ALT" > /dev/null
103then 105then
104 echo "PASS: Resolved $TEST_DOMAIN_ALT to $RES_IP_ALT." 106 echo "PASS: Resolved $TEST_DOMAIN_ALT to $RES_IP_ALT."
105else 107else
diff --git a/src/gns/test_gns_gns2dns_zkey_lookup.sh b/src/gns/test_gns_gns2dns_zkey_lookup.sh
index 1f8e34c42..a299c34b6 100755
--- a/src/gns/test_gns_gns2dns_zkey_lookup.sh
+++ b/src/gns/test_gns_gns2dns_zkey_lookup.sh
@@ -17,9 +17,11 @@ rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
17# IP address of 'docs.gnunet.org' 17# IP address of 'docs.gnunet.org'
18TEST_IP_ALT2="147.87.255.218" 18TEST_IP_ALT2="147.87.255.218"
19# IP address of 'www.gnunet.org' 19# IP address of 'www.gnunet.org'
20TEST_IP="131.159.74.67" 20TEST_IP="147.87.255.218"
21# IP address of 'www.gnunet.org'
22TEST_IP_ALT="131.159.74.67"
21# IPv6 address of 'gnunet.org' 23# IPv6 address of 'gnunet.org'
22TEST_IP6="2001:4ca0:2001:42:225:90ff:fe6b:d60" 24TEST_IP6="2a07:6b47:100:464::9357:ffdb"
23# permissive DNS resolver we will use for the test 25# permissive DNS resolver we will use for the test
24TEST_IP_GNS2DNS="8.8.8.8" 26TEST_IP_GNS2DNS="8.8.8.8"
25 27
@@ -46,7 +48,7 @@ which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 15"
46 48
47gnunet-arm -s -c test_gns_lookup.conf 49gnunet-arm -s -c test_gns_lookup.conf
48 50
49OUT=`$DO_TIMEOUT gnunet-resolver -c test_gns_lookup.conf gnunet.org` 51OUT=`$DO_TIMEOUT gnunet-resolver -c test_gns_lookup.conf www.gnunet.org`
50echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found ($OUT), skipping test"; exit 77; } 52echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found ($OUT), skipping test"; exit 77; }
51echo $OUT | grep $TEST_IP6 - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found ($OUT), skipping test"; exit 77; } 53echo $OUT | grep $TEST_IP6 - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found ($OUT), skipping test"; exit 77; }
52 54
@@ -66,7 +68,7 @@ gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECOR
66# lookup 'www.gnunet.org', IPv4 68# lookup 'www.gnunet.org', IPv4
67RES_IP=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN -t A -c test_gns_lookup.conf` 69RES_IP=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN -t A -c test_gns_lookup.conf`
68# lookup 'www.gnunet.org', IPv6 70# lookup 'www.gnunet.org', IPv6
69RES_IP6=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN -t AAAA -c test_gns_lookup.conf` 71RES_IP6=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN -t AAAA -c test_gns_lookup.conf | head -n1`
70# lookup 'gnunet.org', IPv4 72# lookup 'gnunet.org', IPv4
71RES_IP_ALT=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_ALT -t A -c test_gns_lookup.conf` 73RES_IP_ALT=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_ALT -t A -c test_gns_lookup.conf`
72# lookup 'docs.gnunet.org', IPv4 74# lookup 'docs.gnunet.org', IPv4
@@ -88,7 +90,7 @@ else
88 ret=1 90 ret=1
89fi 91fi
90 92
91if [ "$RES_IP6" = "$TEST_IP6" ] 93if [ "${RES_IP6%?}" = "${TEST_IP6%?}" ]
92then 94then
93 echo "PASS: Resolved $TEST_DOMAIN to $RES_IP6." 95 echo "PASS: Resolved $TEST_DOMAIN to $RES_IP6."
94else 96else
@@ -96,7 +98,7 @@ else
96 ret=1 98 ret=1
97fi 99fi
98 100
99if echo "$RES_IP_ALT" | grep "$TEST_IP" > /dev/null 101if echo "$RES_IP_ALT" | grep "$TEST_IP_ALT" > /dev/null
100then 102then
101 echo "PASS: Resolved $TEST_DOMAIN_ALT to $RES_IP_ALT." 103 echo "PASS: Resolved $TEST_DOMAIN_ALT to $RES_IP_ALT."
102else 104else
diff --git a/src/gns/test_gns_redirect_lookup.sh b/src/gns/test_gns_redirect_lookup.sh
new file mode 100755
index 000000000..dfe5087ef
--- /dev/null
+++ b/src/gns/test_gns_redirect_lookup.sh
@@ -0,0 +1,100 @@
1#!/bin/sh
2# This file is in the public domain.
3trap "gnunet-arm -e -c test_gns_lookup.conf" INT
4
5LOCATION=$(which gnunet-config)
6if [ -z $LOCATION ]
7then
8 LOCATION="gnunet-config"
9fi
10$LOCATION --version 1> /dev/null
11if test $? != 0
12then
13 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
14 exit 77
15fi
16
17# permissive DNS resolver we will use for the test
18DNS_RESOLVER="8.8.8.8"
19if ! nslookup gnunet.org $DNS_RESOLVER > /dev/null 2>&1
20then
21 echo "Cannot reach DNS, skipping test"
22 exit 77
23fi
24
25
26rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
27
28TEST_IP_PLUS="127.0.0.1"
29TEST_IP_DNS="131.159.74.67"
30TEST_RECORD_REDIRECT_SERVER="server"
31TEST_RECORD_REDIRECT_PLUS="server.+"
32TEST_RECORD_REDIRECT_DNS="gnunet.org"
33TEST_RECORD_NAME_SERVER="server"
34TEST_RECORD_NAME_PLUS="www"
35TEST_RECORD_NAME_ZKEY="www2"
36TEST_RECORD_NAME_DNS="www3"
37MY_EGO="myego"
38TEST_DOMAIN_PLUS="www.$MY_EGO"
39TEST_DOMAIN_ZKEY="www2.$MY_EGO"
40TEST_DOMAIN_DNS="www3.$MY_EGO"
41which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 15"
42
43gnunet-arm -s -c test_gns_lookup.conf
44gnunet-identity -C $MY_EGO -c test_gns_lookup.conf
45MY_EGO_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep ${MY_EGO} | awk '{print $3}')
46TEST_RECORD_REDIRECT_ZKEY="server.${MY_EGO_PKEY}"
47gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME_DNS -t REDIRECT -V $TEST_RECORD_REDIRECT_DNS -e never -c test_gns_lookup.conf
48gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME_PLUS -t REDIRECT -V $TEST_RECORD_REDIRECT_PLUS -e never -c test_gns_lookup.conf
49gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME_ZKEY -t REDIRECT -V $TEST_RECORD_REDIRECT_ZKEY -e never -c test_gns_lookup.conf
50gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_REDIRECT_SERVER -t A -V $TEST_IP_PLUS -e never -c test_gns_lookup.conf
51gnunet-namestore -D -z $MY_EGO
52RES_REDIRECT=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_PLUS -t A -c test_gns_lookup.conf`
53RES_REDIRECT_RAW=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_PLUS -t REDIRECT -c test_gns_lookup.conf`
54RES_REDIRECT_ZKEY=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_ZKEY -t A -c test_gns_lookup.conf`
55RES_REDIRECT_DNS=`$DO_TIMEOUT gnunet-gns --raw -u $TEST_DOMAIN_DNS -t A -c test_gns_lookup.conf | grep $TEST_IP_DNS`
56
57TESTEGOZONE=`gnunet-identity -c test_gns_lookup.conf -d | awk '{print $3}'`
58gnunet-namestore -p -z $MY_EGO -d -n $TEST_RECORD_NAME_DNS -t REDIRECT -V $TEST_RECORD_REDIRECT_DNS -e never -c test_gns_lookup.conf
59gnunet-namestore -p -z $MY_EGO -d -n $TEST_RECORD_NAME_PLUS -t REDIRECT -V $TEST_RECORD_REDIRECT_PLUS -e never -c test_gns_lookup.conf
60gnunet-namestore -p -z $MY_EGO -d -n $TEST_RECORD_NAME_ZKEY -t REDIRECT -V $TEST_RECORD_REDIRECT_ZKEY -e never -c test_gns_lookup.conf
61gnunet-namestore -p -z $MY_EGO -d -n $TEST_RECORD_REDIRECT_SERVER -t A -V $TEST_IP_PLUS -e never -c test_gns_lookup.conf
62gnunet-identity -D $MY_EGO -c test_gns_lookup.conf
63gnunet-arm -e -c test_gns_lookup.conf
64rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
65
66# make cmp case-insensitive by converting to lower case first
67RES_REDIRECT_RAW=`echo $RES_REDIRECT_RAW | tr [A-Z] [a-z]`
68TESTEGOZONE=`echo $TESTEGOZONE | tr [A-Z] [a-z]`
69if [ "$RES_REDIRECT_RAW" = "server.$TESTEGOZONE" ]
70then
71 echo "PASS: REDIRECT resolution from GNS"
72else
73 echo "FAIL: REDIRECT resolution from GNS, got $RES_REDIRECT_RAW, expected server.$TESTEGOZONE."
74 exit 1
75fi
76
77if [ "$RES_REDIRECT" = "$TEST_IP_PLUS" ]
78then
79 echo "PASS: IP resolution from GNS (.+)"
80else
81 echo "FAIL: IP resolution from GNS (.+), got $RES_REDIRECT, expected $TEST_IP_PLUS."
82 exit 1
83fi
84
85if [ "$RES_REDIRECT_ZKEY" = "$TEST_IP_PLUS" ]
86then
87 echo "PASS: IP resolution from GNS (.zkey)"
88else
89 echo "FAIL: IP resolution from GNS (.zkey), got $RES_REDIRECT, expected $TEST_IP_PLUS."
90 exit 1
91fi
92
93if echo "$RES_REDIRECT_DNS" | grep "$TEST_IP_DNS" > /dev/null
94then
95 echo "PASS: IP resolution from DNS"
96 exit 0
97else
98 echo "FAIL: IP resolution from DNS, got $RES_REDIRECT_DNS, expected $TEST_IP_DNS."
99 exit 1
100fi
diff --git a/src/gnsrecord/Makefile.am b/src/gnsrecord/Makefile.am
index 4308d9c1a..e2538b1a2 100644
--- a/src/gnsrecord/Makefile.am
+++ b/src/gnsrecord/Makefile.am
@@ -20,7 +20,6 @@ check_PROGRAMS = \
20 test_gnsrecord_crypto \ 20 test_gnsrecord_crypto \
21 test_gnsrecord_serialization \ 21 test_gnsrecord_serialization \
22 test_gnsrecord_block_expiration \ 22 test_gnsrecord_block_expiration \
23 test_gnsrecord_testvectors \
24 perf_gnsrecord_crypto 23 perf_gnsrecord_crypto
25 24
26if ENABLE_TEST_RUN 25if ENABLE_TEST_RUN
@@ -35,7 +34,8 @@ lib_LTLIBRARIES = \
35 libgnunetgnsrecordjson.la 34 libgnunetgnsrecordjson.la
36 35
37gnunet_gnsrecord_tvg_SOURCES = \ 36gnunet_gnsrecord_tvg_SOURCES = \
38 gnunet-gnsrecord-tvg.c 37 gnunet-gnsrecord-tvg.c \
38 gnsrecord_crypto.h
39gnunet_gnsrecord_tvg_LDADD = \ 39gnunet_gnsrecord_tvg_LDADD = \
40 $(top_builddir)/src/util/libgnunetutil.la \ 40 $(top_builddir)/src/util/libgnunetutil.la \
41 $(top_builddir)/src/identity/libgnunetidentity.la \ 41 $(top_builddir)/src/identity/libgnunetidentity.la \
@@ -86,13 +86,13 @@ libgnunet_plugin_gnsrecord_dns_la_LDFLAGS = \
86EXTRA_DIST = \ 86EXTRA_DIST = \
87 $(check_SCRIPTS) 87 $(check_SCRIPTS)
88 88
89test_gnsrecord_testvectors_SOURCES = \ 89#test_gnsrecord_testvectors_SOURCES = \
90 test_gnsrecord_testvectors.c 90# test_gnsrecord_testvectors.c
91test_gnsrecord_testvectors_LDADD = \ 91#test_gnsrecord_testvectors_LDADD = \
92 $(top_builddir)/src/testing/libgnunettesting.la \ 92# $(top_builddir)/src/testing/libgnunettesting.la \
93 $(top_builddir)/src/identity/libgnunetidentity.la \ 93# $(top_builddir)/src/identity/libgnunetidentity.la \
94 libgnunetgnsrecord.la \ 94# libgnunetgnsrecord.la \
95 $(top_builddir)/src/util/libgnunetutil.la 95# $(top_builddir)/src/util/libgnunetutil.la
96 96
97 97
98test_gnsrecord_serialization_SOURCES = \ 98test_gnsrecord_serialization_SOURCES = \
diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c
index e9994a868..52c480ef6 100644
--- a/src/gnsrecord/gnsrecord.c
+++ b/src/gnsrecord/gnsrecord.c
@@ -260,4 +260,25 @@ GNUNET_GNSRECORD_number_to_typename (uint32_t type)
260} 260}
261 261
262 262
263enum GNUNET_GenericReturnValue
264GNUNET_GNSRECORD_is_critical (uint32_t type)
265{
266 struct Plugin *plugin;
267
268 if (GNUNET_GNSRECORD_TYPE_ANY == type)
269 return GNUNET_NO;
270 init ();
271 for (unsigned int i = 0; i < num_plugins; i++)
272 {
273 plugin = gns_plugins[i];
274 if (NULL == plugin->api->is_critical)
275 continue;
276 if (GNUNET_NO == plugin->api->is_critical (plugin->api->cls, type))
277 continue;
278 return GNUNET_YES;
279 }
280 return GNUNET_NO;
281}
282
283
263/* end of gnsrecord.c */ 284/* end of gnsrecord.c */
diff --git a/src/gnsrecord/gnsrecord_crypto.c b/src/gnsrecord/gnsrecord_crypto.c
index 890ddb011..ff92911de 100644
--- a/src/gnsrecord/gnsrecord_crypto.c
+++ b/src/gnsrecord/gnsrecord_crypto.c
@@ -223,7 +223,6 @@ block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
223 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; 223 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2];
224 unsigned char skey[GNUNET_CRYPTO_AES_KEY_LENGTH]; 224 unsigned char skey[GNUNET_CRYPTO_AES_KEY_LENGTH];
225 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)]; 225 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)];
226 uint32_t rd_count_nbo;
227 struct GNUNET_TIME_Absolute now; 226 struct GNUNET_TIME_Absolute now;
228 227
229 if (payload_len < 0) 228 if (payload_len < 0)
@@ -254,7 +253,6 @@ block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
254 /* serialize */ 253 /* serialize */
255 *block = GNUNET_malloc (sizeof (struct GNUNET_GNSRECORD_Block) + payload_len); 254 *block = GNUNET_malloc (sizeof (struct GNUNET_GNSRECORD_Block) + payload_len);
256 (*block)->size = htonl(sizeof (struct GNUNET_GNSRECORD_Block) + payload_len); 255 (*block)->size = htonl(sizeof (struct GNUNET_GNSRECORD_Block) + payload_len);
257 rd_count_nbo = htonl (rd_count);
258 { 256 {
259 char payload[payload_len]; 257 char payload[payload_len];
260 258
@@ -282,12 +280,12 @@ block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
282 label, 280 label,
283 ecblock->expiration_time.abs_value_us__, 281 ecblock->expiration_time.abs_value_us__,
284 pkey); 282 pkey);
285 GNUNET_break (payload_len == 283 GNUNET_assert (payload_len ==
286 ecdsa_symmetric_encrypt (payload, 284 ecdsa_symmetric_encrypt (payload,
287 payload_len, 285 payload_len,
288 skey, 286 skey,
289 ctr, 287 ctr,
290 &ecblock[1])); 288 &ecblock[1]));
291 GNUNET_memcpy (&gnr_block[1], &ecblock[1], payload_len); 289 GNUNET_memcpy (&gnr_block[1], &ecblock[1], payload_len);
292 } 290 }
293 if (GNUNET_OK != 291 if (GNUNET_OK !=
@@ -298,8 +296,10 @@ block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
298 GNUNET_break (0); 296 GNUNET_break (0);
299 GNUNET_free (*block); 297 GNUNET_free (*block);
300 GNUNET_free (dkey); 298 GNUNET_free (dkey);
299 GNUNET_free (gnr_block);
301 return GNUNET_SYSERR; 300 return GNUNET_SYSERR;
302 } 301 }
302 GNUNET_free (gnr_block);
303 GNUNET_free (dkey); 303 GNUNET_free (dkey);
304 return GNUNET_OK; 304 return GNUNET_OK;
305} 305}
@@ -348,7 +348,6 @@ block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key,
348 unsigned char nonce[crypto_secretbox_NONCEBYTES]; 348 unsigned char nonce[crypto_secretbox_NONCEBYTES];
349 unsigned char skey[crypto_secretbox_KEYBYTES]; 349 unsigned char skey[crypto_secretbox_KEYBYTES];
350 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)]; 350 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)];
351 uint32_t rd_count_nbo;
352 struct GNUNET_TIME_Absolute now; 351 struct GNUNET_TIME_Absolute now;
353 352
354 if (payload_len < 0) 353 if (payload_len < 0)
@@ -381,7 +380,6 @@ block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key,
381 + payload_len + crypto_secretbox_MACBYTES); 380 + payload_len + crypto_secretbox_MACBYTES);
382 (*block)->size = htonl(sizeof (struct GNUNET_GNSRECORD_Block) 381 (*block)->size = htonl(sizeof (struct GNUNET_GNSRECORD_Block)
383 + payload_len + crypto_secretbox_MACBYTES); 382 + payload_len + crypto_secretbox_MACBYTES);
384 rd_count_nbo = htonl (rd_count);
385 { 383 {
386 char payload[payload_len]; 384 char payload[payload_len];
387 385
@@ -415,12 +413,12 @@ block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key,
415 label, 413 label,
416 edblock->expiration_time.abs_value_us__, 414 edblock->expiration_time.abs_value_us__,
417 pkey); 415 pkey);
418 GNUNET_break (GNUNET_OK == 416 GNUNET_assert (GNUNET_OK ==
419 eddsa_symmetric_encrypt (payload, 417 eddsa_symmetric_encrypt (payload,
420 payload_len, 418 payload_len,
421 skey, 419 skey,
422 nonce, 420 nonce,
423 &edblock[1])); 421 &edblock[1]));
424 GNUNET_memcpy (&gnr_block[1], &edblock[1], 422 GNUNET_memcpy (&gnr_block[1], &edblock[1],
425 payload_len + crypto_secretbox_MACBYTES); 423 payload_len + crypto_secretbox_MACBYTES);
426 424
@@ -438,7 +436,7 @@ GNUNET_GNSRECORD_block_calculate_size (const struct
438 unsigned int rd_count) 436 unsigned int rd_count)
439{ 437{
440 struct GNUNET_IDENTITY_PublicKey pkey; 438 struct GNUNET_IDENTITY_PublicKey pkey;
441 ssize_t res; 439 ssize_t res = -1;
442 440
443 GNUNET_IDENTITY_key_get_public (key, 441 GNUNET_IDENTITY_key_get_public (key,
444 &pkey); 442 &pkey);
@@ -453,7 +451,7 @@ GNUNET_GNSRECORD_block_calculate_size (const struct
453 default: 451 default:
454 GNUNET_assert (0); 452 GNUNET_assert (0);
455 } 453 }
456 return -1; 454 return res;
457 455
458} 456}
459 457
@@ -593,8 +591,9 @@ GNUNET_GNSRECORD_block_verify (const struct GNUNET_GNSRECORD_Block *block)
593 purp = GNUNET_malloc (sizeof (struct GNRBlockPS) + payload_len); 591 purp = GNUNET_malloc (sizeof (struct GNRBlockPS) + payload_len);
594 purp->purpose.size = htonl (sizeof (struct GNRBlockPS) + payload_len); 592 purp->purpose.size = htonl (sizeof (struct GNRBlockPS) + payload_len);
595 purp->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); 593 purp->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
596 GNUNET_memcpy (&purp[1], &block[1], payload_len); 594 GNUNET_memcpy (&purp[1],
597 595 &block[1],
596 payload_len);
598 switch (ntohl (block->type)) 597 switch (ntohl (block->type))
599 { 598 {
600 case GNUNET_GNSRECORD_TYPE_PKEY: 599 case GNUNET_GNSRECORD_TYPE_PKEY:
@@ -650,10 +649,10 @@ block_decrypt_ecdsa (const struct GNUNET_GNSRECORD_Block *block,
650 char payload[payload_len]; 649 char payload[payload_len];
651 unsigned int rd_count; 650 unsigned int rd_count;
652 651
653 GNUNET_break (payload_len == 652 GNUNET_assert (payload_len ==
654 ecdsa_symmetric_decrypt (&block[1], payload_len, 653 ecdsa_symmetric_decrypt (&block[1], payload_len,
655 key, ctr, 654 key, ctr,
656 payload)); 655 payload));
657 rd_count = GNUNET_GNSRECORD_records_deserialize_get_size (payload_len, 656 rd_count = GNUNET_GNSRECORD_records_deserialize_get_size (payload_len,
658 payload); 657 payload);
659 if (rd_count > 2048) 658 if (rd_count > 2048)
@@ -754,7 +753,6 @@ block_decrypt_eddsa (const struct GNUNET_GNSRECORD_Block *block,
754 GNUNET_GNSRECORD_RecordCallback proc, 753 GNUNET_GNSRECORD_RecordCallback proc,
755 void *proc_cls) 754 void *proc_cls)
756{ 755{
757 const struct GNUNET_GNSRECORD_EddsaBlock *edblock = &block->eddsa_block;
758 size_t payload_len = ntohl (block->size) - sizeof (struct 756 size_t payload_len = ntohl (block->size) - sizeof (struct
759 GNUNET_GNSRECORD_Block); 757 GNUNET_GNSRECORD_Block);
760 unsigned char nonce[crypto_secretbox_NONCEBYTES]; 758 unsigned char nonce[crypto_secretbox_NONCEBYTES];
@@ -776,10 +774,10 @@ block_decrypt_eddsa (const struct GNUNET_GNSRECORD_Block *block,
776 char payload[payload_len]; 774 char payload[payload_len];
777 unsigned int rd_count; 775 unsigned int rd_count;
778 776
779 GNUNET_break (GNUNET_OK == 777 GNUNET_assert (GNUNET_OK ==
780 eddsa_symmetric_decrypt (&block[1], payload_len, 778 eddsa_symmetric_decrypt (&block[1], payload_len,
781 key, nonce, 779 key, nonce,
782 payload)); 780 payload));
783 payload_len -= crypto_secretbox_MACBYTES; 781 payload_len -= crypto_secretbox_MACBYTES;
784 rd_count = GNUNET_GNSRECORD_records_deserialize_get_size (payload_len, 782 rd_count = GNUNET_GNSRECORD_records_deserialize_get_size (payload_len,
785 payload); 783 payload);
@@ -909,7 +907,7 @@ GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block,
909 proc_cls); 907 proc_cls);
910 break; 908 break;
911 default: 909 default:
912 return GNUNET_SYSERR; 910 res = GNUNET_SYSERR;
913 } 911 }
914 GNUNET_free (norm_label); 912 GNUNET_free (norm_label);
915 return res; 913 return res;
diff --git a/src/gnsrecord/gnsrecord_misc.c b/src/gnsrecord/gnsrecord_misc.c
index 61604c730..54d8fb860 100644
--- a/src/gnsrecord/gnsrecord_misc.c
+++ b/src/gnsrecord/gnsrecord_misc.c
@@ -38,23 +38,26 @@
38#define LOG(kind, ...) GNUNET_log_from (kind, "gnsrecord", __VA_ARGS__) 38#define LOG(kind, ...) GNUNET_log_from (kind, "gnsrecord", __VA_ARGS__)
39 39
40char * 40char *
41GNUNET_GNSRECORD_string_to_lowercase (const char *src) 41GNUNET_GNSRECORD_string_normalize (const char *src)
42{ 42{
43 char *res; 43 /*FIXME: We may want to follow RFC5890/RFC5891 */
44 44 return GNUNET_STRINGS_utf8_normalize (src);
45 res = GNUNET_strdup (src);
46 GNUNET_STRINGS_utf8_tolower (src, res);
47 return res;
48} 45}
49 46
50char * 47enum GNUNET_GenericReturnValue
51GNUNET_GNSRECORD_string_normalize (const char *src) 48GNUNET_GNSRECORD_label_check (const char*label, char **emsg)
52{ 49{
53 char *res; 50 if (NULL == label)
54 res = GNUNET_strdup (src); 51 {
55 GNUNET_STRINGS_utf8_tolower (src, res); 52 *emsg = GNUNET_strdup (_ ("Label is NULL which is not allowed\n"));
56 GNUNET_STRINGS_utf8_normalize (src, res); 53 return GNUNET_NO;
57 return res; 54 }
55 if (0 != strchr (label, '.'))
56 {
57 *emsg = GNUNET_strdup (_ ("Label contains `.' which is not allowed\n"));
58 return GNUNET_NO;
59 }
60 return GNUNET_OK;
58} 61}
59 62
60/** 63/**
@@ -144,19 +147,11 @@ GNUNET_GNSRECORD_records_cmp (const struct GNUNET_GNSRECORD_Data *a,
144} 147}
145 148
146 149
147/**
148 * Returns the expiration time of the given block of records. The block
149 * expiration time is the expiration time of the record with smallest
150 * expiration time.
151 *
152 * @param rd_count number of records given in @a rd
153 * @param rd array of records
154 * @return absolute expiration time
155 */
156struct GNUNET_TIME_Absolute 150struct GNUNET_TIME_Absolute
157GNUNET_GNSRECORD_record_get_expiration_time (unsigned int rd_count, 151GNUNET_GNSRECORD_record_get_expiration_time (unsigned int rd_count,
158 const struct 152 const struct
159 GNUNET_GNSRECORD_Data *rd) 153 GNUNET_GNSRECORD_Data *rd,
154 struct GNUNET_TIME_Absolute min)
160{ 155{
161 struct GNUNET_TIME_Absolute expire; 156 struct GNUNET_TIME_Absolute expire;
162 struct GNUNET_TIME_Absolute at; 157 struct GNUNET_TIME_Absolute at;
@@ -164,8 +159,8 @@ GNUNET_GNSRECORD_record_get_expiration_time (unsigned int rd_count,
164 struct GNUNET_TIME_Absolute at_shadow; 159 struct GNUNET_TIME_Absolute at_shadow;
165 struct GNUNET_TIME_Relative rt_shadow; 160 struct GNUNET_TIME_Relative rt_shadow;
166 161
167 if (NULL == rd) 162 if (0 == rd_count)
168 return GNUNET_TIME_UNIT_ZERO_ABS; 163 return GNUNET_TIME_absolute_max (GNUNET_TIME_UNIT_ZERO_ABS, min);
169 expire = GNUNET_TIME_UNIT_FOREVER_ABS; 164 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
170 for (unsigned int c = 0; c < rd_count; c++) 165 for (unsigned int c = 0; c < rd_count; c++)
171 { 166 {
@@ -202,6 +197,7 @@ GNUNET_GNSRECORD_record_get_expiration_time (unsigned int rd_count,
202 expire = GNUNET_TIME_absolute_min (at, 197 expire = GNUNET_TIME_absolute_min (at,
203 expire); 198 expire);
204 } 199 }
200 expire = GNUNET_TIME_absolute_max (expire, min);
205 LOG (GNUNET_ERROR_TYPE_DEBUG, 201 LOG (GNUNET_ERROR_TYPE_DEBUG,
206 "Determined expiration time for block with %u records to be %s\n", 202 "Determined expiration time for block with %u records to be %s\n",
207 rd_count, 203 rd_count,
@@ -284,12 +280,24 @@ GNUNET_GNSRECORD_identity_from_data (const char *data,
284{ 280{
285 if (GNUNET_NO == GNUNET_GNSRECORD_is_zonekey_type (type)) 281 if (GNUNET_NO == GNUNET_GNSRECORD_is_zonekey_type (type))
286 return GNUNET_SYSERR; 282 return GNUNET_SYSERR;
287 if (data_size > sizeof (struct GNUNET_IDENTITY_PublicKey)) 283 switch (type)
288 return GNUNET_SYSERR; 284 {
289 return (GNUNET_IDENTITY_read_key_from_buffer (key, data, data_size) == 285 case GNUNET_GNSRECORD_TYPE_PKEY:
290 data_size? 286 if (data_size > sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))
291 GNUNET_OK : 287 return GNUNET_SYSERR;
292 GNUNET_SYSERR); 288 memcpy (&key->ecdsa_key, data, data_size);
289 break;
290 case GNUNET_GNSRECORD_TYPE_EDKEY:
291 if (data_size > sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))
292 return GNUNET_SYSERR;
293 memcpy (&key->eddsa_key, data, data_size);
294 break;
295 default:
296 return GNUNET_NO;
297 }
298 key->type = htonl (type);
299
300 return GNUNET_YES;
293} 301}
294 302
295 303
@@ -302,16 +310,11 @@ GNUNET_GNSRECORD_data_from_identity (const struct
302{ 310{
303 char *tmp; 311 char *tmp;
304 *type = ntohl (key->type); 312 *type = ntohl (key->type);
305 *data_size = GNUNET_IDENTITY_key_get_length (key); 313 *data_size = GNUNET_IDENTITY_key_get_length (key) - sizeof (key->type);
306 if (0 == *data_size) 314 if (0 == *data_size)
307 return GNUNET_SYSERR; 315 return GNUNET_SYSERR;
308 tmp = GNUNET_malloc (*data_size); 316 tmp = GNUNET_malloc (*data_size);
309 if (GNUNET_IDENTITY_write_key_to_buffer (key, tmp, *data_size) 317 memcpy (tmp, ((char*) key) + sizeof (key->type), *data_size);
310 != *data_size) {
311 GNUNET_free (tmp);
312 *data_size = 0;
313 return GNUNET_SYSERR;
314 }
315 *data = tmp; 318 *data = tmp;
316 return GNUNET_OK; 319 return GNUNET_OK;
317} 320}
@@ -406,5 +409,176 @@ GNUNET_GNSRECORD_record_to_identity_key (const struct GNUNET_GNSRECORD_Data *rd,
406 409
407} 410}
408 411
412enum GNUNET_GenericReturnValue
413GNUNET_GNSRECORD_normalize_record_set (const char *label,
414 const struct
415 GNUNET_GNSRECORD_Data *rd,
416 unsigned int rd_count,
417 struct GNUNET_GNSRECORD_Data *
418 rd_public,
419 unsigned int *rd_count_public,
420 struct GNUNET_TIME_Absolute *expiry,
421 int include_private,
422 char **emsg)
423{
424 struct GNUNET_TIME_Absolute now;
425 struct GNUNET_TIME_Absolute minimum_expiration;
426 int have_zone_delegation = GNUNET_NO;
427 int have_gns2dns = GNUNET_NO;
428 int have_other = GNUNET_NO;
429 int have_redirect = GNUNET_NO;
430 int have_empty_label = (0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, label));
431 unsigned int rd_count_tmp;
432
433 minimum_expiration = GNUNET_TIME_UNIT_ZERO_ABS;
434 now = GNUNET_TIME_absolute_get ();
435 rd_count_tmp = 0;
436 for (unsigned int i = 0; i < rd_count; i++)
437 {
438 /* Ignore the tombstone. For maintenance only. Remember expiration time. */
439 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
440 {
441 minimum_expiration.abs_value_us = rd[i].expiration_time;
442 continue;
443 }
444 /* No NICK records unless empty label */
445 if (have_empty_label &&
446 (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type))
447 continue;
448
449 /**
450 * Check for delegation and redirect consistency.
451 * Note that we check for consistency BEFORE we filter for
452 * private records ON PURPOSE.
453 * We also want consistent record sets in our local zone(s).
454 * The only exception is the tombstone (above) which we ignore
455 * for the consistency check(s).
456 * FIXME: What about shadow records? Should we ignore them?
457 */
458 if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
459 {
460 /* No delegation records under empty label*/
461 if (have_empty_label)
462 {
463 *emsg = GNUNET_strdup (_ (
464 "Zone delegation record not allowed in apex."));
465 return GNUNET_SYSERR;
466 }
467 if ((GNUNET_YES == have_other) ||
468 (GNUNET_YES == have_redirect) ||
469 (GNUNET_YES == have_gns2dns))
470 {
471 *emsg = GNUNET_strdup (_ (
472 "Zone delegation record set contains mutually exclusive records."));
473 return GNUNET_SYSERR;
474 }
475 have_zone_delegation = GNUNET_YES;
476 }
477 else if (GNUNET_GNSRECORD_TYPE_REDIRECT == rd[i].record_type)
478 {
479 if (GNUNET_YES == have_redirect)
480 {
481 *emsg = GNUNET_strdup (_ (
482 "Multiple REDIRECT records."));
483 return GNUNET_SYSERR;
484
485 }
486 if ((GNUNET_YES == have_other) ||
487 (GNUNET_YES == have_zone_delegation) ||
488 (GNUNET_YES == have_gns2dns))
489 {
490 *emsg = GNUNET_strdup (_ (
491 "Redirection record set conains mutually exclusive records."));
492 return GNUNET_SYSERR;
493 }
494 /* No redirection records under empty label*/
495 if (have_empty_label)
496 {
497 *emsg = GNUNET_strdup (_ (
498 "Redirection records not allowed in apex."));
499 return GNUNET_SYSERR;
500 }
501 have_redirect = GNUNET_YES;
502 }
503 else if (GNUNET_GNSRECORD_TYPE_GNS2DNS == rd[i].record_type)
504 {
505 /* No gns2dns records under empty label*/
506 if (have_empty_label)
507 {
508 *emsg = GNUNET_strdup (_ (
509 "Redirection records not allowed in apex.."));
510 return GNUNET_SYSERR;
511 }
512 if ((GNUNET_YES == have_other) ||
513 (GNUNET_YES == have_redirect) ||
514 (GNUNET_YES == have_zone_delegation))
515 {
516 *emsg = GNUNET_strdup (_ (
517 "Redirection record set conains mutually exclusive records."));
518 return GNUNET_SYSERR;
519 }
520 have_gns2dns = GNUNET_YES;
521 }
522 else
523 {
524 /* Some other record.
525 * Not allowed for zone delegations or redirections */
526 if ((GNUNET_YES == have_zone_delegation) ||
527 (GNUNET_YES == have_redirect) ||
528 (GNUNET_YES == have_gns2dns))
529 {
530 *emsg = GNUNET_strdup (_ (
531 "Mutually exclusive records."));
532 return GNUNET_SYSERR;
533 }
534 have_other = GNUNET_YES;
535 }
536
537 /* Ignore private records for public record set */
538
539 if ((GNUNET_NO == include_private) &&
540 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)))
541 continue;
542 /* Skip expired records */
543 if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
544 (rd[i].expiration_time < now.abs_value_us))
545 continue; /* record already expired, skip it */
546 rd_public[rd_count_tmp] = rd[i];
547 /* Make sure critical record types are marked as such */
548 if (GNUNET_YES == GNUNET_GNSRECORD_is_critical (rd[i].record_type))
549 rd_public[rd_count_tmp].flags |= GNUNET_GNSRECORD_RF_CRITICAL;
550 rd_count_tmp++;
551 }
552
553 *expiry = GNUNET_GNSRECORD_record_get_expiration_time (rd_count_tmp,
554 rd_public,
555 minimum_expiration);
556 *rd_count_public = rd_count_tmp;
557 return GNUNET_OK;
558}
559
560enum GNUNET_GenericReturnValue
561GNUNET_GNSRECORD_convert_records_for_export (const char *label,
562 const struct
563 GNUNET_GNSRECORD_Data *rd,
564 unsigned int rd_count,
565 struct GNUNET_GNSRECORD_Data *
566 rd_public,
567 unsigned int *rd_count_public,
568 struct GNUNET_TIME_Absolute *expiry,
569 char **emsg)
570{
571 return GNUNET_GNSRECORD_normalize_record_set (label,
572 rd,
573 rd_count,
574 rd_public,
575 rd_count_public,
576 expiry,
577 GNUNET_NO,
578 emsg);
579
580}
581
582
409 583
410/* end of gnsrecord_misc.c */ 584/* end of gnsrecord_misc.c */
diff --git a/src/gnsrecord/gnunet-gnsrecord-tvg.c b/src/gnsrecord/gnunet-gnsrecord-tvg.c
index f9b83e48b..87de32066 100644
--- a/src/gnsrecord/gnunet-gnsrecord-tvg.c
+++ b/src/gnsrecord/gnunet-gnsrecord-tvg.c
@@ -33,9 +33,6 @@
33#include <inttypes.h> 33#include <inttypes.h>
34#include "gnsrecord_crypto.h" 34#include "gnsrecord_crypto.h"
35 35
36#define TEST_RECORD_LABEL "test"
37#define TEST_RECORD_A "1.2.3.4"
38#define TEST_RRCOUNT 2
39 36
40static char *d_pkey = 37static char *d_pkey =
41 "50d7b652a4efeadff37396909785e5952171a02178c8e7d450fa907925fafd98"; 38 "50d7b652a4efeadff37396909785e5952171a02178c8e7d450fa907925fafd98";
@@ -43,7 +40,9 @@ static char *d_pkey =
43static char *d_edkey = 40static char *d_edkey =
44 "5af7020ee19160328832352bbc6a68a8d71a7cbe1b929969a7c66d415a0d8f65"; 41 "5af7020ee19160328832352bbc6a68a8d71a7cbe1b929969a7c66d415a0d8f65";
45 42
46int parsehex (char *src, char *dst, size_t dstlen, int invert) 43
44static int
45parsehex (char *src, char *dst, size_t dstlen, int invert)
47{ 46{
48 char *line = src; 47 char *line = src;
49 char *data = line; 48 char *data = line;
@@ -83,6 +82,7 @@ print_bytes_ (void *buf,
83 printf ("\n"); 82 printf ("\n");
84} 83}
85 84
85
86static void 86static void
87print_bytes (void *buf, 87print_bytes (void *buf,
88 size_t buf_len, 88 size_t buf_len,
@@ -95,7 +95,7 @@ print_bytes (void *buf,
95static void 95static void
96print_record (const struct GNUNET_GNSRECORD_Data *rd) 96print_record (const struct GNUNET_GNSRECORD_Data *rd)
97{ 97{
98 98 uint16_t flags = htons (rd->flags);
99 fprintf (stdout, 99 fprintf (stdout,
100 "EXPIRATION: %" PRIu64 "\n", rd->expiration_time); 100 "EXPIRATION: %" PRIu64 "\n", rd->expiration_time);
101 fprintf (stdout, 101 fprintf (stdout,
@@ -103,7 +103,9 @@ print_record (const struct GNUNET_GNSRECORD_Data *rd)
103 fprintf (stdout, 103 fprintf (stdout,
104 "TYPE: %d\n", rd->record_type); 104 "TYPE: %d\n", rd->record_type);
105 fprintf (stdout, 105 fprintf (stdout,
106 "FLAGS: %d\n", rd->flags); 106 "FLAGS: ");
107 print_bytes ((void*) &flags, sizeof (flags), 8);
108 printf ("\n");
107 fprintf (stdout, 109 fprintf (stdout,
108 "DATA:\n"); 110 "DATA:\n");
109 print_bytes ((char*) rd->data, rd->data_size, 8); 111 print_bytes ((char*) rd->data, rd->data_size, 8);
@@ -120,15 +122,9 @@ print_record (const struct GNUNET_GNSRECORD_Data *rd)
120 * @param cfg configuration 122 * @param cfg configuration
121 */ 123 */
122static void 124static void
123run_pkey (void) 125run_pkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, const char *label)
124{ 126{
125 struct GNUNET_GNSRECORD_Data rd[2];
126 struct GNUNET_TIME_Absolute expire; 127 struct GNUNET_TIME_Absolute expire;
127 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
128 struct GNUNET_TIME_Absolute exp1;
129 struct GNUNET_TIME_Absolute exp2;
130 struct GNUNET_TIME_Relative delta1;
131 struct GNUNET_TIME_Relative delta2;
132 struct GNUNET_GNSRECORD_Block *rrblock; 128 struct GNUNET_GNSRECORD_Block *rrblock;
133 char *bdata; 129 char *bdata;
134 struct GNUNET_IDENTITY_PrivateKey id_priv; 130 struct GNUNET_IDENTITY_PrivateKey id_priv;
@@ -136,24 +132,12 @@ run_pkey (void)
136 struct GNUNET_IDENTITY_PrivateKey pkey_data_p; 132 struct GNUNET_IDENTITY_PrivateKey pkey_data_p;
137 struct GNUNET_IDENTITY_PublicKey pkey_data; 133 struct GNUNET_IDENTITY_PublicKey pkey_data;
138 struct GNUNET_HashCode query; 134 struct GNUNET_HashCode query;
139 void *data;
140 size_t data_size;
141 char *rdata; 135 char *rdata;
142 size_t rdata_size; 136 size_t rdata_size;
143 uint32_t rd_count_nbo;
144 char ztld[128]; 137 char ztld[128];
145 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; 138 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2];
146 unsigned char skey[GNUNET_CRYPTO_AES_KEY_LENGTH]; 139 unsigned char skey[GNUNET_CRYPTO_AES_KEY_LENGTH];
147 140
148 /*
149 * Make two different expiration times
150 */
151 GNUNET_STRINGS_fancy_time_to_absolute ("2048-01-23 10:51:34",
152 &exp1);
153 GNUNET_STRINGS_fancy_time_to_absolute ("3540-05-22 07:55:01",
154 &exp2);
155
156
157 id_priv.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); 141 id_priv.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
158 GNUNET_CRYPTO_ecdsa_key_create (&id_priv.ecdsa_key); 142 GNUNET_CRYPTO_ecdsa_key_create (&id_priv.ecdsa_key);
159 parsehex (d_pkey, 143 parsehex (d_pkey,
@@ -168,13 +152,14 @@ run_pkey (void)
168 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), 8, 1); 152 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), 8, 1);
169 fprintf (stdout, "\n"); 153 fprintf (stdout, "\n");
170 fprintf (stdout, "Zone identifier (ztype|zkey):\n"); 154 fprintf (stdout, "Zone identifier (ztype|zkey):\n");
155 GNUNET_assert (0 < GNUNET_IDENTITY_key_get_length (&id_pub));
171 print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8); 156 print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8);
172 GNUNET_STRINGS_data_to_string (&id_pub, 157 GNUNET_STRINGS_data_to_string (&id_pub,
173 GNUNET_IDENTITY_key_get_length (&id_pub), 158 GNUNET_IDENTITY_key_get_length (&id_pub),
174 ztld, 159 ztld,
175 sizeof (ztld)); 160 sizeof (ztld));
176 fprintf (stdout, "\n"); 161 fprintf (stdout, "\n");
177 fprintf (stdout, "Encoded zone identifier (zkl = zTLD):\n"); 162 fprintf (stdout, "zTLD:\n");
178 fprintf (stdout, "%s\n", ztld); 163 fprintf (stdout, "%s\n", ztld);
179 fprintf (stdout, "\n"); 164 fprintf (stdout, "\n");
180 165
@@ -183,39 +168,31 @@ run_pkey (void)
183 GNUNET_IDENTITY_key_get_public (&pkey_data_p, 168 GNUNET_IDENTITY_key_get_public (&pkey_data_p,
184 &pkey_data); 169 &pkey_data);
185 fprintf (stdout, 170 fprintf (stdout,
186 "Label: %s\nRRCOUNT: %d\n\n", TEST_RECORD_LABEL, TEST_RRCOUNT); 171 "Label: %s\nRRCOUNT: %d\n\n", label, rd_count);
187 memset (rd, 0, sizeof (struct GNUNET_GNSRECORD_Data) * 2);
188 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_string_to_value (
189 GNUNET_DNSPARSER_TYPE_A, TEST_RECORD_A, &data, &data_size));
190 rd[0].data = data;
191 rd[0].data_size = data_size;
192 rd[0].expiration_time = exp1.abs_value_us;
193 rd[0].record_type = GNUNET_DNSPARSER_TYPE_A;
194 fprintf (stdout, "Record #0\n");
195 print_record (&rd[0]);
196 172
197 rd[1].data = "Some nick"; 173 for (int i = 0; i < rd_count; i++)
198 rd[1].data_size = sizeof (struct GNUNET_IDENTITY_PublicKey); 174 {
199 rd[1].expiration_time = exp2.abs_value_us; 175 fprintf (stdout, "Record #%d\n", i);
200 rd[1].record_type = GNUNET_GNSRECORD_TYPE_NICK; 176 print_record (&rd[i]);
201 rd[1].flags = GNUNET_GNSRECORD_RF_PRIVATE; 177 }
202 fprintf (stdout, "Record #1\n");
203 print_record (&rd[1]);
204 178
205 rdata_size = GNUNET_GNSRECORD_records_get_size (TEST_RRCOUNT, 179 rdata_size = GNUNET_GNSRECORD_records_get_size (rd_count,
206 rd); 180 rd);
207 rdata = GNUNET_malloc (rdata_size); 181 rdata = GNUNET_malloc (rdata_size);
208 GNUNET_GNSRECORD_records_serialize (2, 182 GNUNET_GNSRECORD_records_serialize (rd_count,
209 rd, 183 rd,
210 rdata_size, 184 (size_t) rdata_size,
211 rdata); 185 rdata);
212 fprintf (stdout, "RDATA:\n"); 186 fprintf (stdout, "RDATA:\n");
213 print_bytes (rdata, rdata_size, 8); 187 print_bytes (rdata,
188 (size_t) rdata_size,
189 8);
214 fprintf (stdout, "\n"); 190 fprintf (stdout, "\n");
215 expire = GNUNET_GNSRECORD_record_get_expiration_time (TEST_RRCOUNT, rd); 191 expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_count, rd,
192 GNUNET_TIME_UNIT_ZERO_ABS);
216 GNR_derive_block_aes_key (ctr, 193 GNR_derive_block_aes_key (ctr,
217 skey, 194 skey,
218 TEST_RECORD_LABEL, 195 label,
219 GNUNET_TIME_absolute_hton ( 196 GNUNET_TIME_absolute_hton (
220 expire).abs_value_us__, 197 expire).abs_value_us__,
221 &id_pub.ecdsa_key); 198 &id_pub.ecdsa_key);
@@ -227,25 +204,26 @@ run_pkey (void)
227 print_bytes (skey, sizeof (skey), 8); 204 print_bytes (skey, sizeof (skey), 8);
228 fprintf (stdout, "\n"); 205 fprintf (stdout, "\n");
229 GNUNET_GNSRECORD_query_from_public_key (&id_pub, 206 GNUNET_GNSRECORD_query_from_public_key (&id_pub,
230 TEST_RECORD_LABEL, 207 label,
231 &query); 208 &query);
232 fprintf (stdout, "Storage key (q):\n"); 209 fprintf (stdout, "Storage key (q):\n");
233 print_bytes (&query, sizeof (query), 8); 210 print_bytes (&query, sizeof (query), 8);
234 fprintf (stdout, "\n"); 211 fprintf (stdout, "\n");
235 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (&id_priv, 212 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (&id_priv,
236 expire, 213 expire,
237 TEST_RECORD_LABEL, 214 label,
238 rd, 215 rd,
239 TEST_RRCOUNT, 216 rd_count,
240 &rrblock)); 217 &rrblock));
241 size_t bdata_size = ntohl(rrblock->size) - sizeof (struct GNUNET_GNSRECORD_Block); 218 size_t bdata_size = ntohl (rrblock->size) - sizeof (struct
219 GNUNET_GNSRECORD_Block);
242 220
243 bdata = (char*) &(&rrblock->ecdsa_block)[1]; 221 bdata = (char*) &(&rrblock->ecdsa_block)[1];
244 fprintf (stdout, "BDATA:\n"); 222 fprintf (stdout, "BDATA:\n");
245 print_bytes (bdata, bdata_size, 8); 223 print_bytes (bdata, bdata_size, 8);
246 fprintf (stdout, "\n"); 224 fprintf (stdout, "\n");
247 fprintf (stdout, "RRBLOCK:\n"); 225 fprintf (stdout, "RRBLOCK:\n");
248 print_bytes (rrblock, ntohl(rrblock->size), 8); 226 print_bytes (rrblock, ntohl (rrblock->size), 8);
249 fprintf (stdout, "\n"); 227 fprintf (stdout, "\n");
250 GNUNET_free (rdata); 228 GNUNET_free (rdata);
251} 229}
@@ -260,15 +238,9 @@ run_pkey (void)
260 * @param cfg configuration 238 * @param cfg configuration
261 */ 239 */
262static void 240static void
263run_edkey (void) 241run_edkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, const char*label)
264{ 242{
265 struct GNUNET_GNSRECORD_Data rd[2];
266 struct GNUNET_TIME_Absolute expire; 243 struct GNUNET_TIME_Absolute expire;
267 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
268 struct GNUNET_TIME_Absolute exp1;
269 struct GNUNET_TIME_Absolute exp2;
270 struct GNUNET_TIME_Relative delta1;
271 struct GNUNET_TIME_Relative delta2;
272 struct GNUNET_GNSRECORD_Block *rrblock; 244 struct GNUNET_GNSRECORD_Block *rrblock;
273 char *bdata; 245 char *bdata;
274 struct GNUNET_IDENTITY_PrivateKey id_priv; 246 struct GNUNET_IDENTITY_PrivateKey id_priv;
@@ -276,23 +248,13 @@ run_edkey (void)
276 struct GNUNET_IDENTITY_PrivateKey pkey_data_p; 248 struct GNUNET_IDENTITY_PrivateKey pkey_data_p;
277 struct GNUNET_IDENTITY_PublicKey pkey_data; 249 struct GNUNET_IDENTITY_PublicKey pkey_data;
278 struct GNUNET_HashCode query; 250 struct GNUNET_HashCode query;
279 void *data;
280 size_t data_size;
281 char *rdata; 251 char *rdata;
282 size_t rdata_size; 252 size_t rdata_size;
283 uint32_t rd_count_nbo; 253
284 char ztld[128]; 254 char ztld[128];
285 unsigned char nonce[crypto_secretbox_NONCEBYTES]; 255 unsigned char nonce[crypto_secretbox_NONCEBYTES];
286 unsigned char skey[crypto_secretbox_KEYBYTES]; 256 unsigned char skey[crypto_secretbox_KEYBYTES];
287 257
288 /*
289 * Make two different expiration times
290 */
291 GNUNET_STRINGS_fancy_time_to_absolute ("%2048-01-23 10:51:34",
292 &exp1);
293 GNUNET_STRINGS_fancy_time_to_absolute ("3540-05-22 07:55:01",
294 &exp2);
295
296 id_priv.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); 258 id_priv.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
297 GNUNET_CRYPTO_ecdsa_key_create (&id_priv.ecdsa_key); 259 GNUNET_CRYPTO_ecdsa_key_create (&id_priv.ecdsa_key);
298 GNUNET_IDENTITY_key_get_public (&id_priv, 260 GNUNET_IDENTITY_key_get_public (&id_priv,
@@ -311,13 +273,14 @@ run_edkey (void)
311 GNUNET_CRYPTO_EddsaPrivateKey), 8); 273 GNUNET_CRYPTO_EddsaPrivateKey), 8);
312 fprintf (stdout, "\n"); 274 fprintf (stdout, "\n");
313 fprintf (stdout, "Zone identifier (ztype|zkey):\n"); 275 fprintf (stdout, "Zone identifier (ztype|zkey):\n");
276 GNUNET_assert (0 < GNUNET_IDENTITY_key_get_length (&id_pub));
314 print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8); 277 print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8);
315 GNUNET_STRINGS_data_to_string (&id_pub, 278 GNUNET_STRINGS_data_to_string (&id_pub,
316 GNUNET_IDENTITY_key_get_length (&id_pub), 279 GNUNET_IDENTITY_key_get_length (&id_pub),
317 ztld, 280 ztld,
318 sizeof (ztld)); 281 sizeof (ztld));
319 fprintf (stdout, "\n"); 282 fprintf (stdout, "\n");
320 fprintf (stdout, "Encoded zone identifier (zkl = zTLD):\n"); 283 fprintf (stdout, "zTLD:\n");
321 fprintf (stdout, "%s\n", ztld); 284 fprintf (stdout, "%s\n", ztld);
322 fprintf (stdout, "\n"); 285 fprintf (stdout, "\n");
323 286
@@ -326,40 +289,33 @@ run_edkey (void)
326 GNUNET_IDENTITY_key_get_public (&pkey_data_p, 289 GNUNET_IDENTITY_key_get_public (&pkey_data_p,
327 &pkey_data); 290 &pkey_data);
328 fprintf (stdout, 291 fprintf (stdout,
329 "Label: %s\nRRCOUNT: %d\n\n", TEST_RECORD_LABEL, TEST_RRCOUNT); 292 "Label: %s\nRRCOUNT: %d\n\n", label, rd_count);
330 memset (rd, 0, sizeof (struct GNUNET_GNSRECORD_Data) * 2);
331 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_string_to_value (
332 GNUNET_DNSPARSER_TYPE_A, TEST_RECORD_A, &data, &data_size));
333 rd[0].data = data;
334 rd[0].data_size = data_size;
335 rd[0].expiration_time = exp1.abs_value_us;
336 rd[0].record_type = GNUNET_DNSPARSER_TYPE_A;
337 fprintf (stdout, "Record #0\n");
338 print_record (&rd[0]);
339 293
340 rd[1].data = "My Nick"; 294 for (int i = 0; i < rd_count; i++)
341 rd[1].data_size = sizeof (struct GNUNET_IDENTITY_PublicKey); 295 {
342 rd[1].expiration_time = exp2.abs_value_us; 296 fprintf (stdout, "Record #%d\n", i);
343 rd[1].record_type = GNUNET_GNSRECORD_TYPE_NICK; 297 print_record (&rd[i]);
344 rd[1].flags = GNUNET_GNSRECORD_RF_PRIVATE; 298 }
345 fprintf (stdout, "Record #1\n");
346 print_record (&rd[1]);
347 299
348 rdata_size = GNUNET_GNSRECORD_records_get_size (TEST_RRCOUNT, 300 rdata_size = GNUNET_GNSRECORD_records_get_size (rd_count,
349 rd); 301 rd);
350 expire = GNUNET_GNSRECORD_record_get_expiration_time (TEST_RRCOUNT, 302 expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_count,
351 rd); 303 rd,
352 rdata = GNUNET_malloc (rdata_size); 304 GNUNET_TIME_UNIT_ZERO_ABS);
353 GNUNET_GNSRECORD_records_serialize (2, 305 GNUNET_assert (0 < rdata_size);
306 rdata = GNUNET_malloc ((size_t) rdata_size);
307 GNUNET_GNSRECORD_records_serialize (rd_count,
354 rd, 308 rd,
355 rdata_size, 309 (size_t) rdata_size,
356 rdata); 310 rdata);
357 fprintf (stdout, "RDATA:\n"); 311 fprintf (stdout, "RDATA:\n");
358 print_bytes (rdata, rdata_size, 8); 312 print_bytes (rdata,
313 (size_t) rdata_size,
314 8);
359 fprintf (stdout, "\n"); 315 fprintf (stdout, "\n");
360 GNR_derive_block_xsalsa_key (nonce, 316 GNR_derive_block_xsalsa_key (nonce,
361 skey, 317 skey,
362 TEST_RECORD_LABEL, 318 label,
363 GNUNET_TIME_absolute_hton ( 319 GNUNET_TIME_absolute_hton (
364 expire).abs_value_us__, 320 expire).abs_value_us__,
365 &id_pub.eddsa_key); 321 &id_pub.eddsa_key);
@@ -370,7 +326,7 @@ run_edkey (void)
370 print_bytes (skey, sizeof (skey), 8); 326 print_bytes (skey, sizeof (skey), 8);
371 fprintf (stdout, "\n"); 327 fprintf (stdout, "\n");
372 GNUNET_GNSRECORD_query_from_public_key (&id_pub, 328 GNUNET_GNSRECORD_query_from_public_key (&id_pub,
373 TEST_RECORD_LABEL, 329 label,
374 &query); 330 &query);
375 fprintf (stdout, "Storage key (q):\n"); 331 fprintf (stdout, "Storage key (q):\n");
376 print_bytes (&query, sizeof (query), 8); 332 print_bytes (&query, sizeof (query), 8);
@@ -378,18 +334,19 @@ run_edkey (void)
378 334
379 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (&id_priv, 335 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (&id_priv,
380 expire, 336 expire,
381 TEST_RECORD_LABEL, 337 label,
382 rd, 338 rd,
383 TEST_RRCOUNT, 339 rd_count,
384 &rrblock)); 340 &rrblock));
385 size_t bdata_size = ntohl(rrblock->size) - sizeof (struct GNUNET_GNSRECORD_Block); 341 size_t bdata_size = ntohl (rrblock->size) - sizeof (struct
342 GNUNET_GNSRECORD_Block);
386 343
387 bdata = (char*) &(&rrblock->eddsa_block)[1]; 344 bdata = (char*) &(&rrblock->eddsa_block)[1];
388 fprintf (stdout, "BDATA:\n"); 345 fprintf (stdout, "BDATA:\n");
389 print_bytes (bdata, bdata_size, 8); 346 print_bytes (bdata, bdata_size, 8);
390 fprintf (stdout, "\n"); 347 fprintf (stdout, "\n");
391 fprintf (stdout, "RRBLOCK:\n"); 348 fprintf (stdout, "RRBLOCK:\n");
392 print_bytes (rrblock, ntohl(rrblock->size), 8); 349 print_bytes (rrblock, ntohl (rrblock->size), 8);
393 fprintf (stdout, "\n"); 350 fprintf (stdout, "\n");
394 GNUNET_free (rdata); 351 GNUNET_free (rdata);
395} 352}
@@ -409,8 +366,67 @@ run (void *cls,
409 const char *cfgfile, 366 const char *cfgfile,
410 const struct GNUNET_CONFIGURATION_Handle *cfg) 367 const struct GNUNET_CONFIGURATION_Handle *cfg)
411{ 368{
412 run_pkey (); 369 struct GNUNET_GNSRECORD_Data rd_pkey;
413 run_edkey (); 370 struct GNUNET_GNSRECORD_Data rd[3];
371 struct GNUNET_TIME_Absolute exp1;
372 struct GNUNET_TIME_Absolute exp2;
373 struct GNUNET_TIME_Relative exp3;
374 size_t pkey_data_size;
375 size_t ip_data_size;
376 char *pkey_data;
377 char *ip_data;
378
379 /*
380 * Make different expiration times
381 */
382 GNUNET_STRINGS_fancy_time_to_absolute ("2048-01-23 10:51:34",
383 &exp1);
384 GNUNET_STRINGS_fancy_time_to_absolute ("3540-05-22 07:55:01",
385 &exp2);
386 GNUNET_STRINGS_fancy_time_to_relative ("100y",
387 &exp3);
388
389
390 memset (&rd_pkey, 0, sizeof (struct GNUNET_GNSRECORD_Data));
391 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_string_to_value (
392 GNUNET_GNSRECORD_TYPE_PKEY,
393 "000G0011WESGZY9VRV9NNJ66W3GKNZFZF56BFD2BQF3MHMJST2G2GKDYGG",
394 (void**) &pkey_data,
395 &pkey_data_size));
396 rd_pkey.data = pkey_data;
397 rd_pkey.data_size = pkey_data_size;
398 rd_pkey.expiration_time = exp1.abs_value_us;
399 rd_pkey.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
400 rd_pkey.flags = GNUNET_GNSRECORD_RF_CRITICAL;
401 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_string_to_value (
402 GNUNET_DNSPARSER_TYPE_AAAA,
403 "::dead:beef",
404 (void**) &ip_data,
405 &ip_data_size));
406
407 rd[0].data = ip_data;
408 rd[0].data_size = ip_data_size;
409 rd[0].expiration_time = exp1.abs_value_us;
410 rd[0].record_type = GNUNET_DNSPARSER_TYPE_AAAA;
411 rd[0].flags = GNUNET_GNSRECORD_RF_NONE;
412
413 rd[1].data = "\u611b\u79f0";
414 rd[1].data_size = strlen (rd[1].data);
415 rd[1].expiration_time = exp2.abs_value_us;
416 rd[1].record_type = GNUNET_GNSRECORD_TYPE_NICK;
417 rd[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
418
419 rd[2].data = "Hello World";
420 rd[2].data_size = strlen (rd[2].data);
421 rd[2].expiration_time = exp3.rel_value_us;
422 rd[2].record_type = GNUNET_DNSPARSER_TYPE_TXT;
423 rd[2].flags = GNUNET_GNSRECORD_RF_SUPPLEMENTAL
424 | GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
425
426 run_pkey (&rd_pkey, 1, "testdelegation");
427 run_pkey (rd, 3, "namesystem");
428 run_edkey (&rd_pkey, 1, "testdelegation");
429 run_edkey (rd, 3, "namesystem");
414} 430}
415 431
416 432
diff --git a/src/gnsrecord/perf_gnsrecord_crypto.c b/src/gnsrecord/perf_gnsrecord_crypto.c
index d9a3c20cf..6b5f84235 100644
--- a/src/gnsrecord/perf_gnsrecord_crypto.c
+++ b/src/gnsrecord/perf_gnsrecord_crypto.c
@@ -90,12 +90,12 @@ run (void *cls,
90 start_time = GNUNET_TIME_absolute_get (); 90 start_time = GNUNET_TIME_absolute_get ();
91 for (unsigned int i = 0; i < ROUNDS; i++) 91 for (unsigned int i = 0; i < ROUNDS; i++)
92 { 92 {
93 GNUNET_assert (NULL != (block = 93 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (&privkey,
94 GNUNET_GNSRECORD_block_create2 (&privkey,
95 expire, 94 expire,
96 s_name, 95 s_name,
97 s_rd, 96 s_rd,
98 RECORDS))); 97 RECORDS,
98 &block));
99 GNUNET_GNSRECORD_query_from_private_key (&privkey, 99 GNUNET_GNSRECORD_query_from_private_key (&privkey,
100 s_name, 100 s_name,
101 &query); 101 &query);
diff --git a/src/gnsrecord/plugin_gnsrecord_dns.c b/src/gnsrecord/plugin_gnsrecord_dns.c
index 123c59905..649133cd1 100644
--- a/src/gnsrecord/plugin_gnsrecord_dns.c
+++ b/src/gnsrecord/plugin_gnsrecord_dns.c
@@ -773,6 +773,12 @@ dns_number_to_typename (void *cls, uint32_t type)
773} 773}
774 774
775 775
776static enum GNUNET_GenericReturnValue
777dns_is_critical (void *cls, uint32_t type)
778{
779 return GNUNET_NO;
780}
781
776/** 782/**
777 * Entry point for the plugin. 783 * Entry point for the plugin.
778 * 784 *
@@ -789,6 +795,7 @@ libgnunet_plugin_gnsrecord_dns_init (void *cls)
789 api->string_to_value = &dns_string_to_value; 795 api->string_to_value = &dns_string_to_value;
790 api->typename_to_number = &dns_typename_to_number; 796 api->typename_to_number = &dns_typename_to_number;
791 api->number_to_typename = &dns_number_to_typename; 797 api->number_to_typename = &dns_number_to_typename;
798 api->is_critical = &dns_is_critical;
792 return api; 799 return api;
793} 800}
794 801
diff --git a/src/gnsrecord/test_gnsrecord_block_expiration.c b/src/gnsrecord/test_gnsrecord_block_expiration.c
index b53d7d7e8..d14ce3914 100644
--- a/src/gnsrecord/test_gnsrecord_block_expiration.c
+++ b/src/gnsrecord/test_gnsrecord_block_expiration.c
@@ -72,7 +72,8 @@ run (void *cls, char *const *args, const char *cfgfile,
72 72
73 GNUNET_assert (expiration_abs.abs_value_us == 73 GNUNET_assert (expiration_abs.abs_value_us ==
74 GNUNET_GNSRECORD_record_get_expiration_time (2, 74 GNUNET_GNSRECORD_record_get_expiration_time (2,
75 rd).abs_value_us); 75 rd,
76 GNUNET_TIME_UNIT_ZERO_ABS).abs_value_us);
76 77
77 rd[1].expiration_time = expiration_abs_shadow.abs_value_us; 78 rd[1].expiration_time = expiration_abs_shadow.abs_value_us;
78 rd[1].record_type = TEST_RECORD_TYPE; 79 rd[1].record_type = TEST_RECORD_TYPE;
@@ -83,7 +84,8 @@ run (void *cls, char *const *args, const char *cfgfile,
83 84
84 GNUNET_assert (expiration_abs_shadow.abs_value_us == 85 GNUNET_assert (expiration_abs_shadow.abs_value_us ==
85 GNUNET_GNSRECORD_record_get_expiration_time (2, 86 GNUNET_GNSRECORD_record_get_expiration_time (2,
86 rd).abs_value_us); 87 rd,
88 GNUNET_TIME_UNIT_ZERO_ABS).abs_value_us);
87 res = 0; 89 res = 0;
88} 90}
89 91
diff --git a/src/gnsrecord/test_gnsrecord_testvectors.c b/src/gnsrecord/test_gnsrecord_testvectors.c
index 153c56261..bb4922417 100644
--- a/src/gnsrecord/test_gnsrecord_testvectors.c
+++ b/src/gnsrecord/test_gnsrecord_testvectors.c
@@ -10,16 +10,16 @@
10 10
11 11
12static char *d = 12static char *d =
13"50d7b652a4efeadff37396909785e5952171a02178c8e7d450fa907925fafd98"; 13 "50d7b652a4efeadff37396909785e5952171a02178c8e7d450fa907925fafd98";
14 14
15 15
16static char *zid = 16static char *zid =
17"00010000677c477d2d93097c85b195c6f96d84ff61f5982c2c4fe02d5a11fedfb0c2901f"; 17 "00010000677c477d2d93097c85b195c6f96d84ff61f5982c2c4fe02d5a11fedfb0c2901f";
18 18
19#define RRCOUNT 2 19#define RRCOUNT 2
20#define LABEL "test" 20#define LABEL "namesystem"
21 21
22#define R0_EXPIRATION 14888744139323793 22#define R0_EXPIRATION
23#define R0_DATA_SIZE 4 23#define R0_DATA_SIZE 4
24#define R0_TYPE 1 24#define R0_TYPE 1
25#define R0_FLAGS 0 25#define R0_FLAGS 0
@@ -31,12 +31,12 @@ static char *zid =
31#define R1_TYPE 65536 31#define R1_TYPE 65536
32#define R1_FLAGS 2 32#define R1_FLAGS 2
33#define R1_DATA \ 33#define R1_DATA \
34"000100000e601be42eb57fb4697610cf3a3b18347b65a33f025b5b174abefb30807bfecf" 34 "000100000e601be42eb57fb4697610cf3a3b18347b65a33f025b5b174abefb30807bfecf"
35 35
36#define R1_RRBLOCK \ 36#define R1_RRBLOCK \
37"000100008e16da87203b5159c5538e9b765742e968c54af9afbc0890dc80205ad14c84e107b0c115fc0089aa38b9c7ab9cbe1d77040d282a51a2ad493f61f3495f02d8170fe473a55ec6bdf9a509ab1701ffc37ea3bb4cac4a672520986df96e67cc1a73000000940000000f0034e53be193799100e4837eb5d04f92903de4b5234e8ccac5736c9793379a59c33375fc8951aca2eb7aad067bf9af60bf26758646a17f5e5c3b6215f94079545b1c4d4f1b2ebb22c2b4dad44126817b6f001530d476401dd67ac0148554e806353da9e4298079f3e1b16942c48d90c4360c61238c40d9d52911aea52cc0037ac7160bb3cf5b2f4a722fd96b" 37 "000100008e16da87203b5159c5538e9b765742e968c54af9afbc0890dc80205ad14c84e107b0c115fc0089aa38b9c7ab9cbe1d77040d282a51a2ad493f61f3495f02d8170fe473a55ec6bdf9a509ab1701ffc37ea3bb4cac4a672520986df96e67cc1a73000000940000000f0034e53be193799100e4837eb5d04f92903de4b5234e8ccac5736c9793379a59c33375fc8951aca2eb7aad067bf9af60bf26758646a17f5e5c3b6215f94079545b1c4d4f1b2ebb22c2b4dad44126817b6f001530d476401dd67ac0148554e806353da9e4298079f3e1b16942c48d90c4360c61238c40d9d52911aea52cc0037ac7160bb3cf5b2f4a722fd96b"
38 38
39int parsehex(char *src, char *dst, size_t dstlen, int invert) 39int parsehex (char *src, char *dst, size_t dstlen, int invert)
40{ 40{
41 char *line = src; 41 char *line = src;
42 char *data = line; 42 char *data = line;
@@ -44,7 +44,8 @@ int parsehex(char *src, char *dst, size_t dstlen, int invert)
44 int read_byte; 44 int read_byte;
45 int data_len = 0; 45 int data_len = 0;
46 46
47 while (sscanf(data, " %02x%n", &read_byte, &off) == 1) { 47 while (sscanf (data, " %02x%n", &read_byte, &off) == 1)
48 {
48 if (invert) 49 if (invert)
49 dst[dstlen - 1 - data_len++] = read_byte; 50 dst[dstlen - 1 - data_len++] = read_byte;
50 else 51 else
@@ -62,8 +63,8 @@ res_checker (void *cls,
62 int r1_found = 0; 63 int r1_found = 0;
63 char r0_data[R0_DATA_SIZE]; 64 char r0_data[R0_DATA_SIZE];
64 char r1_data[R1_DATA_SIZE]; 65 char r1_data[R1_DATA_SIZE];
65 parsehex(R0_DATA, (char*)r0_data, 0, 0); 66 parsehex (R0_DATA, (char*) r0_data, 0, 0);
66 parsehex(R1_DATA, (char*)r1_data, 0, 0); 67 parsehex (R1_DATA, (char*) r1_data, 0, 0);
67 GNUNET_assert (rd_count == RRCOUNT); 68 GNUNET_assert (rd_count == RRCOUNT);
68 for (int i = 0; i < RRCOUNT; i++) 69 for (int i = 0; i < RRCOUNT; i++)
69 { 70 {
@@ -104,7 +105,7 @@ res_checker (void *cls,
104 105
105 106
106int 107int
107main() 108main ()
108{ 109{
109 struct GNUNET_IDENTITY_PrivateKey priv; 110 struct GNUNET_IDENTITY_PrivateKey priv;
110 struct GNUNET_IDENTITY_PublicKey pub; 111 struct GNUNET_IDENTITY_PublicKey pub;
@@ -112,13 +113,15 @@ main()
112 struct GNUNET_GNSRECORD_Block *rrblock; 113 struct GNUNET_GNSRECORD_Block *rrblock;
113 char *bdata; 114 char *bdata;
114 115
115 parsehex(d,(char*)&priv.ecdsa_key, sizeof (priv.ecdsa_key), 1); 116 parsehex (d,(char*) &priv.ecdsa_key, sizeof (priv.ecdsa_key), 1);
116 priv.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); 117 priv.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
117 parsehex(zid,(char*)&pub_parsed, 0, 0); 118 parsehex (zid,(char*) &pub_parsed, 0, 0);
118 GNUNET_IDENTITY_key_get_public(&priv, &pub); 119 GNUNET_IDENTITY_key_get_public (&priv, &pub);
119 GNUNET_assert (0 == memcmp (&pub, &pub_parsed, sizeof (pub))); 120 GNUNET_assert (0 == memcmp (&pub, &pub_parsed, sizeof (pub)));
120 rrblock = GNUNET_malloc (strlen (R1_RRBLOCK) / 2); 121 rrblock = GNUNET_malloc (strlen (R1_RRBLOCK) / 2);
121 parsehex(R1_RRBLOCK, (char*)rrblock, 0, 0); 122 parsehex (R1_RRBLOCK, (char*) rrblock, 0, 0);
123 GNUNET_assert (GNUNET_YES
124 == GNUNET_GNSRECORD_is_critical (GNUNET_GNSRECORD_TYPE_PKEY));
122 GNUNET_GNSRECORD_block_decrypt (rrblock, 125 GNUNET_GNSRECORD_block_decrypt (rrblock,
123 &pub_parsed, 126 &pub_parsed,
124 LABEL, 127 LABEL,
diff --git a/src/hello/.gitignore b/src/hello/.gitignore
index bb49ceb20..d175d148e 100644
--- a/src/hello/.gitignore
+++ b/src/hello/.gitignore
@@ -1,3 +1,5 @@
1gnunet-hello 1gnunet-hello
2test_friend_hello 2test_friend_hello
3test_hello 3test_hello
4test_hello-uri
5test_hello-ng
diff --git a/src/hello/Makefile.am b/src/hello/Makefile.am
index 6a250e42f..c04b85106 100644
--- a/src/hello/Makefile.am
+++ b/src/hello/Makefile.am
@@ -11,7 +11,8 @@ lib_LTLIBRARIES = libgnunethello.la
11libgnunethello_la_SOURCES = \ 11libgnunethello_la_SOURCES = \
12 hello.c \ 12 hello.c \
13 address.c \ 13 address.c \
14 hello-ng.c 14 hello-ng.c \
15 hello-uri.c
15libgnunethello_la_LIBADD = \ 16libgnunethello_la_LIBADD = \
16 $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ 17 $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \
17 $(LTLIBINTL) 18 $(LTLIBINTL)
@@ -24,6 +25,7 @@ noinst_PROGRAMS = \
24 25
25check_PROGRAMS = \ 26check_PROGRAMS = \
26 test_hello \ 27 test_hello \
28 test_hello-uri \
27 test_friend_hello \ 29 test_friend_hello \
28 test_hello-ng 30 test_hello-ng
29 31
@@ -36,25 +38,32 @@ test_hello_SOURCES = \
36 test_hello.c 38 test_hello.c
37test_hello_LDADD = \ 39test_hello_LDADD = \
38 libgnunethello.la \ 40 libgnunethello.la \
39 $(top_builddir)/src/util/libgnunetutil.la 41 $(top_builddir)/src/util/libgnunetutil.la
40 42
41test_hello_ng_SOURCES = \ 43test_hello_ng_SOURCES = \
42 test_hello-ng.c 44 test_hello-ng.c
43test_hello_ng_LDADD = \ 45test_hello_ng_LDADD = \
44 libgnunethello.la \ 46 libgnunethello.la \
45 $(top_builddir)/src/util/libgnunetutil.la 47 $(top_builddir)/src/util/libgnunetutil.la
48
49test_hello_uri_SOURCES = \
50 test_hello-uri.c
51test_hello_uri_LDADD = \
52 libgnunethello.la \
53 $(top_builddir)/src/util/libgnunetutil.la \
54 -lgcrypt
46 55
47 56
48test_friend_hello_SOURCES = \ 57test_friend_hello_SOURCES = \
49 test_friend_hello.c 58 test_friend_hello.c
50test_friend_hello_LDADD = \ 59test_friend_hello_LDADD = \
51 libgnunethello.la \ 60 libgnunethello.la \
52 $(top_builddir)/src/util/libgnunetutil.la 61 $(top_builddir)/src/util/libgnunetutil.la
53 62
54gnunet_hello_SOURCES = \ 63gnunet_hello_SOURCES = \
55 gnunet-hello.c 64 gnunet-hello.c
56gnunet_hello_LDADD = \ 65gnunet_hello_LDADD = \
57 libgnunethello.la \ 66 libgnunethello.la \
58 $(top_builddir)/src/util/libgnunetutil.la 67 $(top_builddir)/src/util/libgnunetutil.la
59gnunet_hello_LDFLAGS = \ 68gnunet_hello_LDFLAGS = \
60 $(GN_LIBINTL) 69 $(GN_LIBINTL)
diff --git a/src/hello/hello-uri.c b/src/hello/hello-uri.c
new file mode 100644
index 000000000..bacaf697e
--- /dev/null
+++ b/src/hello/hello-uri.c
@@ -0,0 +1,891 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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 */
20
21/**
22 * @file hello/hello-uri.c
23 * @brief helper library for handling URI-based HELLOs
24 * @author Christian Grothoff
25 *
26 * Note:
27 * - Current API does not support deserializing HELLO of
28 * another peer and then serializing it into another
29 * format (we always require the private key).
30 * Not sure if we need this, but if we do, we need
31 * to extend the builder and the API.
32 * - Current API does not allow overriding the default
33 * HELLO expiration time. We may want to add a function
34 * that does this to create bootstrap HELLOs shipped with
35 * the TGZ.
36 */
37#include "platform.h"
38#include "gnunet_signatures.h"
39#include "gnunet_hello_uri_lib.h"
40#include "gnunet_protocols.h"
41#include "gnunet_util_lib.h"
42
43
44GNUNET_NETWORK_STRUCT_BEGIN
45
46/**
47 * Message signed as part of a HELLO block/URL.
48 */
49struct HelloSignaturePurpose
50{
51 /**
52 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_HELLO
53 */
54 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
55
56 /**
57 * When does the signature expire?
58 */
59 struct GNUNET_TIME_AbsoluteNBO expiration_time;
60
61 /**
62 * Hash over all addresses.
63 */
64 struct GNUNET_HashCode h_addrs;
65
66};
67
68/**
69 * Message used when gossiping HELLOs between peers.
70 */
71struct HelloUriMessage
72{
73 /**
74 * Type must be #GNUNET_MESSAGE_TYPE_HELLO_URI
75 */
76 struct GNUNET_MessageHeader header;
77
78 /**
79 * Reserved. 0.
80 */
81 uint16_t reserved GNUNET_PACKED;
82
83 /**
84 * Number of URLs encoded after the end of the struct, in NBO.
85 */
86 uint16_t url_counter GNUNET_PACKED;
87
88 /* followed by a 'block' */
89};
90
91
92/**
93 * Start of a 'block'.
94 */
95struct BlockHeader
96{
97 /**
98 * Public key of the peer.
99 */
100 struct GNUNET_PeerIdentity pid;
101
102 /**
103 * Signature over the block, of purpose #GNUNET_SIGNATURE_PURPOSE_HELLO.
104 */
105 struct GNUNET_CRYPTO_EddsaSignature sig;
106
107 /**
108 * When does the HELLO expire?
109 */
110 struct GNUNET_TIME_AbsoluteNBO expiration_time;
111
112};
113
114
115/**
116 * Message used when a DHT provides its HELLO to direct
117 * neighbours.
118 */
119struct DhtHelloMessage
120{
121 /**
122 * Type must be #GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO
123 */
124 struct GNUNET_MessageHeader header;
125
126 /**
127 * Reserved. 0.
128 */
129 uint16_t reserved GNUNET_PACKED;
130
131 /**
132 * Number of URLs encoded after the end of the struct, in NBO.
133 */
134 uint16_t url_counter GNUNET_PACKED;
135
136 /**
137 * Signature over the block, of purpose #GNUNET_SIGNATURE_PURPOSE_HELLO.
138 */
139 struct GNUNET_CRYPTO_EddsaSignature sig;
140
141 /**
142 * When does the HELLO expire?
143 */
144 struct GNUNET_TIME_AbsoluteNBO expiration_time;
145
146 /* followed by the serialized addresses of the 'block' */
147};
148
149
150GNUNET_NETWORK_STRUCT_END
151
152
153/**
154 * Address of a peer.
155 */
156struct Address
157{
158 /**
159 * Kept in a DLL.
160 */
161 struct Address *next;
162
163 /**
164 * Kept in a DLL.
165 */
166 struct Address *prev;
167
168 /**
169 * Actual URI, allocated at the end of this struct.
170 */
171 const char *uri;
172
173 /**
174 * Length of @a uri including 0-terminator.
175 */
176 size_t uri_len;
177};
178
179
180/**
181 * Context for building (or parsing) HELLO URIs.
182 */
183struct GNUNET_HELLO_Builder
184{
185 /**
186 * Public key of the peer.
187 */
188 struct GNUNET_PeerIdentity pid;
189
190 /**
191 * Head of the addresses DLL.
192 */
193 struct Address *a_head;
194
195 /**
196 * Tail of the addresses DLL.
197 */
198 struct Address *a_tail;
199
200 /**
201 * Length of the @a a_head DLL.
202 */
203 unsigned int a_length;
204
205};
206
207
208/**
209 * Compute @a hash over addresses in @a builder.
210 *
211 * @param builder the builder to hash addresses of
212 * @param[out] hash where to write the hash
213 */
214static void
215hash_addresses (const struct GNUNET_HELLO_Builder *builder,
216 struct GNUNET_HashCode *hash)
217{
218 struct GNUNET_HashContext *hc;
219
220 hc = GNUNET_CRYPTO_hash_context_start ();
221 for (struct Address *a = builder->a_head;
222 NULL != a;
223 a = a->next)
224 {
225 GNUNET_CRYPTO_hash_context_read (hc,
226 a->uri,
227 a->uri_len);
228 }
229 GNUNET_CRYPTO_hash_context_finish (hc,
230 hash);
231
232}
233
234
235/**
236 * Create HELLO signature.
237 *
238 * @param builder the builder to use
239 * @param et expiration time to sign
240 * @param priv key to sign with
241 * @param[out] sig where to write the signature
242 */
243static void
244sign_hello (const struct GNUNET_HELLO_Builder *builder,
245 struct GNUNET_TIME_Timestamp et,
246 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
247 struct GNUNET_CRYPTO_EddsaSignature *sig)
248{
249 struct HelloSignaturePurpose hsp = {
250 .purpose.size = htonl (sizeof (hsp)),
251 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_HELLO),
252 .expiration_time = GNUNET_TIME_absolute_hton (et.abs_time)
253 };
254
255 hash_addresses (builder,
256 &hsp.h_addrs);
257 GNUNET_CRYPTO_eddsa_sign (priv,
258 &hsp,
259 sig);
260}
261
262
263/**
264 * Verify HELLO signature.
265 *
266 * @param builder the builder to use
267 * @param et expiration time to verify
268 * @param sig signature to verify
269 * @return #GNUNET_OK if everything is ok, #GNUNET_NO if the
270 * HELLO expired, #GNUNET_SYSERR if the signature is wrong
271 */
272static enum GNUNET_GenericReturnValue
273verify_hello (const struct GNUNET_HELLO_Builder *builder,
274 struct GNUNET_TIME_Absolute et,
275 const struct GNUNET_CRYPTO_EddsaSignature *sig)
276{
277 struct HelloSignaturePurpose hsp = {
278 .purpose.size = htonl (sizeof (hsp)),
279 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_HELLO),
280 .expiration_time = GNUNET_TIME_absolute_hton (et)
281 };
282
283 hash_addresses (builder,
284 &hsp.h_addrs);
285 if (GNUNET_OK !=
286 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_HELLO,
287 &hsp,
288 sig,
289 &builder->pid.public_key))
290 {
291 GNUNET_break_op (0);
292 return GNUNET_SYSERR;
293 }
294 if (GNUNET_TIME_absolute_is_past (et))
295 return GNUNET_NO;
296 return GNUNET_OK;
297}
298
299
300struct GNUNET_HELLO_Builder *
301GNUNET_HELLO_builder_new (const struct GNUNET_PeerIdentity *pid)
302{
303 struct GNUNET_HELLO_Builder *builder;
304
305 builder = GNUNET_new (struct GNUNET_HELLO_Builder);
306 builder->pid = *pid;
307 return builder;
308}
309
310
311void
312GNUNET_HELLO_builder_free (struct GNUNET_HELLO_Builder *builder)
313{
314 struct Address *a;
315
316 while (NULL != (a = builder->a_head))
317 {
318 GNUNET_CONTAINER_DLL_remove (builder->a_head,
319 builder->a_tail,
320 a);
321 builder->a_length--;
322 GNUNET_free (a);
323 }
324 GNUNET_assert (0 == builder->a_length);
325 GNUNET_free (builder);
326}
327
328
329struct GNUNET_HELLO_Builder *
330GNUNET_HELLO_builder_from_msg (const struct GNUNET_MessageHeader *msg)
331{
332 const struct HelloUriMessage *h;
333 uint16_t size = ntohs (msg->size);
334
335 if (GNUNET_MESSAGE_TYPE_HELLO_URI != ntohs (msg->type))
336 {
337 GNUNET_break (0);
338 return NULL;
339 }
340 if (sizeof (struct HelloUriMessage) > size)
341 {
342 GNUNET_break_op (0);
343 return NULL;
344 }
345 h = (const struct HelloUriMessage *) msg;
346 size -= sizeof (*h);
347 return GNUNET_HELLO_builder_from_block (&h[1],
348 size);
349}
350
351
352struct GNUNET_HELLO_Builder *
353GNUNET_HELLO_builder_from_block (const void *block,
354 size_t block_size)
355{
356 const struct BlockHeader *bh = block;
357 struct GNUNET_HELLO_Builder *b;
358
359 if (block_size < sizeof (*bh))
360 {
361 GNUNET_break_op (0);
362 return NULL;
363 }
364 b = GNUNET_HELLO_builder_new (&bh->pid);
365 block += sizeof (*bh);
366 block_size -= sizeof (*bh);
367 while (block_size > 0)
368 {
369 const void *end = memchr (block,
370 '\0',
371 block_size);
372
373 if (NULL == end)
374 {
375 GNUNET_break_op (0);
376 GNUNET_HELLO_builder_free (b);
377 return NULL;
378 }
379 if (GNUNET_OK !=
380 GNUNET_HELLO_builder_add_address (b,
381 block))
382 {
383 GNUNET_break_op (0);
384 GNUNET_HELLO_builder_free (b);
385 return NULL;
386 }
387 end++;
388 block_size -= (end - block);
389 block = end;
390 }
391 {
392 enum GNUNET_GenericReturnValue ret;
393
394 ret = verify_hello (b,
395 GNUNET_TIME_absolute_ntoh (bh->expiration_time),
396 &bh->sig);
397 GNUNET_break (GNUNET_SYSERR != ret);
398 if (GNUNET_OK != ret)
399 {
400 GNUNET_HELLO_builder_free (b);
401 return NULL;
402 }
403 }
404 return b;
405}
406
407
408struct GNUNET_HELLO_Builder *
409GNUNET_HELLO_builder_from_url (const char *url)
410{
411 const char *q;
412 const char *s1;
413 const char *s2;
414 struct GNUNET_PeerIdentity pid;
415 struct GNUNET_CRYPTO_EddsaSignature sig;
416 struct GNUNET_TIME_Absolute et;
417 size_t len;
418 struct GNUNET_HELLO_Builder *b;
419
420 if (0 != strncasecmp (url,
421 "gnunet://hello/",
422 strlen ("gnunet://hello/")))
423 return NULL;
424 url += strlen ("gnunet://hello/");
425 s1 = strchr (url, '/');
426 if (NULL == s1)
427 {
428 GNUNET_break_op (0);
429 return NULL;
430 }
431 s2 = strchr (s1 + 1, '/');
432 if (NULL == s1)
433 {
434 GNUNET_break_op (0);
435 return NULL;
436 }
437 q = strchr (url, '?');
438 if (NULL == q)
439 q = url + strlen (url);
440 if (GNUNET_OK !=
441 GNUNET_STRINGS_string_to_data (url,
442 s1 - url,
443 &pid,
444 sizeof(pid)))
445 {
446 GNUNET_break_op (0);
447 return NULL;
448 }
449 if (GNUNET_OK !=
450 GNUNET_STRINGS_string_to_data (s1 + 1,
451 s2 - (s1 + 1),
452 &sig,
453 sizeof(sig)))
454 {
455 GNUNET_break_op (0);
456 return NULL;
457 }
458 {
459 unsigned long long sec;
460 char dummy = '?';
461
462 if ( (0 == sscanf (s2 + 1,
463 "%llu%c",
464 &sec,
465 &dummy)) ||
466 ('?' != dummy) )
467 {
468 GNUNET_break_op (0);
469 return NULL;
470 }
471 et = GNUNET_TIME_absolute_from_s (sec);
472 }
473
474 b = GNUNET_HELLO_builder_new (&pid);
475 len = strlen (q);
476 while (len > 0)
477 {
478 const char *eq;
479 const char *amp;
480 char *addr = NULL;
481 char *uri;
482
483 /* skip ?/& separator */
484 len--;
485 q++;
486 eq = strchr (q, '=');
487 if ( (eq == q) ||
488 (NULL == eq) )
489 {
490 GNUNET_break_op (0);
491 GNUNET_HELLO_builder_free (b);
492 return NULL;
493 }
494 amp = strchr (eq, '&');
495 if (NULL == amp)
496 amp = &q[len];
497 GNUNET_STRINGS_urldecode (eq + 1,
498 amp - (eq + 1),
499 &addr);
500 if ( (NULL == addr) ||
501 (0 == strlen (addr)) )
502 {
503 GNUNET_free (addr);
504 GNUNET_break_op (0);
505 GNUNET_HELLO_builder_free (b);
506 return NULL;
507 }
508 GNUNET_asprintf (&uri,
509 "%.*s://%s",
510 (int) (eq - q),
511 q,
512 addr);
513 GNUNET_free (addr);
514 if (GNUNET_OK !=
515 GNUNET_HELLO_builder_add_address (b,
516 uri))
517 {
518 GNUNET_break_op (0);
519 GNUNET_free (uri);
520 GNUNET_HELLO_builder_free (b);
521 return NULL;
522 }
523 GNUNET_free (uri);
524 /* move to next URL */
525 len -= (amp - q);
526 q = amp;
527 }
528
529 {
530 enum GNUNET_GenericReturnValue ret;
531
532 ret = verify_hello (b,
533 et,
534 &sig);
535 GNUNET_break (GNUNET_SYSERR != ret);
536 if (GNUNET_OK != ret)
537 {
538 GNUNET_HELLO_builder_free (b);
539 return NULL;
540 }
541 }
542 return b;
543}
544
545
546struct GNUNET_MQ_Envelope *
547GNUNET_HELLO_builder_to_env (const struct GNUNET_HELLO_Builder *builder,
548 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
549{
550 struct GNUNET_MQ_Envelope *env;
551 struct HelloUriMessage *msg;
552 size_t blen;
553
554 if (builder->a_length > UINT16_MAX)
555 {
556 GNUNET_break (0);
557 return NULL;
558 }
559 blen = 0;
560 GNUNET_assert (GNUNET_NO ==
561 GNUNET_HELLO_builder_to_block (builder,
562 priv,
563 NULL,
564 &blen));
565 env = GNUNET_MQ_msg_extra (msg,
566 blen,
567 GNUNET_MESSAGE_TYPE_HELLO_URI);
568 msg->url_counter = htonl ((uint16_t) builder->a_length);
569 GNUNET_assert (GNUNET_OK ==
570 GNUNET_HELLO_builder_to_block (builder,
571 priv,
572 &msg[1],
573 &blen));
574 return env;
575}
576
577
578struct GNUNET_MessageHeader *
579GNUNET_HELLO_builder_to_dht_hello_msg (
580 const struct GNUNET_HELLO_Builder *builder,
581 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
582{
583 struct DhtHelloMessage *msg;
584 size_t blen;
585
586 if (builder->a_length > UINT16_MAX)
587 {
588 GNUNET_break (0);
589 return NULL;
590 }
591 blen = 0;
592 GNUNET_assert (GNUNET_NO ==
593 GNUNET_HELLO_builder_to_block (builder,
594 priv,
595 NULL,
596 &blen));
597 GNUNET_assert (blen < UINT16_MAX);
598 GNUNET_assert (blen >= sizeof (struct BlockHeader));
599 {
600 char buf[blen] GNUNET_ALIGN;
601 const struct BlockHeader *block = (const struct BlockHeader *) buf;
602
603 GNUNET_assert (GNUNET_OK ==
604 GNUNET_HELLO_builder_to_block (builder,
605 priv,
606 buf,
607 &blen));
608 msg = GNUNET_malloc (sizeof (*msg)
609 + blen
610 - sizeof (*block));
611 msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO);
612 msg->header.size = htons (sizeof (*msg)
613 + blen
614 - sizeof (*block));
615 memcpy (&msg[1],
616 &block[1],
617 blen - sizeof (*block));
618 msg->sig = block->sig;
619 msg->expiration_time = block->expiration_time;
620 }
621 msg->url_counter = htonl ((uint16_t) builder->a_length);
622 return &msg->header;
623}
624
625
626char *
627GNUNET_HELLO_builder_to_url (const struct GNUNET_HELLO_Builder *builder,
628 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
629{
630 struct GNUNET_CRYPTO_EddsaSignature sig;
631 struct GNUNET_TIME_Timestamp et;
632 char *result;
633 char *pids;
634 char *sigs;
635 const char *sep = "?";
636
637 et = GNUNET_TIME_relative_to_timestamp (GNUNET_HELLO_ADDRESS_EXPIRATION);
638 sign_hello (builder,
639 et,
640 priv,
641 &sig);
642 pids = GNUNET_STRINGS_data_to_string_alloc (&builder->pid,
643 sizeof (builder->pid));
644 sigs = GNUNET_STRINGS_data_to_string_alloc (&sig,
645 sizeof (sig));
646 GNUNET_asprintf (&result,
647 "gnunet://hello/%s/%s/%llu",
648 pids,
649 sigs,
650 (unsigned long long) GNUNET_TIME_timestamp_to_s (et));
651 GNUNET_free (sigs);
652 GNUNET_free (pids);
653 for (struct Address *a = builder->a_head;
654 NULL != a;
655 a = a->next)
656 {
657 char *ue;
658 char *tmp;
659 int pfx_len;
660 const char *eou;
661
662 eou = strstr (a->uri,
663 "://");
664 if (NULL == eou)
665 {
666 GNUNET_break (0);
667 GNUNET_free (result);
668 return NULL;
669 }
670 pfx_len = eou - a->uri;
671 eou += 3;
672 GNUNET_STRINGS_urlencode (eou,
673 a->uri_len - 4 - pfx_len,
674 &ue);
675 GNUNET_asprintf (&tmp,
676 "%s%s%.*s=%s",
677 result,
678 sep,
679 pfx_len,
680 a->uri,
681 ue);
682 GNUNET_free (ue);
683 GNUNET_free (result);
684 result = tmp;
685 sep = "&";
686 }
687 return result;
688}
689
690
691enum GNUNET_GenericReturnValue
692GNUNET_HELLO_builder_to_block (const struct GNUNET_HELLO_Builder *builder,
693 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
694 void *block,
695 size_t *block_size)
696{
697 struct BlockHeader bh;
698 size_t needed = sizeof (bh);
699 char *pos;
700 struct GNUNET_TIME_Timestamp et;
701
702 for (struct Address *a = builder->a_head;
703 NULL != a;
704 a = a->next)
705 {
706 GNUNET_assert (needed + a->uri_len > needed);
707 needed += a->uri_len;
708 }
709 if ( (NULL == block) ||
710 (needed < *block_size) )
711 {
712 *block_size = needed;
713 return GNUNET_NO;
714 }
715 bh.pid = builder->pid;
716 et = GNUNET_TIME_relative_to_timestamp (GNUNET_HELLO_ADDRESS_EXPIRATION);
717 bh.expiration_time = GNUNET_TIME_absolute_hton (et.abs_time);
718 sign_hello (builder,
719 et,
720 priv,
721 &bh.sig);
722 memcpy (block,
723 &bh,
724 sizeof (bh));
725 pos = block + sizeof (bh);
726 for (struct Address *a = builder->a_head;
727 NULL != a;
728 a = a->next)
729 {
730 memcpy (pos,
731 a->uri,
732 a->uri_len);
733 pos += a->uri_len;
734 }
735 *block_size = needed;
736 return GNUNET_OK;
737}
738
739
740enum GNUNET_GenericReturnValue
741GNUNET_HELLO_builder_add_address (struct GNUNET_HELLO_Builder *builder,
742 const char *address)
743{
744 size_t alen = strlen (address) + 1;
745 struct Address *a;
746 const char *e;
747
748 if (NULL == (e = strstr (address,
749 "://")))
750 {
751 GNUNET_break_op (0);
752 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
753 "Invalid address `%s'\n",
754 address);
755 return GNUNET_SYSERR;
756 }
757 if (e == address)
758 {
759 GNUNET_break_op (0);
760 return GNUNET_SYSERR;
761 }
762 for (const char *p = address; p != e; p++)
763 if ( (! isalpha ((unsigned char) *p)) &&
764 ('+' != *p) )
765 {
766 GNUNET_break_op (0);
767 return GNUNET_SYSERR;
768 }
769 /* check for duplicates */
770 for (a = builder->a_head;
771 NULL != a;
772 a = a->next)
773 if (0 == strcmp (address,
774 a->uri))
775 return GNUNET_NO;
776 a = GNUNET_malloc (sizeof (struct Address) + alen);
777 a->uri_len = alen;
778 memcpy (&a[1],
779 address,
780 alen);
781 a->uri = (const char *) &a[1];
782 GNUNET_CONTAINER_DLL_insert_tail (builder->a_head,
783 builder->a_tail,
784 a);
785 builder->a_length++;
786 return GNUNET_OK;
787}
788
789
790enum GNUNET_GenericReturnValue
791GNUNET_HELLO_builder_del_address (struct GNUNET_HELLO_Builder *builder,
792 const char *address)
793{
794 struct Address *a;
795
796 /* check for duplicates */
797 for (a = builder->a_head;
798 NULL != a;
799 a = a->next)
800 if (0 == strcmp (address,
801 a->uri))
802 break;
803 if (NULL == a)
804 return GNUNET_NO;
805 GNUNET_CONTAINER_DLL_remove (builder->a_head,
806 builder->a_tail,
807 a);
808 builder->a_length--;
809 GNUNET_free (a);
810 return GNUNET_OK;
811}
812
813
814void
815GNUNET_HELLO_builder_iterate (const struct GNUNET_HELLO_Builder *builder,
816 struct GNUNET_PeerIdentity *pid,
817 GNUNET_HELLO_UriCallback uc,
818 void *uc_cls)
819{
820 struct Address *nxt;
821
822 *pid = builder->pid;
823 if (NULL == uc)
824 return;
825 for (struct Address *a = builder->a_head;
826 NULL != a;
827 a = nxt)
828 {
829 nxt = a->next;
830 uc (uc_cls,
831 a->uri);
832 }
833}
834
835
836enum GNUNET_GenericReturnValue
837GNUNET_HELLO_dht_msg_to_block (const struct GNUNET_MessageHeader *hello,
838 const struct GNUNET_PeerIdentity *pid,
839 void **block,
840 size_t *block_size,
841 struct GNUNET_TIME_Absolute *block_expiration)
842{
843 const struct DhtHelloMessage *msg
844 = (const struct DhtHelloMessage *) hello;
845 uint16_t len = ntohs (hello->size);
846 struct BlockHeader *bh;
847 struct GNUNET_HELLO_Builder *b;
848 enum GNUNET_GenericReturnValue ret;
849
850 if (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO != ntohs (hello->type))
851 {
852 GNUNET_break (0);
853 return GNUNET_SYSERR;
854 }
855 if (len < sizeof (*msg))
856 {
857 GNUNET_break_op (0);
858 return GNUNET_SYSERR;
859 }
860 len -= sizeof (*msg);
861 *block_size = len + sizeof (*bh);
862 *block = GNUNET_malloc (*block_size);
863 bh = *block;
864 bh->pid = *pid;
865 bh->sig = msg->sig;
866 bh->expiration_time = msg->expiration_time;
867 *block_expiration = GNUNET_TIME_absolute_ntoh (msg->expiration_time);
868 memcpy (&bh[1],
869 &msg[1],
870 len);
871 b = GNUNET_HELLO_builder_from_block (*block,
872 *block_size);
873 if (NULL == b)
874 {
875 GNUNET_break_op (0);
876 GNUNET_free (*block);
877 *block_size = 0;
878 return GNUNET_SYSERR;
879 }
880 ret = verify_hello (b,
881 *block_expiration,
882 &msg->sig);
883 GNUNET_HELLO_builder_free (b);
884 if (GNUNET_SYSERR == ret)
885 {
886 GNUNET_free (*block);
887 *block_size = 0;
888 return GNUNET_SYSERR;
889 }
890 return ret;
891}
diff --git a/src/hello/test_hello-ng.c b/src/hello/test_hello-ng.c
index e6b1d42a0..4ace9439f 100644
--- a/src/hello/test_hello-ng.c
+++ b/src/hello/test_hello-ng.c
@@ -1,3 +1,22 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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 */
1#include "platform.h" 20#include "platform.h"
2#include "gnunet_util_lib.h" 21#include "gnunet_util_lib.h"
3#include "gnunet_nt_lib.h" 22#include "gnunet_nt_lib.h"
@@ -23,12 +42,12 @@ main (int argc,
23 GNUNET_NT_LAN, 42 GNUNET_NT_LAN,
24 t, 43 t,
25 &privKey, 44 &privKey,
26 (void**)&res, 45 (void**) &res,
27 &res_len); 46 &res_len);
28 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 47 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
29 "%s\n", res); 48 "%s\n", res);
30 GNUNET_assert (NULL != 49 GNUNET_assert (NULL !=
31 GNUNET_HELLO_extract_address ((void**)res, 50 GNUNET_HELLO_extract_address ((void**) res,
32 res_len, 51 res_len,
33 &pid, 52 &pid,
34 &nt, 53 &nt,
diff --git a/src/hello/test_hello-uri.c b/src/hello/test_hello-uri.c
new file mode 100644
index 000000000..7e70d6763
--- /dev/null
+++ b/src/hello/test_hello-uri.c
@@ -0,0 +1,212 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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 */
20/**
21 * @file hello/test_hello-uri.c
22 * @brief test for helper library for handling URI-based HELLOs
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_signatures.h"
27#include "gnunet_hello_uri_lib.h"
28#include "gnunet_util_lib.h"
29
30
31/**
32 * Check for expected URIs.
33 *
34 * @param cls a `unsigned int*`, bitmask set to found URIs
35 * @param uri URI to check for
36 */
37static void
38check_uris (void *cls,
39 const char *uri)
40{
41 unsigned int *found = cls;
42
43 if (0 == strcmp (uri,
44 "test://address"))
45 *found |= 1;
46 else if (0 == strcmp (uri,
47 "test://more"))
48 *found |= 2;
49 else
50 *found = (unsigned int) -1;
51}
52
53
54int
55main (int argc,
56 char *argv[])
57{
58 struct GNUNET_PeerIdentity pid;
59 struct GNUNET_HELLO_Builder *b;
60 struct GNUNET_CRYPTO_EddsaPrivateKey priv;
61
62 GNUNET_log_setup ("test-hell-uri",
63 "WARNING",
64 NULL);
65 GNUNET_CRYPTO_eddsa_key_create (&priv);
66 GNUNET_CRYPTO_eddsa_key_get_public (&priv,
67 &pid.public_key);
68 b = GNUNET_HELLO_builder_new (&pid);
69 GNUNET_assert (GNUNET_SYSERR ==
70 GNUNET_HELLO_builder_add_address (b,
71 "invalid"));
72 GNUNET_assert (GNUNET_SYSERR ==
73 GNUNET_HELLO_builder_add_address (b,
74 "i%v://bla"));
75 GNUNET_assert (GNUNET_SYSERR ==
76 GNUNET_HELLO_builder_add_address (b,
77 "://empty"));
78 GNUNET_assert (GNUNET_OK ==
79 GNUNET_HELLO_builder_add_address (b,
80 "test://address"));
81 GNUNET_assert (GNUNET_NO ==
82 GNUNET_HELLO_builder_add_address (b,
83 "test://address"));
84 GNUNET_assert (GNUNET_OK ==
85 GNUNET_HELLO_builder_add_address (b,
86 "test://more"));
87 {
88 void *block;
89 size_t block_size = 0;
90 struct GNUNET_HELLO_Builder *b2;
91 struct GNUNET_PeerIdentity p2;
92 unsigned int found;
93
94 GNUNET_assert (GNUNET_NO ==
95 GNUNET_HELLO_builder_to_block (b,
96 &priv,
97 NULL,
98 &block_size));
99 GNUNET_assert (GNUNET_NO ==
100 GNUNET_HELLO_builder_to_block (b,
101 &priv,
102 NULL,
103 &block_size));
104 GNUNET_assert (0 != block_size);
105 block = GNUNET_malloc (block_size);
106 GNUNET_assert (GNUNET_OK ==
107 GNUNET_HELLO_builder_to_block (b,
108 &priv,
109 block,
110 &block_size));
111 b2 = GNUNET_HELLO_builder_from_block (block,
112 block_size);
113 GNUNET_free (block);
114 GNUNET_assert (NULL != b2);
115 found = 0;
116 GNUNET_HELLO_builder_iterate (b2,
117 &p2,
118 &check_uris,
119 &found);
120 GNUNET_assert (3 == found);
121 GNUNET_assert (0 ==
122 GNUNET_memcmp (&p2,
123 &pid));
124 GNUNET_HELLO_builder_free (b2);
125 }
126
127 {
128 char *url;
129 struct GNUNET_HELLO_Builder *b2;
130 struct GNUNET_PeerIdentity p2;
131 unsigned int found;
132
133 url = GNUNET_HELLO_builder_to_url (b,
134 &priv);
135 b2 = GNUNET_HELLO_builder_from_url (url);
136 GNUNET_free (url);
137 GNUNET_assert (NULL != b2);
138 found = 0;
139 GNUNET_HELLO_builder_iterate (b2,
140 &p2,
141 &check_uris,
142 &found);
143 GNUNET_assert (3 == found);
144 GNUNET_assert (0 ==
145 GNUNET_memcmp (&p2,
146 &pid));
147 GNUNET_HELLO_builder_free (b2);
148 }
149
150 {
151 struct GNUNET_MQ_Envelope *env;
152 struct GNUNET_HELLO_Builder *b2;
153 struct GNUNET_PeerIdentity p2;
154 unsigned int found;
155
156 env = GNUNET_HELLO_builder_to_env (b,
157 &priv);
158 b2 = GNUNET_HELLO_builder_from_msg (GNUNET_MQ_env_get_msg (env));
159 GNUNET_free (env);
160 GNUNET_assert (NULL != b2);
161 found = 0;
162 GNUNET_HELLO_builder_iterate (b2,
163 &p2,
164 &check_uris,
165 &found);
166 GNUNET_assert (3 == found);
167 GNUNET_assert (0 ==
168 GNUNET_memcmp (&p2,
169 &pid));
170 GNUNET_HELLO_builder_free (b2);
171 }
172
173 GNUNET_HELLO_builder_free (b);
174
175 GNUNET_CRYPTO_mpi_print_unsigned (priv.d,
176 sizeof (priv.d),
177 GCRYMPI_CONST_ONE);
178 priv.d[0] &= 248;
179 priv.d[31] &= 127;
180 priv.d[31] |= 64;
181 {
182 char *buf;
183
184 buf = GNUNET_STRINGS_data_to_string_alloc (&priv,
185 sizeof (priv));
186 fprintf (stderr,
187 "PK: %s\n",
188 buf);
189 GNUNET_free (buf);
190 }
191 GNUNET_CRYPTO_eddsa_key_get_public (&priv,
192 &pid.public_key);
193 b = GNUNET_HELLO_builder_new (&pid);
194 GNUNET_assert (GNUNET_OK ==
195 GNUNET_HELLO_builder_add_address (b,
196 "a://first"));
197 GNUNET_assert (GNUNET_OK ==
198 GNUNET_HELLO_builder_add_address (b,
199 "b://second"));
200 {
201 char *url;
202
203 url = GNUNET_HELLO_builder_to_url (b,
204 &priv);
205 fprintf (stderr,
206 "TV: %s\n",
207 url);
208 GNUNET_free (url);
209 }
210
211 return 0;
212}
diff --git a/src/hostlist/gnunet-daemon-hostlist_client.c b/src/hostlist/gnunet-daemon-hostlist_client.c
index 44966d3de..1f7d4cc35 100644
--- a/src/hostlist/gnunet-daemon-hostlist_client.c
+++ b/src/hostlist/gnunet-daemon-hostlist_client.c
@@ -1635,7 +1635,11 @@ GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
1635 "PROXY_TYPE", 1635 "PROXY_TYPE",
1636 &proxytype_str)) 1636 &proxytype_str))
1637 { 1637 {
1638 GNUNET_STRINGS_utf8_toupper (proxytype_str, proxytype_str); 1638 if (GNUNET_OK != GNUNET_STRINGS_utf8_toupper (proxytype_str,
1639 proxytype_str))
1640 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1641 "Unable to convert `%s' to UTF-8 uppercase\n",
1642 proxytype_str);
1639 proxy_type = CURLPROXY_HTTP; 1643 proxy_type = CURLPROXY_HTTP;
1640 if (0 == strcmp (proxytype_str, "HTTP")) 1644 if (0 == strcmp (proxytype_str, "HTTP"))
1641 proxy_type = CURLPROXY_HTTP; 1645 proxy_type = CURLPROXY_HTTP;
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index e535c208a..5a2110974 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -95,6 +95,7 @@ test_identity_defaults_LDADD = \
95 $(top_builddir)/src/util/libgnunetutil.la 95 $(top_builddir)/src/util/libgnunetutil.la
96 96
97EXTRA_DIST = \ 97EXTRA_DIST = \
98 test_identity.conf 98 test_identity.conf \
99 test_identity_messages.sh
99 100
100 101
diff --git a/src/identity/gnunet-service-identity.c b/src/identity/gnunet-service-identity.c
index 2bb4b0897..51f897557 100644
--- a/src/identity/gnunet-service-identity.c
+++ b/src/identity/gnunet-service-identity.c
@@ -489,8 +489,7 @@ handle_get_default_message (void *cls,
489 char *identifier; 489 char *identifier;
490 490
491 name = GNUNET_strdup ((const char *) &gdm[1]); 491 name = GNUNET_strdup ((const char *) &gdm[1]);
492 GNUNET_STRINGS_utf8_tolower ((const char *) &gdm[1], 492 GNUNET_STRINGS_utf8_tolower ((const char *) &gdm[1], name);
493 name);
494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
495 "Received GET_DEFAULT for service `%s' from client\n", 494 "Received GET_DEFAULT for service `%s' from client\n",
496 name); 495 name);
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index e4b02b8ee..8808f6802 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -57,6 +57,7 @@ gnunetinclude_HEADERS = \
57 gnunet_gnsrecord_plugin.h \ 57 gnunet_gnsrecord_plugin.h \
58 gnu_name_system_record_types.h \ 58 gnu_name_system_record_types.h \
59 gnunet_hello_lib.h \ 59 gnunet_hello_lib.h \
60 gnunet_hello_uri_lib.h \
60 gnunet_helper_lib.h \ 61 gnunet_helper_lib.h \
61 gnunet_identity_service.h \ 62 gnunet_identity_service.h \
62 gnunet_abe_lib.h \ 63 gnunet_abe_lib.h \
diff --git a/src/include/gnunet_block_group_lib.h b/src/include/gnunet_block_group_lib.h
index 6cb601757..b03e913c6 100644
--- a/src/include/gnunet_block_group_lib.h
+++ b/src/include/gnunet_block_group_lib.h
@@ -94,7 +94,7 @@ GNUNET_BLOCK_GROUP_bf_create (void *cls,
94 * @return #GNUNET_YES if @a hc is (likely) a duplicate 94 * @return #GNUNET_YES if @a hc is (likely) a duplicate
95 * #GNUNET_NO if @a hc was definitively not in @bg (but now is) 95 * #GNUNET_NO if @a hc was definitively not in @bg (but now is)
96 */ 96 */
97int 97enum GNUNET_GenericReturnValue
98GNUNET_BLOCK_GROUP_bf_test_and_set (struct GNUNET_BLOCK_Group *bg, 98GNUNET_BLOCK_GROUP_bf_test_and_set (struct GNUNET_BLOCK_Group *bg,
99 const struct GNUNET_HashCode *hc); 99 const struct GNUNET_HashCode *hc);
100 100
diff --git a/src/include/gnunet_block_lib.h b/src/include/gnunet_block_lib.h
index 5640209a6..515b8256c 100644
--- a/src/include/gnunet_block_lib.h
+++ b/src/include/gnunet_block_lib.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2010 GNUnet e.V. 3 Copyright (C) 2010, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -119,6 +119,12 @@ enum GNUNET_BLOCK_Type
119 GNUNET_BLOCK_TYPE_REVOCATION = 12, 119 GNUNET_BLOCK_TYPE_REVOCATION = 12,
120 120
121 /** 121 /**
122 * Type of a block that contains a DHT-NG HELLO for a peer (for
123 * DHT and CADET find-peer operations).
124 */
125 GNUNET_BLOCK_TYPE_DHT_URL_HELLO = 13,
126
127 /**
122 * Block to store a cadet regex state 128 * Block to store a cadet regex state
123 */ 129 */
124 GNUNET_BLOCK_TYPE_REGEX = 22, 130 GNUNET_BLOCK_TYPE_REGEX = 22,
@@ -156,108 +162,35 @@ enum GNUNET_BLOCK_Type
156 162
157 163
158/** 164/**
159 * Flags that can be set to control the evaluation.
160 * @deprecated
161 */
162enum GNUNET_BLOCK_EvaluationOptions
163{
164 /**
165 * Default behavior.
166 */
167 GNUNET_BLOCK_EO_NONE = 0,
168
169 /**
170 * The block is obtained from the local database, skip cryptographic
171 * checks.
172 */
173 GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO = 1
174};
175
176
177/**
178 * Possible ways for how a block may relate to a query. 165 * Possible ways for how a block may relate to a query.
179 * @deprecated
180 */ 166 */
181enum GNUNET_BLOCK_EvaluationResult 167enum GNUNET_BLOCK_ReplyEvaluationResult
182{ 168{
183 /**
184 * Valid result, and there may be more.
185 */
186 GNUNET_BLOCK_EVALUATION_OK_MORE = 0,
187 169
188 /** 170 /**
189 * Last possible valid result. 171 * Specified block type not supported by any plugin.
190 */ 172 */
191 GNUNET_BLOCK_EVALUATION_OK_LAST = 1, 173 GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED = -1,
192 174
193 /** 175 /**
194 * Valid result, but suppressed because it is a duplicate. 176 * Valid result, but suppressed because it is a duplicate.
195 */ 177 */
196 GNUNET_BLOCK_EVALUATION_OK_DUPLICATE = 2, 178 GNUNET_BLOCK_REPLY_OK_DUPLICATE = 0,
197
198 /**
199 * Block does not match query (invalid result)
200 */
201 GNUNET_BLOCK_EVALUATION_RESULT_INVALID = 3,
202 179
203 /** 180 /**
204 * Block does not match xquery (valid result, not relevant for the request) 181 * Block does not match xquery (valid result, not relevant for the request)
205 */ 182 */
206 GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT = 4, 183 GNUNET_BLOCK_REPLY_IRRELEVANT = 1,
207
208 /**
209 * Query is valid, no reply given.
210 */
211 GNUNET_BLOCK_EVALUATION_REQUEST_VALID = 10,
212
213 /**
214 * Query format does not match block type (invalid query). For
215 * example, xquery not given or xquery_size not appropriate for
216 * type.
217 */
218 GNUNET_BLOCK_EVALUATION_REQUEST_INVALID = 11,
219
220 /**
221 * Specified block type not supported by this plugin.
222 */
223 GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED = 20
224};
225
226
227/**
228 * Possible ways for how a block may relate to a query.
229 */
230enum GNUNET_BLOCK_ReplyEvaluationResult
231{
232 /**
233 * Valid result, but suppressed because it is a duplicate.
234 */
235 GNUNET_BLOCK_REPLY_OK_DUPLICATE = 0,
236 184
237 /** 185 /**
238 * Valid result, and there may be more. 186 * Valid result, and there may be more.
239 */ 187 */
240 GNUNET_BLOCK_REPLY_OK_MORE = 1, 188 GNUNET_BLOCK_REPLY_OK_MORE = 2,
241 189
242 /** 190 /**
243 * Last possible valid result. 191 * Last possible valid result.
244 */ 192 */
245 GNUNET_BLOCK_REPLY_OK_LAST = 2, 193 GNUNET_BLOCK_REPLY_OK_LAST = 3
246
247 /**
248 * Specified block type not supported by any plugin.
249 */
250 GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED = -1,
251
252 /**
253 * Block does not match query (invalid result)
254 */
255 GNUNET_BLOCK_REPLY_INVALID = -2,
256
257 /**
258 * Block does not match xquery (valid result, not relevant for the request)
259 */
260 GNUNET_BLOCK_REPLY_IRRELEVANT = -3,
261 194
262}; 195};
263 196
@@ -356,44 +289,12 @@ GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg);
356 289
357 290
358/** 291/**
359 * Function called to validate a reply or a request. For 292 * Function called to validate if a reply is good for a
360 * request evaluation, simply pass "NULL" for the @a reply_block. 293 * particular query.
361 * Note that it is assumed that the reply has already been
362 * matched to the key (and signatures checked) as it would
363 * be done with the #GNUNET_BLOCK_get_key() function.
364 *
365 * @param ctx block contxt
366 * @param type block type
367 * @param group block group to use for evaluation
368 * @param eo evaluation options to control evaluation
369 * @param query original query (hash)
370 * @param xquery extrended query data (can be NULL, depending on type)
371 * @param xquery_size number of bytes in @a xquery
372 * @param reply_block response to validate
373 * @param reply_block_size number of bytes in @a reply_block
374 * @return characterization of result
375 * @deprecated
376 */
377enum GNUNET_BLOCK_EvaluationResult
378GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx,
379 enum GNUNET_BLOCK_Type type,
380 struct GNUNET_BLOCK_Group *group,
381 enum GNUNET_BLOCK_EvaluationOptions eo,
382 const struct GNUNET_HashCode *query,
383 const void *xquery,
384 size_t xquery_size,
385 const void *reply_block,
386 size_t reply_block_size);
387
388
389/**
390 * Function called to validate a reply.
391 * Also checks the query key against the block contents
392 * as it would be done with the #GNUNET_BLOCK_get_key() function.
393 * 294 *
394 * @param ctx block contxt 295 * @param ctx block contxt
395 * @param type block type 296 * @param type block type
396 * @param group block group to use for evaluation 297 * @param[in,out] group block group to use for evaluation
397 * @param query original query (hash) 298 * @param query original query (hash)
398 * @param xquery extrended query data (can be NULL, depending on type) 299 * @param xquery extrended query data (can be NULL, depending on type)
399 * @param xquery_size number of bytes in @a xquery 300 * @param xquery_size number of bytes in @a xquery
@@ -436,7 +337,6 @@ GNUNET_BLOCK_check_query (struct GNUNET_BLOCK_Context *ctx,
436 * 337 *
437 * @param ctx block contxt 338 * @param ctx block contxt
438 * @param type block type 339 * @param type block type
439 * @param query query key (hash)
440 * @param block payload to put 340 * @param block payload to put
441 * @param block_size number of bytes in @a block 341 * @param block_size number of bytes in @a block
442 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not, 342 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not,
@@ -445,13 +345,14 @@ GNUNET_BLOCK_check_query (struct GNUNET_BLOCK_Context *ctx,
445enum GNUNET_GenericReturnValue 345enum GNUNET_GenericReturnValue
446GNUNET_BLOCK_check_block (struct GNUNET_BLOCK_Context *ctx, 346GNUNET_BLOCK_check_block (struct GNUNET_BLOCK_Context *ctx,
447 enum GNUNET_BLOCK_Type type, 347 enum GNUNET_BLOCK_Type type,
448 const struct GNUNET_HashCode *query,
449 const void *block, 348 const void *block,
450 size_t block_size); 349 size_t block_size);
451 350
452 351
453/** 352/**
454 * Function called to obtain the key for a block. 353 * Function called to obtain the @a key for a @a block.
354 * If the @a block is malformed, the function should
355 * zero-out @a key and return #GNUNET_OK.
455 * 356 *
456 * @param ctx block context 357 * @param ctx block context
457 * @param type block type 358 * @param type block type
@@ -459,9 +360,8 @@ GNUNET_BLOCK_check_block (struct GNUNET_BLOCK_Context *ctx,
459 * @param block_size number of bytes in @a block 360 * @param block_size number of bytes in @a block
460 * @param key set to the key (query) for the given block 361 * @param key set to the key (query) for the given block
461 * @return #GNUNET_YES on success, 362 * @return #GNUNET_YES on success,
462 * #GNUNET_NO if the block is malformed 363 * #GNUNET_NO if extracting a key from a block of this @a type does not work
463 * #GNUNET_SYSERR if type not supported 364 * #GNUNET_SYSERR if @a type not supported
464 * (or if extracting a key from a block of this type does not work)
465 */ 365 */
466enum GNUNET_GenericReturnValue 366enum GNUNET_GenericReturnValue
467GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx, 367GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
diff --git a/src/include/gnunet_block_plugin.h b/src/include/gnunet_block_plugin.h
index 2c9a3839d..1fa7ccf8b 100644
--- a/src/include/gnunet_block_plugin.h
+++ b/src/include/gnunet_block_plugin.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2010,2013,2017 GNUnet e.V. 3 Copyright (C) 2010, 2013, 2017, 2021, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -163,43 +163,9 @@ typedef struct GNUNET_BLOCK_Group *
163 163
164 164
165/** 165/**
166 * Function called to validate a reply or a request. For
167 * request evaluation, simply pass "NULL" for the @a reply_block.
168 * Note that it is assumed that the reply has already been
169 * matched to the key (and signatures checked) as it would
170 * be done with the "get_key" function.
171 *
172 * @param cls closure
173 * @param ctx block context
174 * @param type block type
175 * @param group which block group to use for evaluation
176 * @param eo evaluation options to control evaluation
177 * @param query original query (hash)
178 * @param xquery extrended query data (can be NULL, depending on type)
179 * @param xquery_size number of bytes in @a xquery
180 * @param reply_block response to validate
181 * @param reply_block_size number of bytes in @a reply_block
182 * @return characterization of result
183 * @deprecated
184 */
185typedef enum GNUNET_BLOCK_EvaluationResult
186(*GNUNET_BLOCK_EvaluationFunction)(void *cls,
187 struct GNUNET_BLOCK_Context *ctx,
188 enum GNUNET_BLOCK_Type type,
189 struct GNUNET_BLOCK_Group *group,
190 enum GNUNET_BLOCK_EvaluationOptions eo,
191 const struct GNUNET_HashCode *query,
192 const void *xquery,
193 size_t xquery_size,
194 const void *reply_block,
195 size_t reply_block_size);
196
197
198/**
199 * Function called to validate a query. 166 * Function called to validate a query.
200 * 167 *
201 * @param cls closure 168 * @param cls closure
202 * @param ctx block context
203 * @param type block type 169 * @param type block type
204 * @param query original query (hash) 170 * @param query original query (hash)
205 * @param xquery extrended query data (can be NULL, depending on type) 171 * @param xquery extrended query data (can be NULL, depending on type)
@@ -215,19 +181,17 @@ typedef enum GNUNET_GenericReturnValue
215 181
216 182
217/** 183/**
218 * Function called to validate a block for storage. 184 * Function called to validate a @a block for storage.
219 * 185 *
220 * @param cls closure 186 * @param cls closure
221 * @param type block type 187 * @param type block type
222 * @param query key for the block (hash), must match exactly
223 * @param block block data to validate 188 * @param block block data to validate
224 * @param block_size number of bytes in @a block 189 * @param block_size number of bytes in @a block
225 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 190 * @return #GNUNET_OK if the @a block is fine, #GNUNET_NO if not, #GNUNET_SYSERR if the @a type is not supported
226 */ 191 */
227typedef enum GNUNET_GenericReturnValue 192typedef enum GNUNET_GenericReturnValue
228(*GNUNET_BLOCK_BlockEvaluationFunction)(void *cls, 193(*GNUNET_BLOCK_BlockEvaluationFunction)(void *cls,
229 enum GNUNET_BLOCK_Type type, 194 enum GNUNET_BLOCK_Type type,
230 const struct GNUNET_HashCode *query,
231 const void *block, 195 const void *block,
232 size_t block_size); 196 size_t block_size);
233 197
@@ -260,17 +224,18 @@ typedef enum GNUNET_BLOCK_ReplyEvaluationResult
260 224
261 225
262/** 226/**
263 * Function called to obtain the key for a block. 227 * Function called to obtain the @a key for a block.
228 * If the @a block is malformed, the function should
229 * zero-out @a key and return #GNUNET_OK.
264 * 230 *
265 * @param cls closure 231 * @param cls closure
266 * @param type block type 232 * @param type block type
267 * @param block block to get the key for 233 * @param block block to get the @a key for
268 * @param block_size number of bytes in @a block 234 * @param block_size number of bytes in @a block
269 * @param[out] key set to the key (query) for the given block 235 * @param[out] key set to the key (query) for the given block
270 * @return #GNUNET_YES on success, 236 * @return #GNUNET_YES on success,
271 * #GNUNET_NO if the block is malformed 237 * #GNUNET_NO if extracting a key for this @a type does not work
272 * #GNUNET_SYSERR if type not supported 238 * #GNUNET_SYSERR if @a type not supported
273 * (or if extracting a key from a block of this type does not work)
274 */ 239 */
275typedef enum GNUNET_GenericReturnValue 240typedef enum GNUNET_GenericReturnValue
276(*GNUNET_BLOCK_GetKeyFunction) (void *cls, 241(*GNUNET_BLOCK_GetKeyFunction) (void *cls,
@@ -297,14 +262,6 @@ struct GNUNET_BLOCK_PluginFunctions
297 const enum GNUNET_BLOCK_Type *types; 262 const enum GNUNET_BLOCK_Type *types;
298 263
299 /** 264 /**
300 * Main function of a block plugin. Allows us to check if a
301 * block matches a query.
302 *
303 * @param deprecated
304 */
305 GNUNET_BLOCK_EvaluationFunction evaluate;
306
307 /**
308 * Obtain the key for a given block (if possible). 265 * Obtain the key for a given block (if possible).
309 */ 266 */
310 GNUNET_BLOCK_GetKeyFunction get_key; 267 GNUNET_BLOCK_GetKeyFunction get_key;
diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h
index 4472d3ee8..9bcd99c7b 100644
--- a/src/include/gnunet_common.h
+++ b/src/include/gnunet_common.h
@@ -623,6 +623,31 @@ GNUNET_abort_ (void) GNUNET_NORETURN;
623 623
624 624
625/** 625/**
626 * Convert a buffer to an 8-character string
627 * representative of the contents. This is used
628 * for logging binary data when debugging.
629 *
630 * @param buf buffer to log
631 * @param buf_size number of bytes in @a buf
632 * @return text representation of buf, valid until next
633 * call to this function
634 */
635const char *
636GNUNET_b2s (const void *buf,
637 size_t buf_size);
638
639
640/**
641 * Convert a fixed-sized object to a string using
642 * #GNUNET_b2s().
643 *
644 * @param obj address of object to convert
645 * @return string representing the binary obj buffer
646 */
647#define GNUNET_B2S(obj) GNUNET_b2s ((obj), sizeof (*(obj)))
648
649
650/**
626 * @ingroup logging 651 * @ingroup logging
627 * Ignore the next @a n calls to the log function. 652 * Ignore the next @a n calls to the log function.
628 * 653 *
@@ -1240,7 +1265,7 @@ GNUNET_is_zero_ (const void *a,
1240 * @return GNUNET_YES if a is zero, GNUNET_NO otherwise 1265 * @return GNUNET_YES if a is zero, GNUNET_NO otherwise
1241 */ 1266 */
1242#define GNUNET_is_zero(a) \ 1267#define GNUNET_is_zero(a) \
1243 GNUNET_is_zero_ (a, sizeof (*a)) 1268 GNUNET_is_zero_ ((a), sizeof (*(a)))
1244 1269
1245 1270
1246/** 1271/**
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 1ab135d80..72d783148 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -307,7 +307,7 @@ struct GNUNET_CRYPTO_SymmetricSessionKey
307/** 307/**
308 * Type of a nonce used for challenges. 308 * Type of a nonce used for challenges.
309 */ 309 */
310struct ChallengeNonceP 310struct GNUNET_CRYPTO_ChallengeNonceP
311{ 311{
312 /** 312 /**
313 * The value of the nonce. Note that this is NOT a hash. 313 * The value of the nonce. Note that this is NOT a hash.
@@ -2551,9 +2551,9 @@ GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv);
2551 * @param[out] pub where to write the public key 2551 * @param[out] pub where to write the public key
2552 */ 2552 */
2553void 2553void
2554GNUNET_CRYPTO_cs_private_key_get_public (const struct 2554GNUNET_CRYPTO_cs_private_key_get_public (
2555 GNUNET_CRYPTO_CsPrivateKey *priv, 2555 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
2556 struct GNUNET_CRYPTO_CsPublicKey *pub); 2556 struct GNUNET_CRYPTO_CsPublicKey *pub);
2557 2557
2558 2558
2559/** 2559/**
@@ -2565,11 +2565,13 @@ GNUNET_CRYPTO_cs_private_key_get_public (const struct
2565 * Comment: Can be done in one HKDF shot and split output. 2565 * Comment: Can be done in one HKDF shot and split output.
2566 * 2566 *
2567 * @param nonce is a random nonce 2567 * @param nonce is a random nonce
2568 * @param seed seed to use in derivation
2568 * @param lts is a long-term-secret in form of a private key 2569 * @param lts is a long-term-secret in form of a private key
2569 * @param[out] r array containing derived secrets r0 and r1 2570 * @param[out] r array containing derived secrets r0 and r1
2570 */ 2571 */
2571void 2572void
2572GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce, 2573GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce,
2574 const char *seed,
2573 const struct GNUNET_CRYPTO_CsPrivateKey *lts, 2575 const struct GNUNET_CRYPTO_CsPrivateKey *lts,
2574 struct GNUNET_CRYPTO_CsRSecret r[2]); 2576 struct GNUNET_CRYPTO_CsRSecret r[2]);
2575 2577
@@ -2595,10 +2597,9 @@ GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
2595 * @param[out] bs array containing the two derived blinding secrets 2597 * @param[out] bs array containing the two derived blinding secrets
2596 */ 2598 */
2597void 2599void
2598GNUNET_CRYPTO_cs_blinding_secrets_derive (const struct 2600GNUNET_CRYPTO_cs_blinding_secrets_derive (
2599 GNUNET_CRYPTO_CsNonce *blind_seed, 2601 const struct GNUNET_CRYPTO_CsNonce *blind_seed,
2600 struct GNUNET_CRYPTO_CsBlindingSecret 2602 struct GNUNET_CRYPTO_CsBlindingSecret bs[2]);
2601 bs[2]);
2602 2603
2603 2604
2604/** 2605/**
@@ -2614,15 +2615,14 @@ GNUNET_CRYPTO_cs_blinding_secrets_derive (const struct
2614 * @param[out] blinded_r_pub array of the two blinded R 2615 * @param[out] blinded_r_pub array of the two blinded R
2615 */ 2616 */
2616void 2617void
2617GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret 2618GNUNET_CRYPTO_cs_calc_blinded_c (
2618 bs[2], 2619 const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
2619 const struct GNUNET_CRYPTO_CsRPublic r_pub[2], 2620 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
2620 const struct GNUNET_CRYPTO_CsPublicKey *pub, 2621 const struct GNUNET_CRYPTO_CsPublicKey *pub,
2621 const void *msg, 2622 const void *msg,
2622 size_t msg_len, 2623 size_t msg_len,
2623 struct GNUNET_CRYPTO_CsC blinded_c[2], 2624 struct GNUNET_CRYPTO_CsC blinded_c[2],
2624 struct GNUNET_CRYPTO_CsRPublic 2625 struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2]);
2625 blinded_r_pub[2]);
2626 2626
2627 2627
2628/** 2628/**
@@ -2642,13 +2642,12 @@ GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret
2642 * @return 0 or 1 for b (see Clause Blind Signature Scheme) 2642 * @return 0 or 1 for b (see Clause Blind Signature Scheme)
2643 */ 2643 */
2644unsigned int 2644unsigned int
2645GNUNET_CRYPTO_cs_sign_derive (const struct GNUNET_CRYPTO_CsPrivateKey *priv, 2645GNUNET_CRYPTO_cs_sign_derive (
2646 const struct GNUNET_CRYPTO_CsRSecret r[2], 2646 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
2647 const struct GNUNET_CRYPTO_CsC c[2], 2647 const struct GNUNET_CRYPTO_CsRSecret r[2],
2648 const struct GNUNET_CRYPTO_CsNonce *nonce, 2648 const struct GNUNET_CRYPTO_CsC c[2],
2649 struct GNUNET_CRYPTO_CsBlindS * 2649 const struct GNUNET_CRYPTO_CsNonce *nonce,
2650 blinded_signature_scalar 2650 struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar);
2651 );
2652 2651
2653 2652
2654/** 2653/**
@@ -2659,10 +2658,10 @@ GNUNET_CRYPTO_cs_sign_derive (const struct GNUNET_CRYPTO_CsPrivateKey *priv,
2659 * @param[out] signature_scalar where to write the unblinded signature 2658 * @param[out] signature_scalar where to write the unblinded signature
2660 */ 2659 */
2661void 2660void
2662GNUNET_CRYPTO_cs_unblind (const struct 2661GNUNET_CRYPTO_cs_unblind (
2663 GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar, 2662 const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
2664 const struct GNUNET_CRYPTO_CsBlindingSecret *bs, 2663 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
2665 struct GNUNET_CRYPTO_CsS *signature_scalar); 2664 struct GNUNET_CRYPTO_CsS *signature_scalar);
2666 2665
2667 2666
2668/** 2667/**
diff --git a/src/include/gnunet_datacache_lib.h b/src/include/gnunet_datacache_lib.h
index 11076e3e7..737a5c845 100644
--- a/src/include/gnunet_datacache_lib.h
+++ b/src/include/gnunet_datacache_lib.h
@@ -154,6 +154,7 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
154 * 154 *
155 * @param h handle to the datacache 155 * @param h handle to the datacache
156 * @param key area of the keyspace to look into 156 * @param key area of the keyspace to look into
157 * @param type entries of which type are relevant?
157 * @param num_results number of results that should be returned to @a iter 158 * @param num_results number of results that should be returned to @a iter
158 * @param iter maybe NULL (to just count) 159 * @param iter maybe NULL (to just count)
159 * @param iter_cls closure for @a iter 160 * @param iter_cls closure for @a iter
@@ -162,6 +163,7 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
162unsigned int 163unsigned int
163GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h, 164GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h,
164 const struct GNUNET_HashCode *key, 165 const struct GNUNET_HashCode *key,
166 enum GNUNET_BLOCK_Type type,
165 unsigned int num_results, 167 unsigned int num_results,
166 GNUNET_DATACACHE_Iterator iter, 168 GNUNET_DATACACHE_Iterator iter,
167 void *iter_cls); 169 void *iter_cls);
diff --git a/src/include/gnunet_datacache_plugin.h b/src/include/gnunet_datacache_plugin.h
index 24570be72..34bf5f277 100644
--- a/src/include/gnunet_datacache_plugin.h
+++ b/src/include/gnunet_datacache_plugin.h
@@ -158,14 +158,16 @@ struct GNUNET_DATACACHE_PluginFunctions
158 158
159 159
160 /** 160 /**
161 * Iterate over the results that are "close" to a particular key in 161 * Iterate over the results that are "close" to a particular key in the
162 * the datacache. "close" is defined as numerically larger than @a 162 * datacache. "close" is defined as returning the @a num_results that are
163 * key (when interpreted as a circular address space), with small 163 * numerically closest and larger than @a key and also @a num_results that
164 * distance. 164 * are numerically lower than @a key. Thus, the maximum number of results
165 * returned is actually twice @a num_results.
165 * 166 *
166 * @param cls closure (internal context for the plugin) 167 * @param cls closure (internal context for the plugin)
167 * @param key area of the keyspace to look into 168 * @param key area of the keyspace to look into
168 * @param num_results number of results that should be returned to @a iter 169 * @param type desired block type for the replies
170 * @param num_results half the number of results that should be returned to @a iter
169 * @param iter maybe NULL (to just count) 171 * @param iter maybe NULL (to just count)
170 * @param iter_cls closure for @a iter 172 * @param iter_cls closure for @a iter
171 * @return the number of results found 173 * @return the number of results found
@@ -173,6 +175,7 @@ struct GNUNET_DATACACHE_PluginFunctions
173 unsigned int 175 unsigned int
174 (*get_closest) (void *cls, 176 (*get_closest) (void *cls,
175 const struct GNUNET_HashCode *key, 177 const struct GNUNET_HashCode *key,
178 enum GNUNET_BLOCK_Type type,
176 unsigned int num_results, 179 unsigned int num_results,
177 GNUNET_DATACACHE_Iterator iter, 180 GNUNET_DATACACHE_Iterator iter,
178 void *iter_cls); 181 void *iter_cls);
diff --git a/src/include/gnunet_dht_service.h b/src/include/gnunet_dht_service.h
index 768b19fb1..22b659d66 100644
--- a/src/include/gnunet_dht_service.h
+++ b/src/include/gnunet_dht_service.h
@@ -101,14 +101,14 @@ enum GNUNET_DHT_RouteOption
101 GNUNET_DHT_RO_RECORD_ROUTE = 2, 101 GNUNET_DHT_RO_RECORD_ROUTE = 2,
102 102
103 /** 103 /**
104 * This is a 'FIND-PEER' request, so approximate results are fine. 104 * Approximate results are fine.
105 */ 105 */
106 GNUNET_DHT_RO_FIND_PEER = 4, 106 GNUNET_DHT_RO_FIND_APPROXIMATE = 4,
107 107
108 /** 108 /**
109 * Flag given to monitors if this was the last hop for a GET/PUT. 109 * Flag given to monitors if this was the last hop for a GET/PUT.
110 * This is only used for internal processing. 110 * This is only used for internal processing.
111 */ 111 */
112 GNUNET_DHT_RO_LAST_HOP = 65535 112 GNUNET_DHT_RO_LAST_HOP = 65535
113}; 113};
114 114
@@ -131,11 +131,6 @@ struct GNUNET_DHT_HopSignature
131 struct GNUNET_TIME_AbsoluteNBO expiration_time; 131 struct GNUNET_TIME_AbsoluteNBO expiration_time;
132 132
133 /** 133 /**
134 * Key of the block.
135 */
136 struct GNUNET_HashCode key;
137
138 /**
139 * Hash over the payload of the block. 134 * Hash over the payload of the block.
140 */ 135 */
141 struct GNUNET_HashCode h_data; 136 struct GNUNET_HashCode h_data;
@@ -181,6 +176,7 @@ struct GNUNET_DHT_PathElement
181 176
182}; 177};
183 178
179
184GNUNET_NETWORK_STRUCT_END 180GNUNET_NETWORK_STRUCT_END
185 181
186/** 182/**
@@ -266,7 +262,7 @@ GNUNET_DHT_put_cancel (struct GNUNET_DHT_PutHandle *ph);
266 * 262 *
267 * @param cls closure 263 * @param cls closure
268 * @param exp when will this value expire 264 * @param exp when will this value expire
269 * @param key key of the result 265 * @param query_hash key of the query
270 * @param get_path peers on reply path (or NULL if not recorded) 266 * @param get_path peers on reply path (or NULL if not recorded)
271 * [0] = datastore's first neighbor, [length - 1] = local peer 267 * [0] = datastore's first neighbor, [length - 1] = local peer
272 * @param get_path_length number of entries in @a get_path 268 * @param get_path_length number of entries in @a get_path
@@ -282,7 +278,7 @@ GNUNET_DHT_put_cancel (struct GNUNET_DHT_PutHandle *ph);
282typedef void 278typedef void
283(*GNUNET_DHT_GetIterator) (void *cls, 279(*GNUNET_DHT_GetIterator) (void *cls,
284 struct GNUNET_TIME_Absolute exp, 280 struct GNUNET_TIME_Absolute exp,
285 const struct GNUNET_HashCode *key, 281 const struct GNUNET_HashCode *query_hash,
286 const struct GNUNET_DHT_PathElement *get_path, 282 const struct GNUNET_DHT_PathElement *get_path,
287 unsigned int get_path_length, 283 unsigned int get_path_length,
288 const struct GNUNET_DHT_PathElement *put_path, 284 const struct GNUNET_DHT_PathElement *put_path,
@@ -487,7 +483,6 @@ GNUNET_DHT_pp2s (const struct GNUNET_DHT_PathElement *path,
487 * the last signature on the path is never verified as that is the slot where 483 * the last signature on the path is never verified as that is the slot where
488 * our peer (@a me) would need to sign. 484 * our peer (@a me) would need to sign.
489 * 485 *
490 * @param key key of the data (not necessarily the query hash)
491 * @param data payload (the block) 486 * @param data payload (the block)
492 * @param data_size number of bytes in @a data 487 * @param data_size number of bytes in @a data
493 * @param exp_time expiration time of @a data 488 * @param exp_time expiration time of @a data
@@ -501,8 +496,7 @@ GNUNET_DHT_pp2s (const struct GNUNET_DHT_PathElement *path,
501 * @a get_path_len + @a put_path_len - 1 if no signature was valid 496 * @a get_path_len + @a put_path_len - 1 if no signature was valid
502 */ 497 */
503unsigned int 498unsigned int
504GNUNET_DHT_verify_path (const struct GNUNET_HashCode *key, 499GNUNET_DHT_verify_path (const void *data,
505 const void *data,
506 size_t data_size, 500 size_t data_size,
507 struct GNUNET_TIME_Absolute exp_time, 501 struct GNUNET_TIME_Absolute exp_time,
508 const struct GNUNET_DHT_PathElement *put_path, 502 const struct GNUNET_DHT_PathElement *put_path,
@@ -512,6 +506,63 @@ GNUNET_DHT_verify_path (const struct GNUNET_HashCode *key,
512 const struct GNUNET_PeerIdentity *me); 506 const struct GNUNET_PeerIdentity *me);
513 507
514 508
509/**
510 * Handle to get a HELLO URL from the DHT for manual bootstrapping.
511 */
512struct GNUNET_DHT_HelloGetHandle;
513
514
515/**
516 * Signature called with the result of a HELLO GET operation.
517 *
518 * @param cls closure
519 * @param hello_url the resulting HELLO URL, NULL on error
520 */
521typedef void
522(*GNUNET_DHT_HelloGetCallback)(void *cls,
523 const char *hello_url);
524
525
526/**
527 * Obtain HELLO URL of the DHT identified by @a dht_handle.
528 *
529 * @param dht_handle DHT to query
530 * @param cb function to call with the result
531 * @param cb_cls closure for @a cb
532 * @return NULL on failure
533 */
534struct GNUNET_DHT_HelloGetHandle *
535GNUNET_DHT_hello_get (struct GNUNET_DHT_Handle *dht_handle,
536 GNUNET_DHT_HelloGetCallback cb,
537 void *cb_cls);
538
539
540/**
541 * Cancel hello get operation.
542 *
543 * @param[in] hgh operation to cancel.
544 */
545void
546GNUNET_DHT_hello_get_cancel (struct GNUNET_DHT_HelloGetHandle *hgh);
547
548
549/**
550 * Offer HELLO URL of the DHT identified by @a dht_handle.
551 * Callback may be invoked once, only way to cancel is to
552 * disconnect @a dht_handle.
553 *
554 * @param dht_handle DHT to query
555 * @param url URL with a HELLO to offer to the DHT
556 * @param cb function called when done
557 * @param cb_cls closure for @a cb
558 */
559void
560GNUNET_DHT_hello_offer (struct GNUNET_DHT_Handle *dht_handle,
561 const char *url,
562 GNUNET_SCHEDULER_TaskCallback cb,
563 void *cb_cls);
564
565
515#if 0 /* keep Emacsens' auto-indent happy */ 566#if 0 /* keep Emacsens' auto-indent happy */
516{ 567{
517#endif 568#endif
diff --git a/src/include/gnunet_dhtu_plugin.h b/src/include/gnunet_dhtu_plugin.h
index 2c97d5848..fa0b5f667 100644
--- a/src/include/gnunet_dhtu_plugin.h
+++ b/src/include/gnunet_dhtu_plugin.h
@@ -59,15 +59,6 @@ struct GNUNET_DHTU_PreferenceHandle;
59 59
60 60
61/** 61/**
62 * Key used to identify peer's position in the DHT.
63 */
64struct GNUNET_DHTU_HashKey
65{
66 struct GNUNET_HashCode sha512;
67};
68
69
70/**
71 * The datastore service will pass a pointer to a struct 62 * The datastore service will pass a pointer to a struct
72 * of this type as the first and only argument to the 63 * of this type as the first and only argument to the
73 * entry point of each datastore plugin. 64 * entry point of each datastore plugin.
@@ -88,7 +79,6 @@ struct GNUNET_DHTU_PluginEnvironment
88 * Function to call with new addresses of this peer. 79 * Function to call with new addresses of this peer.
89 * 80 *
90 * @param cls the closure 81 * @param cls the closure
91 * @param key hash position of this address in the DHT
92 * @param address address under which we are likely reachable, 82 * @param address address under which we are likely reachable,
93 * pointer will remain valid until @e address_del_cb is called; to be used for HELLOs. Example: "ip+udp://1.1.1.1:2086/" 83 * pointer will remain valid until @e address_del_cb is called; to be used for HELLOs. Example: "ip+udp://1.1.1.1:2086/"
94 * @param source handle for sending from this address, NULL if we can only receive 84 * @param source handle for sending from this address, NULL if we can only receive
@@ -96,7 +86,6 @@ struct GNUNET_DHTU_PluginEnvironment
96 */ 86 */
97 void 87 void
98 (*address_add_cb)(void *cls, 88 (*address_add_cb)(void *cls,
99 struct GNUNET_DHTU_HashKey *key,
100 const char *address, 89 const char *address,
101 struct GNUNET_DHTU_Source *source, 90 struct GNUNET_DHTU_Source *source,
102 void **ctx); 91 void **ctx);
@@ -128,20 +117,19 @@ struct GNUNET_DHTU_PluginEnvironment
128 * that peer. 117 * that peer.
129 * 118 *
130 * @param cls the closure 119 * @param cls the closure
131 * @param pk public key of the target,
132 * pointer will remain valid until @e disconnect_cb is called
133 * @para peer_id hash position of the peer,
134 * pointer will remain valid until @e disconnect_cb is called
135 * @param target handle to the target, 120 * @param target handle to the target,
136 * pointer will remain valid until @e disconnect_cb is called 121 * pointer will remain valid until @e disconnect_cb is called
122 * @para pid peer identity,
123 * pointer will remain valid until @e disconnect_cb is called
137 * @param[out] ctx storage space for DHT to use in association with this target 124 * @param[out] ctx storage space for DHT to use in association with this target
138 */ 125 */
139 void 126 void
140 (*connect_cb)(void *cls, 127 (*connect_cb)(void *cls,
141 struct GNUNET_DHTU_Target *target, 128 struct GNUNET_DHTU_Target *target,
142 struct GNUNET_DHTU_HashKey *key, 129 const struct GNUNET_PeerIdentity *pid,
143 void **ctx); 130 void **ctx);
144 131
132
145 /** 133 /**
146 * Function to call when we disconnected from a peer and can henceforth 134 * Function to call when we disconnected from a peer and can henceforth
147 * cannot transmit to that peer anymore. 135 * cannot transmit to that peer anymore.
@@ -185,10 +173,12 @@ struct GNUNET_DHTU_PluginFunctions
185 * Request creation of a session with a peer at the given @a address. 173 * Request creation of a session with a peer at the given @a address.
186 * 174 *
187 * @param cls closure (internal context for the plugin) 175 * @param cls closure (internal context for the plugin)
188 * @param address target address to connect to 176 * @param pid target identity of the peer to connect to
177 * @param address target address URI to connect to
189 */ 178 */
190 void 179 void
191 (*try_connect) (void *cls, 180 (*try_connect) (void *cls,
181 const struct GNUNET_PeerIdentity *pid,
192 const char *address); 182 const char *address);
193 183
194 184
@@ -205,7 +195,7 @@ struct GNUNET_DHTU_PluginFunctions
205 struct GNUNET_DHTU_Target *target); 195 struct GNUNET_DHTU_Target *target);
206 196
207 /** 197 /**
208 * Do no long request underlay to keep the connection alive. 198 * Do no longer request underlay to keep the connection alive.
209 * 199 *
210 * @param cls closure 200 * @param cls closure
211 * @param target connection to keep alive 201 * @param target connection to keep alive
diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h
index 686035e2c..96936bad2 100644
--- a/src/include/gnunet_fs_service.h
+++ b/src/include/gnunet_fs_service.h
@@ -1729,7 +1729,7 @@ GNUNET_FS_file_information_get_id (struct GNUNET_FS_FileInformation *s);
1729 * @return "filename" field of the structure (can be NULL) 1729 * @return "filename" field of the structure (can be NULL)
1730 */ 1730 */
1731const char * 1731const char *
1732GNUNET_FS_file_information_get_filename (struct GNUNET_FS_FileInformation *s); 1732GNUNET_FS_file_information_get_filename (const struct GNUNET_FS_FileInformation *s);
1733 1733
1734 1734
1735/** 1735/**
diff --git a/src/include/gnunet_gns_service.h b/src/include/gnunet_gns_service.h
index 3f6c9b9aa..5c06f8045 100644
--- a/src/include/gnunet_gns_service.h
+++ b/src/include/gnunet_gns_service.h
@@ -48,12 +48,6 @@ extern "C" {
48 48
49 49
50/** 50/**
51 * String we use to indicate an empty label (top-level
52 * entry in the zone). DNS uses "@", so do we.
53 */
54#define GNUNET_GNS_EMPTY_LABEL_AT "@"
55
56/**
57 * Connection to the GNS service. 51 * Connection to the GNS service.
58 */ 52 */
59struct GNUNET_GNS_Handle; 53struct GNUNET_GNS_Handle;
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index fdbac3cf5..51dd5972d 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -44,6 +44,12 @@ extern "C" {
44#endif 44#endif
45 45
46/** 46/**
47 * String we use to indicate an empty label (top-level
48 * entry in the zone). DNS uses "@", so do we.
49 */
50#define GNUNET_GNS_EMPTY_LABEL_AT "@"
51
52/**
47 * Maximum size of a value that can be stored in a GNS block. 53 * Maximum size of a value that can be stored in a GNS block.
48 */ 54 */
49#define GNUNET_GNSRECORD_MAX_BLOCK_SIZE (63 * 1024) 55#define GNUNET_GNSRECORD_MAX_BLOCK_SIZE (63 * 1024)
@@ -299,8 +305,6 @@ struct GNUNET_GNSRECORD_ReverseRecord
299 /* followed by the name the delegator uses to refer to our namespace */ 305 /* followed by the name the delegator uses to refer to our namespace */
300}; 306};
301 307
302GNUNET_NETWORK_STRUCT_END
303
304 308
305/** 309/**
306 * Process a records that were decrypted from a block. 310 * Process a records that were decrypted from a block.
@@ -427,7 +431,8 @@ GNUNET_GNSRECORD_is_expired (const struct GNUNET_GNSRECORD_Data *rd);
427 431
428 432
429/** 433/**
430 * Normalize a UTF-8 string to UTF-8 NFC 434 * Normalize a UTF-8 string to a GNS name
435 *
431 * @param src source string 436 * @param src source string
432 * @return converted result 437 * @return converted result
433 */ 438 */
@@ -436,15 +441,6 @@ GNUNET_GNSRECORD_string_normalize (const char *src);
436 441
437 442
438/** 443/**
439 * Convert a UTF-8 string to UTF-8 lowercase
440 * @param src source string
441 * @return converted result
442 */
443char *
444GNUNET_GNSRECORD_string_to_lowercase (const char *src);
445
446
447/**
448 * Convert a zone to a string (for printing debug messages). 444 * Convert a zone to a string (for printing debug messages).
449 * This is one of the very few calls in the entire API that is 445 * This is one of the very few calls in the entire API that is
450 * NOT reentrant! 446 * NOT reentrant!
@@ -616,11 +612,14 @@ GNUNET_GNSRECORD_records_cmp (const struct GNUNET_GNSRECORD_Data *a,
616 * 612 *
617 * @param rd_count number of records given in @a rd 613 * @param rd_count number of records given in @a rd
618 * @param rd array of records 614 * @param rd array of records
615 * @param min minimum expiration time
619 * @return absolute expiration time 616 * @return absolute expiration time
620 */ 617 */
621struct GNUNET_TIME_Absolute 618struct GNUNET_TIME_Absolute
622GNUNET_GNSRECORD_record_get_expiration_time ( 619GNUNET_GNSRECORD_record_get_expiration_time (unsigned int rd_count,
623 unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd); 620 const struct
621 GNUNET_GNSRECORD_Data *rd,
622 struct GNUNET_TIME_Absolute min);
624 623
625 624
626/** 625/**
@@ -700,6 +699,77 @@ GNUNET_GNSRECORD_data_from_identity (const struct
700enum GNUNET_GenericReturnValue 699enum GNUNET_GenericReturnValue
701GNUNET_GNSRECORD_is_zonekey_type (uint32_t type); 700GNUNET_GNSRECORD_is_zonekey_type (uint32_t type);
702 701
702/**
703 * Check if this type is a critical record.
704 *
705 * @param type the type to check
706 * @return GNUNET_YES if it is critical.
707 */
708enum GNUNET_GenericReturnValue
709GNUNET_GNSRECORD_is_critical (uint32_t type);
710
711/**
712 * Normalize namestore records: Check for consistency and
713 * expirations. Purge expired records. Returns a "clean" record set.
714 * Also returns the minimum expiration time this block should be
715 * published under.
716 * Also checks rules with respect to labels (e.g. no delegations under
717 * the empty label)
718 *
719 * @param label the label under which this set (supposed to be) stored.
720 * @param rd input records
721 * @param rd_count size of the @a rd and @a rd_public arrays
722 * @param rd_public where to write the converted records
723 * @param rd_public_count number of records written to @a rd_public
724 * @param min_expiry the minimum expiration of this set
725 * @param include_private GNUNET_YES if private records should be included.
726 * @param emsg the error message if something went wrong
727 * @return GNUNET_OK if set could be normalized and is consistent
728 */
729enum GNUNET_GenericReturnValue
730GNUNET_GNSRECORD_normalize_record_set (const char *label,
731 const struct GNUNET_GNSRECORD_Data *rd,
732 unsigned int rd_count,
733 struct GNUNET_GNSRECORD_Data *rd_public,
734 unsigned int *rd_count_public,
735 struct GNUNET_TIME_Absolute *min_expiry,
736 int include_private,
737 char **emsg);
738
739
740/**
741 * Convert namestore records from the internal format to that
742 * suitable for publication (removes private records).
743 *
744 * @param label the label under which this set is (supposed to be) published.
745 * @param rd input records
746 * @param rd_count size of the @a rd and @a rd_public arrays
747 * @param rd_public where to write the converted records
748 * @param rd_public_count number of records written to @a rd_public
749 * @param expiry the expiration of the block
750 * @param emsg the error message if something went wrong
751 * @return GNUNET_OK if set is consistent and can be exported
752 */
753enum GNUNET_GenericReturnValue
754GNUNET_GNSRECORD_convert_records_for_export (const char *label,
755 const struct
756 GNUNET_GNSRECORD_Data *rd,
757 unsigned int rd_count,
758 struct GNUNET_GNSRECORD_Data *
759 rd_public,
760 unsigned int *rd_count_public,
761 struct GNUNET_TIME_Absolute *expiry,
762 char **emsg);
763
764/**
765 * Check label for invalid characters.
766 *
767 * @param label the label to check
768 * @param emsg an error message (NULL if label is valid). Will be allocated.
769 * @return GNUNET_OK if label is valid.
770 */
771enum GNUNET_GenericReturnValue
772GNUNET_GNSRECORD_label_check (const char*label, char **emsg);
703 773
704#if 0 /* keep Emacsens' auto-indent happy */ 774#if 0 /* keep Emacsens' auto-indent happy */
705{ 775{
diff --git a/src/include/gnunet_gnsrecord_plugin.h b/src/include/gnunet_gnsrecord_plugin.h
index aec22c3af..84b7c3c23 100644
--- a/src/include/gnunet_gnsrecord_plugin.h
+++ b/src/include/gnunet_gnsrecord_plugin.h
@@ -105,6 +105,18 @@ typedef const char *
105(*GNUNET_GNSRECORD_NumberToTypenameFunction) (void *cls, 105(*GNUNET_GNSRECORD_NumberToTypenameFunction) (void *cls,
106 uint32_t type); 106 uint32_t type);
107 107
108/**
109 * Function called to check for critical records.
110 *
111 * @param cls closure
112 * @param type number of a type to check
113 * @return GNUNET_YES if critical, otherwise GNUNET_NO
114 */
115typedef enum GNUNET_GenericReturnValue
116(*GNUNET_GNSRECORD_IsCriticalFunction) (void *cls,
117 uint32_t type);
118
119
108 120
109/** 121/**
110 * Each plugin is required to return a pointer to a struct of this 122 * Each plugin is required to return a pointer to a struct of this
@@ -136,6 +148,11 @@ struct GNUNET_GNSRECORD_PluginFunctions
136 * Number to typename. 148 * Number to typename.
137 */ 149 */
138 GNUNET_GNSRECORD_NumberToTypenameFunction number_to_typename; 150 GNUNET_GNSRECORD_NumberToTypenameFunction number_to_typename;
151
152 /**
153 * Is critical.
154 */
155 GNUNET_GNSRECORD_IsCriticalFunction is_critical;
139}; 156};
140 157
141/** @} */ /* end of group */ 158/** @} */ /* end of group */
diff --git a/src/include/gnunet_hello_uri_lib.h b/src/include/gnunet_hello_uri_lib.h
new file mode 100644
index 000000000..c109a151a
--- /dev/null
+++ b/src/include/gnunet_hello_uri_lib.h
@@ -0,0 +1,248 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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 */
20
21/**
22 * @author Christian Grothoff
23 * @file
24 * Helper library for handling HELLO URIs
25 *
26 * @defgroup hello_uri Hello_Uri library
27 * Helper library for handling HELLO URIs
28 *
29 * @{
30 */
31
32#ifndef GNUNET_HELLO_URI_LIB_H
33#define GNUNET_HELLO_URI_LIB_H
34
35#ifdef __cplusplus
36extern "C" {
37#if 0 /* keep Emacsens' auto-indent happy */
38}
39#endif
40#endif
41
42#include "gnunet_util_lib.h"
43
44
45/**
46 * Context for building (or parsing) HELLO URIs.
47 */
48struct GNUNET_HELLO_Builder;
49
50
51/**
52 * For how long are HELLO signatures valid?
53 */
54#define GNUNET_HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply ( \
55 GNUNET_TIME_UNIT_DAYS, 2)
56
57
58/**
59 * Allocate builder.
60 *
61 * @param pid peer the builder is for
62 * @return new builder
63 */
64struct GNUNET_HELLO_Builder *
65GNUNET_HELLO_builder_new (const struct GNUNET_PeerIdentity *pid);
66
67
68/**
69 * Release resources of a @a builder.
70 *
71 * @param[in] builder to free
72 */
73void
74GNUNET_HELLO_builder_free (struct GNUNET_HELLO_Builder *builder);
75
76
77/**
78 * Parse @a msg into builder.
79 *
80 * @param msg message to parse
81 * @return builder, NULL on failure
82 */
83struct GNUNET_HELLO_Builder *
84GNUNET_HELLO_builder_from_msg (const struct GNUNET_MessageHeader *msg);
85
86
87/**
88 * Parse @a block into builder.
89 *
90 * @param block DHT block to parse
91 * @param block_size number of bytes in @a block
92 * @return builder, NULL on failure
93 */
94struct GNUNET_HELLO_Builder *
95GNUNET_HELLO_builder_from_block (const void *block,
96 size_t block_size);
97
98
99/**
100 * Parse GNUnet HELLO @a url into builder.
101 *
102 * @param url URL to parse
103 * @return builder, NULL on failure
104 */
105struct GNUNET_HELLO_Builder *
106GNUNET_HELLO_builder_from_url (const char *url);
107
108
109/**
110 * Generate envelope with GNUnet HELLO message (including
111 * peer ID) from a @a builder
112 *
113 * @param builder builder to serialize
114 * @param priv private key to use to sign the result
115 * @return HELLO message matching @a builder
116 */
117struct GNUNET_MQ_Envelope *
118GNUNET_HELLO_builder_to_env (const struct GNUNET_HELLO_Builder *builder,
119 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv);
120
121
122/**
123 * Generate DHT HELLO message (without peer ID) from a @a builder
124 *
125 * @param builder builder to serialize
126 * @param priv private key to use to sign the result
127 * @return HELLO message matching @a builder
128 */
129struct GNUNET_MessageHeader *
130GNUNET_HELLO_builder_to_dht_hello_msg (
131 const struct GNUNET_HELLO_Builder *builder,
132 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv);
133
134
135/**
136 * Generate GNUnet HELLO URI from a @a builder
137 *
138 * @param builder builder to serialize
139 * @param priv private key to use to sign the result
140 * @return hello URI
141 */
142char *
143GNUNET_HELLO_builder_to_url (const struct GNUNET_HELLO_Builder *builder,
144 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv);
145
146/**
147 * Generate DHT block from a @a builder
148 *
149 * @param builder the builder to serialize
150 * @param priv private key to use to sign the result
151 * @param[out] block where to write the block, NULL to only calculate @a block_size
152 * @param[in,out] block_size input is number of bytes available in @a block,
153 * output is number of bytes needed in @a block
154 * @return #GNUNET_OK on success, #GNUNET_NO if @a block_size was too small
155 * or if @a block was NULL
156 */
157enum GNUNET_GenericReturnValue
158GNUNET_HELLO_builder_to_block (const struct GNUNET_HELLO_Builder *builder,
159 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
160 void *block,
161 size_t *block_size);
162
163
164/**
165 * Add individual @a address to the @a builder
166 *
167 * @param[in,out] builder to update
168 * @param address address URI to add
169 * @return #GNUNET_OK on success, #GNUNET_NO if @a address was already
170 * in @a builder
171 */
172enum GNUNET_GenericReturnValue
173GNUNET_HELLO_builder_add_address (struct GNUNET_HELLO_Builder *builder,
174 const char *address);
175
176
177/**
178 * Remove individual @a address from the @a builder
179 *
180 * @param[in,out] builder to update
181 * @param address address URI to remove
182 * @return #GNUNET_OK on success, #GNUNET_NO if @a address was not
183 * in @a builder
184 */
185enum GNUNET_GenericReturnValue
186GNUNET_HELLO_builder_del_address (struct GNUNET_HELLO_Builder *builder,
187 const char *address);
188
189
190/**
191 * Callback function used to extract URIs from a builder.
192 *
193 * @param cls closure
194 * @param uri one of the URIs
195 */
196typedef void
197(*GNUNET_HELLO_UriCallback) (void *cls,
198 const char *uri);
199
200
201/**
202 * Iterate over URIs in a builder.
203 *
204 * @param builder builder to iterate over
205 * @param[out] pid set to the peer the @a builder is for
206 * @param uc callback invoked for each URI, can be NULL
207 * @param uc_cls closure for @a addrgen
208 */
209void
210GNUNET_HELLO_builder_iterate (const struct GNUNET_HELLO_Builder *builder,
211 struct GNUNET_PeerIdentity *pid,
212 GNUNET_HELLO_UriCallback uc,
213 void *uc_cls);
214
215
216/**
217 * Convert a DHT @a hello message to a HELLO @a block.
218 *
219 * @param hello the HELLO message
220 * @param pid peer that created the @a hello
221 * @param[out] block set to the HELLO block
222 * @param[out] block_size set to number of bytes in @a block
223 * @param[out] block_expiration set to expiration time of @a block
224 * @return #GNUNET_OK on success,
225 * #GNUNET_NO if the @a hello is expired (@a block is set!)
226 * #GNUNET_SYSERR if @a hello is invalid (@a block will be set to NULL)
227 */
228enum GNUNET_GenericReturnValue
229GNUNET_HELLO_dht_msg_to_block (const struct GNUNET_MessageHeader *hello,
230 const struct GNUNET_PeerIdentity *pid,
231 void **block,
232 size_t *block_size,
233 struct GNUNET_TIME_Absolute *block_expiration);
234
235
236#if 0 /* keep Emacsens' auto-indent happy */
237{
238#endif
239#ifdef __cplusplus
240}
241#endif
242
243/* ifndef GNUNET_HELLO_URI_LIB_H */
244#endif
245
246/** @} */ /* end of group */
247
248/* end of gnunet_hello_uri_lib.h */
diff --git a/src/include/gnunet_json_lib.h b/src/include/gnunet_json_lib.h
index 7d101196c..6e73a3365 100644
--- a/src/include/gnunet_json_lib.h
+++ b/src/include/gnunet_json_lib.h
@@ -48,10 +48,10 @@ struct GNUNET_JSON_Specification;
48 * @return #GNUNET_SYSERR on error, 48 * @return #GNUNET_SYSERR on error,
49 * #GNUNET_OK on success 49 * #GNUNET_OK on success
50 */ 50 */
51typedef int 51typedef enum GNUNET_GenericReturnValue
52(*GNUNET_JSON_Parser) (void *cls, 52(*GNUNET_JSON_Parser)(void *cls,
53 json_t *root, 53 json_t *root,
54 struct GNUNET_JSON_Specification *spec); 54 struct GNUNET_JSON_Specification *spec);
55 55
56 56
57/** 57/**
diff --git a/src/include/gnunet_namestore_service.h b/src/include/gnunet_namestore_service.h
index 2482b97a5..619b81aed 100644
--- a/src/include/gnunet_namestore_service.h
+++ b/src/include/gnunet_namestore_service.h
@@ -134,6 +134,39 @@ GNUNET_NAMESTORE_records_store (struct GNUNET_NAMESTORE_Handle *h,
134 GNUNET_NAMESTORE_ContinuationWithStatus cont, 134 GNUNET_NAMESTORE_ContinuationWithStatus cont,
135 void *cont_cls); 135 void *cont_cls);
136 136
137/**
138 * Store an item in the namestore. If the item is already present,
139 * it is replaced with the new record. Use an empty array to
140 * remove all records under the given name.
141 *
142 * The continuation is called after the value has been stored in the
143 * database. Monitors may be notified asynchronously (basically with
144 * a buffer). However, if any monitor is consistently too slow to
145 * keep up with the changes, calling @a cont will be delayed until the
146 * monitors do keep up.
147 *
148 * @param h handle to the namestore
149 * @param pkey private key of the zone
150 * @param label name that is being mapped
151 * @param rd_count number of records in the 'rd' array
152 * @param rd array of records with data to store
153 * @param is_zonemaster update tombstones, do not process monitors
154 * @param cont continuation to call when done
155 * @param cont_cls closure for @a cont
156 * @return handle to abort the request
157 */
158struct GNUNET_NAMESTORE_QueueEntry *
159GNUNET_NAMESTORE_records_store_ (struct GNUNET_NAMESTORE_Handle *h,
160 const struct GNUNET_IDENTITY_PrivateKey *pkey,
161 const char *label,
162 unsigned int rd_count,
163 const struct GNUNET_GNSRECORD_Data *rd,
164 int is_zonemaster,
165 GNUNET_NAMESTORE_ContinuationWithStatus cont,
166 void *cont_cls);
167
168
169
137 170
138/** 171/**
139 * Process a record that was stored in the namestore. 172 * Process a record that was stored in the namestore.
@@ -179,6 +212,61 @@ GNUNET_NAMESTORE_records_lookup (struct GNUNET_NAMESTORE_Handle *h,
179 212
180 213
181/** 214/**
215 * Open a record set for editing.
216 * Retrieves an exclusive lock on this set.
217 * Must be commited using @a GNUNET_NAMESTORE_records_commit
218 *
219 * @param h handle to the namestore
220 * @param pkey private key of the zone
221 * @param label name that is being mapped
222 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
223 * the handle is afterwards invalid
224 * @param error_cb_cls closure for @a error_cb
225 * @param rm function to call with the result (with 0 records if we don't have that label)
226 * @param rm_cls closure for @a rm
227 * @return handle to abort the request
228 */
229struct GNUNET_NAMESTORE_QueueEntry *
230GNUNET_NAMESTORE_records_open (struct GNUNET_NAMESTORE_Handle *h,
231 const struct
232 GNUNET_IDENTITY_PrivateKey *pkey,
233 const char *label,
234 GNUNET_SCHEDULER_TaskCallback error_cb,
235 void *error_cb_cls,
236 GNUNET_NAMESTORE_RecordMonitor rm,
237 void *rm_cls);
238
239/**
240 * Commit the record set to the namestore.
241 * Releases the lock on the record set.
242 * Use an empty array to
243 * remove all records under the given name.
244 *
245 * The continuation is called after the value has been stored in the
246 * database. Monitors may be notified asynchronously (basically with
247 * a buffer). However, if any monitor is consistently too slow to
248 * keep up with the changes, calling @a cont will be delayed until the
249 * monitors do keep up.
250 *
251 * @param h handle to the namestore
252 * @param pkey private key of the zone
253 * @param label name that is being mapped
254 * @param rd_count number of records in the 'rd' array
255 * @param rd array of records with data to store
256 * @param cont continuation to call when done
257 * @param cont_cls closure for @a cont
258 * @return handle to abort the request
259 */
260struct GNUNET_NAMESTORE_QueueEntry *
261GNUNET_NAMESTORE_records_commit (struct GNUNET_NAMESTORE_Handle *h,
262 const struct GNUNET_IDENTITY_PrivateKey *pkey,
263 const char *label,
264 unsigned int rd_count,
265 const struct GNUNET_GNSRECORD_Data *rd,
266 GNUNET_NAMESTORE_ContinuationWithStatus cont,
267 void *cont_cls);
268
269/**
182 * Look for an existing PKEY delegation record for a given public key. 270 * Look for an existing PKEY delegation record for a given public key.
183 * Returns at most one result to the processor. 271 * Returns at most one result to the processor.
184 * 272 *
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 9e278eb92..f2892e125 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -153,10 +153,10 @@ extern "C" {
153 ******************************************************************************/ 153 ******************************************************************************/
154 154
155/** 155/**
156 * Previously used for HELLO messages used for communicating peer addresses. 156 * Latest HELLO messages used for communicating peer addresses.
157 * Managed by libgnunethello. 157 * Managed by libgnunethello.
158 */ 158 */
159#define GNUNET_MESSAGE_TYPE_HELLO_LEGACY 16 159#define GNUNET_MESSAGE_TYPE_HELLO_URI 16
160 160
161/** 161/**
162 * HELLO message with friend only flag used for communicating peer addresses. 162 * HELLO message with friend only flag used for communicating peer addresses.
@@ -660,13 +660,26 @@ extern "C" {
660#define GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN 156 660#define GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN 156
661 661
662/** 662/**
663 * DHT wants to use CORE to transmit data. 663 * HELLO advertising a neighbours addresses.
664 */ 664 */
665#define GNUNET_MESSAGE_TYPE_DHT_CORE 143 665#define GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO 157
666 666
667/** 667/**
668 * Further X-VINE DHT messages continued from 880 668 * Encapsulation of DHT messages in CORE service.
669 */ 669 */
670#define GNUNET_MESSAGE_TYPE_DHT_CORE 158
671
672/**
673 * HELLO URL send between client and service (in
674 * either direction).
675 */
676#define GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL 159
677
678/**
679 * Client requests DHT service's HELLO URL.
680 */
681#define GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_GET 161
682
670 683
671/******************************************************************************* 684/*******************************************************************************
672 * HOSTLIST message types 685 * HOSTLIST message types
@@ -1796,7 +1809,6 @@ extern "C" {
1796#define GNUNET_MESSAGE_TYPE_SETU_P2P_SEND_FULL 710 1809#define GNUNET_MESSAGE_TYPE_SETU_P2P_SEND_FULL 710
1797 1810
1798 1811
1799
1800/******************************************************************************* 1812/*******************************************************************************
1801 * SETI message types 1813 * SETI message types
1802 ******************************************************************************/ 1814 ******************************************************************************/
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h
index 9dd2f733e..bb8577b7a 100644
--- a/src/include/gnunet_strings_lib.h
+++ b/src/include/gnunet_strings_lib.h
@@ -159,14 +159,12 @@ GNUNET_STRINGS_to_utf8 (const char *input,
159 159
160/** 160/**
161 * Normalize the utf-8 input string to NFC. 161 * Normalize the utf-8 input string to NFC.
162 * Output needs to be allocated appropriately.
163 * 162 *
164 * @param input input string 163 * @param input input string
165 * @param output output buffer 164 * @return result (freshly allocated) or NULL on error.
166 */ 165 */
167void 166char*
168GNUNET_STRINGS_utf8_normalize (const char *input, 167GNUNET_STRINGS_utf8_normalize (const char *input);
169 char *output);
170 168
171 169
172/** 170/**
@@ -192,8 +190,9 @@ GNUNET_STRINGS_from_utf8 (const char *input,
192 * 190 *
193 * @param input input string 191 * @param input input string
194 * @param output output buffer 192 * @param output output buffer
193 * @return GNUNET_OK on success
195 */ 194 */
196void 195enum GNUNET_GenericReturnValue
197GNUNET_STRINGS_utf8_tolower (const char *input, 196GNUNET_STRINGS_utf8_tolower (const char *input,
198 char *output); 197 char *output);
199 198
@@ -204,8 +203,9 @@ GNUNET_STRINGS_utf8_tolower (const char *input,
204 * 203 *
205 * @param input input string 204 * @param input input string
206 * @param output output buffer 205 * @param output output buffer
206 * @return GNUNET_OK on success
207 */ 207 */
208void 208enum GNUNET_GenericReturnValue
209GNUNET_STRINGS_utf8_toupper (const char *input, 209GNUNET_STRINGS_utf8_toupper (const char *input,
210 char *output); 210 char *output);
211 211
@@ -458,7 +458,7 @@ GNUNET_STRINGS_base64url_decode (const char *data,
458 * 458 *
459 * @param data the data to encode 459 * @param data the data to encode
460 * @param len the length of the input 460 * @param len the length of the input
461 * @param output where to write the output (*output should be NULL, 461 * @param[out] out where to write the output (*output should be NULL,
462 * is allocated) 462 * is allocated)
463 * @return the size of the output 463 * @return the size of the output
464 */ 464 */
diff --git a/src/include/gnunet_time_lib.h b/src/include/gnunet_time_lib.h
index b14439462..96413c3cc 100644
--- a/src/include/gnunet_time_lib.h
+++ b/src/include/gnunet_time_lib.h
@@ -762,11 +762,22 @@ GNUNET_TIME_absolute_from_s (uint64_t s_after_epoch);
762 * 762 *
763 * @param s_after_epoch seconds after epoch to convert 763 * @param s_after_epoch seconds after epoch to convert
764 * @return converted time value 764 * @return converted time value
765 */struct GNUNET_TIME_Timestamp 765 */
766struct GNUNET_TIME_Timestamp
766GNUNET_TIME_timestamp_from_s (uint64_t s_after_epoch); 767GNUNET_TIME_timestamp_from_s (uint64_t s_after_epoch);
767 768
768 769
769/** 770/**
771 * Convert timestamp to number of seconds after the UNIX epoch.
772 *
773 * @param ts timestamp to convert
774 * @return converted time value
775 */
776uint64_t
777GNUNET_TIME_timestamp_to_s (struct GNUNET_TIME_Timestamp ts);
778
779
780/**
770 * Convert absolute time from network byte order. 781 * Convert absolute time from network byte order.
771 * 782 *
772 * @param a time to convert 783 * @param a time to convert
diff --git a/src/json/json_pack.c b/src/json/json_pack.c
index 296f56104..cc1ca3e97 100644
--- a/src/json/json_pack.c
+++ b/src/json/json_pack.c
@@ -31,6 +31,12 @@ GNUNET_JSON_pack_ (struct GNUNET_JSON_PackSpec spec[])
31{ 31{
32 json_t *ret; 32 json_t *ret;
33 33
34 if (NULL == spec[0].field_name)
35 {
36 ret = spec[0].object;
37 spec[0].object = NULL;
38 return ret;
39 }
34 ret = json_object (); 40 ret = json_object ();
35 GNUNET_assert (NULL != ret); 41 GNUNET_assert (NULL != ret);
36 for (unsigned int i = 0; 42 for (unsigned int i = 0;
diff --git a/src/messenger/gnunet-service-messenger.c b/src/messenger/gnunet-service-messenger.c
index 546f4c0d2..31bffec18 100644
--- a/src/messenger/gnunet-service-messenger.c
+++ b/src/messenger/gnunet-service-messenger.c
@@ -170,9 +170,7 @@ handle_room_close (void *cls,
170 170
171 if (GNUNET_YES == close_handle_room (msg_client->handle, &(msg->key))) 171 if (GNUNET_YES == close_handle_room (msg_client->handle, &(msg->key)))
172 { 172 {
173 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key)); 173 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room succeeded: %s\n", GNUNET_h2s (&(msg->key)));
174
175 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room with member id: %s\n", GNUNET_sh2s (member_id));
176 174
177 struct GNUNET_MESSENGER_RoomMessage *response; 175 struct GNUNET_MESSENGER_RoomMessage *response;
178 struct GNUNET_MQ_Envelope *env; 176 struct GNUNET_MQ_Envelope *env;
diff --git a/src/messenger/gnunet-service-messenger_member_session.c b/src/messenger/gnunet-service-messenger_member_session.c
index 846dbbe2b..6bd1d24b8 100644
--- a/src/messenger/gnunet-service-messenger_member_session.c
+++ b/src/messenger/gnunet-service-messenger_member_session.c
@@ -84,6 +84,9 @@ check_member_session_completion (struct GNUNET_MESSENGER_MemberSession *session)
84{ 84{
85 GNUNET_assert (session); 85 GNUNET_assert (session);
86 86
87 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Check session history (%s) for completion.\n",
88 GNUNET_sh2s(get_member_session_id(session)));
89
87 if (!session->messages.tail) 90 if (!session->messages.tail)
88 { 91 {
89 session->completed = GNUNET_YES; 92 session->completed = GNUNET_YES;
@@ -142,7 +145,10 @@ check_member_session_completion (struct GNUNET_MESSENGER_MemberSession *session)
142completion: 145completion:
143 if (GNUNET_YES == is_member_session_completed(session)) 146 if (GNUNET_YES == is_member_session_completed(session))
144 { 147 {
145 GNUNET_CONTAINER_multihashmap_destroy (session->history); 148 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Completed session history (%s)\n",
149 GNUNET_sh2s(get_member_session_id(session)));
150
151 GNUNET_CONTAINER_multihashmap_clear (session->history);
146 152
147 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store); 153 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
148 154
diff --git a/src/messenger/gnunet-service-messenger_room.c b/src/messenger/gnunet-service-messenger_room.c
index 7f2fd0ca6..7a20d2191 100644
--- a/src/messenger/gnunet-service-messenger_room.c
+++ b/src/messenger/gnunet-service-messenger_room.c
@@ -92,14 +92,14 @@ static void
92handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room); 92handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room);
93 93
94void 94void
95destroy_room (struct GNUNET_MESSENGER_SrvRoom *room) 95destroy_room (struct GNUNET_MESSENGER_SrvRoom *room,
96 int deletion)
96{ 97{
97 GNUNET_assert(room); 98 GNUNET_assert(room);
98 99
99 if (room->idle) 100 if (room->idle)
100 { 101 {
101 GNUNET_SCHEDULER_cancel (room->idle); 102 GNUNET_SCHEDULER_cancel (room->idle);
102
103 room->idle = NULL; 103 room->idle = NULL;
104 } 104 }
105 105
@@ -107,18 +107,22 @@ destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
107 GNUNET_CADET_close_port (room->port); 107 GNUNET_CADET_close_port (room->port);
108 108
109 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels, NULL); 109 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels, NULL);
110
111 handle_room_messages (room); 110 handle_room_messages (room);
112 111
113 if (room->service->dir) 112 if (!(room->service->dir))
113 goto skip_saving;
114
115 if (GNUNET_YES == deletion)
116 remove_room (room);
117 else
114 save_room (room); 118 save_room (room);
115 119
120skip_saving:
116 clear_member_store (get_room_member_store(room)); 121 clear_member_store (get_room_member_store(room));
117 clear_message_store (get_room_message_store(room)); 122 clear_message_store (get_room_message_store(room));
118 clear_operation_store(get_room_operation_store(room)); 123 clear_operation_store(get_room_operation_store(room));
119 124
120 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels); 125 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels);
121
122 clear_list_tunnels (&(room->basement)); 126 clear_list_tunnels (&(room->basement));
123 clear_message_state(&(room->state)); 127 clear_message_state(&(room->state));
124 128
@@ -1221,6 +1225,20 @@ save_room (struct GNUNET_MESSENGER_SrvRoom *room)
1221 GNUNET_free(room_dir); 1225 GNUNET_free(room_dir);
1222} 1226}
1223 1227
1228void
1229remove_room (struct GNUNET_MESSENGER_SrvRoom *room)
1230{
1231 GNUNET_assert(room);
1232
1233 char *room_dir;
1234 get_room_data_subdir (room, &room_dir);
1235
1236 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
1237 GNUNET_DISK_directory_remove(room_dir);
1238
1239 GNUNET_free(room_dir);
1240}
1241
1224static void 1242static void
1225remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room, 1243remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room,
1226 struct GNUNET_MESSENGER_MemberSession *session) 1244 struct GNUNET_MESSENGER_MemberSession *session)
diff --git a/src/messenger/gnunet-service-messenger_room.h b/src/messenger/gnunet-service-messenger_room.h
index 4b3811104..58edc4121 100644
--- a/src/messenger/gnunet-service-messenger_room.h
+++ b/src/messenger/gnunet-service-messenger_room.h
@@ -95,10 +95,15 @@ create_room (struct GNUNET_MESSENGER_SrvHandle *handle,
95/** 95/**
96 * Destroys a room and frees its memory fully. 96 * Destroys a room and frees its memory fully.
97 * 97 *
98 * The <i>deletion</i> flag should only be set to #GNUNET_YES if the
99 * room gets dropped by the service, otherwise #GNUNET_NO.
100 *
98 * @param[in/out] room Room 101 * @param[in/out] room Room
102 * @param[in] deletion Flag to indicate context of destruction
99 */ 103 */
100void 104void
101destroy_room (struct GNUNET_MESSENGER_SrvRoom *room); 105destroy_room (struct GNUNET_MESSENGER_SrvRoom *room,
106 int deletion);
102 107
103/** 108/**
104 * Returns the used member store of a given <i>room</i>. 109 * Returns the used member store of a given <i>room</i>.
@@ -364,4 +369,12 @@ load_room (struct GNUNET_MESSENGER_SrvRoom *room);
364void 369void
365save_room (struct GNUNET_MESSENGER_SrvRoom *room); 370save_room (struct GNUNET_MESSENGER_SrvRoom *room);
366 371
372/**
373 * Removes the configuration for a given <i>room</i> of a service.
374 *
375 * @param[in] room Room
376 */
377void
378remove_room (struct GNUNET_MESSENGER_SrvRoom *room);
379
367#endif //GNUNET_SERVICE_MESSENGER_ROOM_H 380#endif //GNUNET_SERVICE_MESSENGER_ROOM_H
diff --git a/src/messenger/gnunet-service-messenger_service.c b/src/messenger/gnunet-service-messenger_service.c
index b53b72af8..83d7632d8 100644
--- a/src/messenger/gnunet-service-messenger_service.c
+++ b/src/messenger/gnunet-service-messenger_service.c
@@ -94,7 +94,7 @@ iterate_destroy_rooms (void *cls,
94 void *value) 94 void *value)
95{ 95{
96 struct GNUNET_MESSENGER_SrvRoom *room = value; 96 struct GNUNET_MESSENGER_SrvRoom *room = value;
97 destroy_room (room); 97 destroy_room (room, GNUNET_NO);
98 return GNUNET_YES; 98 return GNUNET_YES;
99} 99}
100 100
@@ -220,7 +220,7 @@ open_service_room (struct GNUNET_MESSENGER_Service *service,
220 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) 220 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
221 return GNUNET_YES; 221 return GNUNET_YES;
222 222
223 destroy_room (room); 223 destroy_room (room, GNUNET_YES);
224 return GNUNET_NO; 224 return GNUNET_NO;
225} 225}
226 226
@@ -253,7 +253,7 @@ entry_service_room (struct GNUNET_MESSENGER_Service *service,
253 } 253 }
254 else 254 else
255 { 255 {
256 destroy_room (room); 256 destroy_room (room, GNUNET_YES);
257 return GNUNET_NO; 257 return GNUNET_NO;
258 } 258 }
259 259
@@ -287,7 +287,7 @@ close_service_room (struct GNUNET_MESSENGER_Service *service,
287 { 287 {
288 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (service->rooms, key, room)) 288 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (service->rooms, key, room))
289 { 289 {
290 destroy_room (room); 290 destroy_room (room, GNUNET_YES);
291 return GNUNET_YES; 291 return GNUNET_YES;
292 } 292 }
293 else 293 else
diff --git a/src/messenger/messenger.conf.in b/src/messenger/messenger.conf.in
index 6b54550ea..ef0544681 100644
--- a/src/messenger/messenger.conf.in
+++ b/src/messenger/messenger.conf.in
@@ -1,12 +1,12 @@
1[messenger] 1[messenger]
2START_ON_DEMAND = YES 2START_ON_DEMAND = @START_ON_DEMAND@
3RUN_PER_USER = YES 3RUN_PER_USER = YES
4PORT = 2097 4@JAVAPORT@PORT = 2125
5HOSTNAME = localhost 5HOSTNAME = localhost
6BINARY = gnunet-service-messenger 6BINARY = gnunet-service-messenger
7ACCEPT_FROM = 127.0.0.1; 7ACCEPT_FROM = 127.0.0.1;
8ACCEPT_FROM6 = ::1; 8ACCEPT_FROM6 = ::1;
9UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-messenger.sock 9UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-messenger.sock
10UNIX_MATCH_UID = NO 10UNIX_MATCH_UID = NO
11UNIX_MATCH_GID = YES 11UNIX_MATCH_GID = YES
12 12
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c
index 496c98dbf..3814def70 100644
--- a/src/messenger/messenger_api_message.c
+++ b/src/messenger/messenger_api_message.c
@@ -219,6 +219,10 @@ get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
219 case GNUNET_MESSENGER_KIND_PRIVATE: 219 case GNUNET_MESSENGER_KIND_PRIVATE:
220 length += member_size(struct GNUNET_MESSENGER_Message, body.privacy.key); 220 length += member_size(struct GNUNET_MESSENGER_Message, body.privacy.key);
221 break; 221 break;
222 case GNUNET_MESSENGER_KIND_DELETE:
223 length += member_size(struct GNUNET_MESSENGER_Message, body.deletion.hash);
224 length += member_size(struct GNUNET_MESSENGER_Message, body.deletion.delay);
225 break;
222 default: 226 default:
223 break; 227 break;
224 } 228 }
@@ -445,6 +449,10 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind kind,
445 encode_step(buffer, offset, &(body->privacy.key)); 449 encode_step(buffer, offset, &(body->privacy.key));
446 encode_step_ext(buffer, offset, body->privacy.data, min(length - offset, body->privacy.length)); 450 encode_step_ext(buffer, offset, body->privacy.data, min(length - offset, body->privacy.length));
447 break; 451 break;
452 case GNUNET_MESSENGER_KIND_DELETE:
453 encode_step(buffer, offset, &(body->deletion.hash));
454 encode_step(buffer, offset, &(body->deletion.delay));
455 break;
448 default: 456 default:
449 break; 457 break;
450 } 458 }
@@ -616,6 +624,10 @@ decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind,
616 body->privacy.length = (length - offset); 624 body->privacy.length = (length - offset);
617 decode_step_malloc(buffer, offset, body->privacy.data, length - offset, 0); 625 decode_step_malloc(buffer, offset, body->privacy.data, length - offset, 0);
618 break; 626 break;
627 case GNUNET_MESSENGER_KIND_DELETE:
628 decode_step(buffer, offset, &(body->deletion.hash));
629 decode_step(buffer, offset, &(body->deletion.delay));
630 break;
619 default: 631 default:
620 *kind = GNUNET_MESSENGER_KIND_UNKNOWN; 632 *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
621 break; 633 break;
diff --git a/src/namecache/test_namecache_api_cache_block.c b/src/namecache/test_namecache_api_cache_block.c
index 310c4de42..6188fb014 100644
--- a/src/namecache/test_namecache_api_cache_block.c
+++ b/src/namecache/test_namecache_api_cache_block.c
@@ -187,9 +187,10 @@ run (void *cls,
187 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); 187 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN);
188 rd.flags = 0; 188 rd.flags = 0;
189 memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); 189 memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN);
190 block = GNUNET_GNSRECORD_block_create (&privkey, 190 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (&privkey,
191 GNUNET_TIME_UNIT_FOREVER_ABS, 191 GNUNET_TIME_UNIT_FOREVER_ABS,
192 name, &rd, 1); 192 name, &rd, 1,
193 &block));
193 if (NULL == block) 194 if (NULL == block)
194 { 195 {
195 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 196 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index 51708dd67..2441b864a 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -39,6 +39,7 @@ if HAVE_SQLITE
39SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la 39SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la
40SQLITE_TESTS = test_plugin_namestore_sqlite \ 40SQLITE_TESTS = test_plugin_namestore_sqlite \
41 test_namestore_api_store_sqlite \ 41 test_namestore_api_store_sqlite \
42 test_namestore_api_store_locking_sqlite \
42 test_namestore_api_store_update_sqlite \ 43 test_namestore_api_store_update_sqlite \
43 test_namestore_api_zone_iteration_sqlite \ 44 test_namestore_api_zone_iteration_sqlite \
44 test_namestore_api_remove_sqlite \ 45 test_namestore_api_remove_sqlite \
@@ -249,6 +250,16 @@ test_namestore_api_store_sqlite_LDADD = \
249 $(top_builddir)/src/identity/libgnunetidentity.la \ 250 $(top_builddir)/src/identity/libgnunetidentity.la \
250 libgnunetnamestore.la 251 libgnunetnamestore.la
251 252
253test_namestore_api_store_locking_sqlite_SOURCES = \
254 test_namestore_api_store_locking.c
255test_namestore_api_store_locking_sqlite_LDADD = \
256 $(top_builddir)/src/testing/libgnunettesting.la \
257 $(top_builddir)/src/util/libgnunetutil.la \
258 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
259 $(top_builddir)/src/identity/libgnunetidentity.la \
260 libgnunetnamestore.la
261
262
252test_namestore_api_store_postgres_SOURCES = \ 263test_namestore_api_store_postgres_SOURCES = \
253 test_namestore_api_store.c 264 test_namestore_api_store.c
254test_namestore_api_store_postgres_LDADD = \ 265test_namestore_api_store_postgres_LDADD = \
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c
index 852d99608..af40f2dbe 100644
--- a/src/namestore/gnunet-namestore.c
+++ b/src/namestore/gnunet-namestore.c
@@ -33,6 +33,12 @@
33#include <gnunet_gns_service.h> 33#include <gnunet_gns_service.h>
34#include <gnunet_namestore_service.h> 34#include <gnunet_namestore_service.h>
35 35
36/**
37 * The upper bound for the zone iteration interval
38 * (per record).
39 */
40#define WARN_RELATIVE_EXPIRATION_LIMIT GNUNET_TIME_relative_multiply ( \
41 GNUNET_TIME_UNIT_MINUTES, 15)
36 42
37/** 43/**
38 * Entry in record set for bulk processing. 44 * Entry in record set for bulk processing.
@@ -430,6 +436,8 @@ display_record (const char *rname,
430 if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) && 436 if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
431 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT))) 437 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)))
432 continue; 438 continue;
439 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
440 continue;
433 if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type)) 441 if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type))
434 continue; 442 continue;
435 have_record = GNUNET_YES; 443 have_record = GNUNET_YES;
@@ -447,6 +455,8 @@ display_record (const char *rname,
447 if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) && 455 if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
448 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT))) 456 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)))
449 continue; 457 continue;
458 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
459 continue;
450 if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type)) 460 if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type))
451 continue; 461 continue;
452 typestr = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type); 462 typestr = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
@@ -649,28 +659,6 @@ get_existing_record (void *cls,
649 { 659 {
650 switch (rd[i].record_type) 660 switch (rd[i].record_type)
651 { 661 {
652 case GNUNET_DNSPARSER_TYPE_CNAME:
653 fprintf (
654 stderr,
655 _ (
656 "A %s record exists already under `%s', no other records can be added.\n"),
657 "CNAME",
658 rec_name);
659 ret = 1;
660 test_finished ();
661 return;
662
663 case GNUNET_GNSRECORD_TYPE_PKEY:
664 case GNUNET_GNSRECORD_TYPE_EDKEY:
665 fprintf (
666 stderr,
667 _ (
668 "A zone key record exists already under `%s', no other records can be added.\n"),
669 rec_name);
670 ret = 1;
671 test_finished ();
672 return;
673
674 case GNUNET_DNSPARSER_TYPE_SOA: 662 case GNUNET_DNSPARSER_TYPE_SOA:
675 if (GNUNET_DNSPARSER_TYPE_SOA == type) 663 if (GNUNET_DNSPARSER_TYPE_SOA == type)
676 { 664 {
@@ -686,51 +674,6 @@ get_existing_record (void *cls,
686 break; 674 break;
687 } 675 }
688 } 676 }
689 switch (type)
690 {
691 case GNUNET_DNSPARSER_TYPE_CNAME:
692 if (0 != rd_count)
693 {
694 fprintf (stderr,
695 _ (
696 "Records already exist under `%s', cannot add `%s' record.\n"),
697 rec_name,
698 "CNAME");
699 ret = 1;
700 test_finished ();
701 return;
702 }
703 break;
704
705 case GNUNET_GNSRECORD_TYPE_PKEY:
706 case GNUNET_GNSRECORD_TYPE_EDKEY:
707 if (0 != rd_count)
708 {
709 fprintf (stderr,
710 _ (
711 "Records already exist under `%s', cannot add record.\n"),
712 rec_name);
713 ret = 1;
714 test_finished ();
715 return;
716 }
717 break;
718
719 case GNUNET_GNSRECORD_TYPE_GNS2DNS:
720 for (unsigned int i = 0; i < rd_count; i++)
721 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
722 {
723 fprintf (
724 stderr,
725 _ (
726 "Non-GNS2DNS records already exist under `%s', cannot add GNS2DNS record.\n"),
727 rec_name);
728 ret = 1;
729 test_finished ();
730 return;
731 }
732 break;
733 }
734 memset (rdn, 0, sizeof(struct GNUNET_GNSRECORD_Data)); 677 memset (rdn, 0, sizeof(struct GNUNET_GNSRECORD_Data));
735 GNUNET_memcpy (&rdn[1], rd, rd_count * sizeof(struct GNUNET_GNSRECORD_Data)); 678 GNUNET_memcpy (&rdn[1], rd, rd_count * sizeof(struct GNUNET_GNSRECORD_Data));
736 rde = &rdn[0]; 679 rde = &rdn[0];
@@ -929,6 +872,13 @@ parse_expiration (const char *expirationstring,
929 { 872 {
930 *etime_is_rel = GNUNET_YES; 873 *etime_is_rel = GNUNET_YES;
931 *etime = etime_rel.rel_value_us; 874 *etime = etime_rel.rel_value_us;
875 if (GNUNET_TIME_relative_cmp (etime_rel, <, WARN_RELATIVE_EXPIRATION_LIMIT))
876 {
877 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
878 "Relative expiration times of less than %s are not recommended. To improve availability, consider increasing this value.\n",
879 GNUNET_STRINGS_relative_time_to_string (
880 WARN_RELATIVE_EXPIRATION_LIMIT, GNUNET_NO));
881 }
932 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
933 "Storing record with relative expiration time of %s\n", 883 "Storing record with relative expiration time of %s\n",
934 GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO)); 884 GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO));
@@ -1212,8 +1162,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1212 char sname[64]; 1162 char sname[64];
1213 struct GNUNET_IDENTITY_PublicKey pkey; 1163 struct GNUNET_IDENTITY_PublicKey pkey;
1214 1164
1215 memset(sh, 0, 105); 1165 memset (sh, 0, 105);
1216 memset(sname, 0, 64); 1166 memset (sname, 0, 64);
1217 1167
1218 if ((2 != (sscanf (uri, "gnunet://gns/%58s/%63s", sh, sname))) || 1168 if ((2 != (sscanf (uri, "gnunet://gns/%58s/%63s", sh, sname))) ||
1219 (GNUNET_OK != 1169 (GNUNET_OK !=
@@ -1286,15 +1236,6 @@ identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
1286 const struct GNUNET_CONFIGURATION_Handle *cfg = cls; 1236 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1287 1237
1288 el = NULL; 1238 el = NULL;
1289 if ((NULL != name) && (0 != strchr (name, '.')))
1290 {
1291 fprintf (stderr,
1292 _ ("Label `%s' contains `.' which is not allowed\n"),
1293 name);
1294 GNUNET_SCHEDULER_shutdown ();
1295 ret = -1;
1296 return;
1297 }
1298 1239
1299 if (NULL == ego) 1240 if (NULL == ego)
1300 { 1241 {
@@ -1705,13 +1646,13 @@ main (int argc, char *const *argv)
1705 NULL))) 1646 NULL)))
1706 { 1647 {
1707 GNUNET_free_nz ((void *) argv); 1648 GNUNET_free_nz ((void *) argv);
1708 //FIXME 1649 // FIXME
1709 //GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey); 1650 // GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey);
1710 return lret; 1651 return lret;
1711 } 1652 }
1712 GNUNET_free_nz ((void *) argv); 1653 GNUNET_free_nz ((void *) argv);
1713 //FIXME 1654 // FIXME
1714 //GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey); 1655 // GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey);
1715 return ret; 1656 return ret;
1716} 1657}
1717 1658
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index 9b2d9b6f3..d735822fb 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -121,6 +121,23 @@ struct ZoneIteration
121 int send_end; 121 int send_end;
122}; 122};
123 123
124/**
125 * Lock on a record set
126 */
127struct RecordsLock
128{
129 /* DLL */
130 struct RecordsLock *prev;
131
132 /* DLL */
133 struct RecordsLock *next;
134
135 /* Hash of the locked label */
136 struct GNUNET_HashCode label_hash;
137
138 /* Client locking the zone */
139 struct NamestoreClient *client;
140};
124 141
125/** 142/**
126 * A namestore client 143 * A namestore client
@@ -394,6 +411,16 @@ static struct StoreActivity *sa_head;
394static struct StoreActivity *sa_tail; 411static struct StoreActivity *sa_tail;
395 412
396/** 413/**
414 * Head of the DLL of record set locks
415 */
416static struct RecordsLock *locks_head;
417
418/**
419 * Tail of the DLL of record set locks
420 */
421static struct RecordsLock *locks_tail;
422
423/**
397 * Notification context shared by all monitors. 424 * Notification context shared by all monitors.
398 */ 425 */
399static struct GNUNET_NotificationContext *monitor_nc; 426static struct GNUNET_NotificationContext *monitor_nc;
@@ -420,6 +447,7 @@ static void
420cleanup_task (void *cls) 447cleanup_task (void *cls)
421{ 448{
422 struct CacheOperation *cop; 449 struct CacheOperation *cop;
450 struct RecordsLock *lock;
423 451
424 (void) cls; 452 (void) cls;
425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); 453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
@@ -431,6 +459,14 @@ cleanup_task (void *cls)
431 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); 459 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
432 GNUNET_free (cop); 460 GNUNET_free (cop);
433 } 461 }
462 while (NULL != (lock = locks_head))
463 {
464 GNUNET_CONTAINER_DLL_remove (locks_head,
465 locks_tail,
466 lock);
467 GNUNET_free (lock);
468 }
469
434 if (NULL != namecache) 470 if (NULL != namecache)
435 { 471 {
436 GNUNET_NAMECACHE_disconnect (namecache); 472 GNUNET_NAMECACHE_disconnect (namecache);
@@ -808,7 +844,8 @@ send_lookup_response (struct NamestoreClient *nc,
808 * @param rid client's request ID 844 * @param rid client's request ID
809 */ 845 */
810static void 846static void
811send_store_response (struct NamestoreClient *nc, int res, uint32_t rid) 847send_store_response (struct NamestoreClient *nc, int res, const char*emsg,
848 uint32_t rid)
812{ 849{
813 struct GNUNET_MQ_Envelope *env; 850 struct GNUNET_MQ_Envelope *env;
814 struct RecordStoreResponseMessage *rcr_msg; 851 struct RecordStoreResponseMessage *rcr_msg;
@@ -820,10 +857,17 @@ send_store_response (struct NamestoreClient *nc, int res, uint32_t rid)
820 "Store requests completed", 857 "Store requests completed",
821 1, 858 1,
822 GNUNET_NO); 859 GNUNET_NO);
823 env = GNUNET_MQ_msg (rcr_msg, 860 env = GNUNET_MQ_msg_extra (rcr_msg,
824 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE); 861 (NULL != emsg) ? strlen (emsg) + 1 : 0,
862 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
825 rcr_msg->gns_header.r_id = htonl (rid); 863 rcr_msg->gns_header.r_id = htonl (rid);
826 rcr_msg->op_result = htonl (res); 864 rcr_msg->op_result = htonl (res);
865 rcr_msg->reserved = htons (0);
866 if (NULL != emsg)
867 {
868 rcr_msg->emsg_len = htons (strlen (emsg) + 1);
869 memcpy (&rcr_msg[1], emsg, strlen (emsg) + 1);
870 }
827 GNUNET_MQ_send (nc->mq, env); 871 GNUNET_MQ_send (nc->mq, env);
828} 872}
829 873
@@ -874,7 +918,7 @@ finish_cache_operation (void *cls, int32_t success, const char *emsg)
874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n"); 918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n");
875 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); 919 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
876 if (NULL != cop->nc) 920 if (NULL != cop->nc)
877 send_store_response (cop->nc, success, cop->rid); 921 send_store_response (cop->nc, success, emsg, cop->rid);
878 if (NULL != (zi = cop->zi)) 922 if (NULL != (zi = cop->zi))
879 { 923 {
880 zi->cache_ops--; 924 zi->cache_ops--;
@@ -910,29 +954,40 @@ refresh_block (struct NamestoreClient *nc,
910 const struct GNUNET_GNSRECORD_Data *rd) 954 const struct GNUNET_GNSRECORD_Data *rd)
911{ 955{
912 struct GNUNET_GNSRECORD_Block *block; 956 struct GNUNET_GNSRECORD_Block *block;
957 struct GNUNET_GNSRECORD_Data rd_clean[rd_count];
913 struct CacheOperation *cop; 958 struct CacheOperation *cop;
914 struct GNUNET_IDENTITY_PublicKey pkey; 959 struct GNUNET_IDENTITY_PublicKey pkey;
915 struct GNUNET_GNSRECORD_Data *nick; 960 struct GNUNET_GNSRECORD_Data *nick;
916 struct GNUNET_GNSRECORD_Data *res; 961 struct GNUNET_GNSRECORD_Data *res;
917 unsigned int res_count; 962 unsigned int res_count;
963 unsigned int rd_count_clean;
918 struct GNUNET_TIME_Absolute exp_time; 964 struct GNUNET_TIME_Absolute exp_time;
919 965
966 /** Do not block-cache tombstones */
967 rd_count_clean = 0;
968 for (int i = 0; i < rd_count; i++)
969 {
970 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
971 continue;
972 rd_clean[rd_count_clean++] = rd[i];
973 }
974
920 nick = get_nick_record (zone_key); 975 nick = get_nick_record (zone_key);
921 res_count = rd_count; 976 res_count = rd_count_clean;
922 res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */ 977 res = (struct GNUNET_GNSRECORD_Data *) rd_clean; /* fixme: a bit unclean... */
923 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT))) 978 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
924 { 979 {
925 nick->flags = 980 nick->flags =
926 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; 981 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
927 merge_with_nick_records (nick, rd_count, rd, &res_count, &res); 982 merge_with_nick_records (nick, rd_count_clean, rd_clean, &res_count, &res);
928 } 983 }
929 if (NULL != nick) 984 if (NULL != nick)
930 GNUNET_free (nick); 985 GNUNET_free (nick);
931 if (0 == res_count) 986 if (0 == res_count)
932 { 987 {
933 if (NULL != nc) 988 if (NULL != nc)
934 send_store_response (nc, GNUNET_OK, rid); 989 send_store_response (nc, GNUNET_OK, NULL, rid);
935 if (rd != res) 990 if (rd_clean != res)
936 GNUNET_free (res); 991 GNUNET_free (res);
937 return; /* no data, no need to update cache */ 992 return; /* no data, no need to update cache */
938 } 993 }
@@ -943,20 +998,21 @@ refresh_block (struct NamestoreClient *nc,
943 1, 998 1,
944 GNUNET_NO); 999 GNUNET_NO);
945 if (NULL != nc) 1000 if (NULL != nc)
946 send_store_response (nc, GNUNET_OK, rid); 1001 send_store_response (nc, GNUNET_OK, NULL, rid);
947 if (rd != res) 1002 if (rd_clean != res)
948 GNUNET_free (res); 1003 GNUNET_free (res);
949 return; 1004 return;
950 } 1005 }
951 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res); 1006 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res,
1007 GNUNET_TIME_UNIT_ZERO_ABS);
952 if (cache_keys) 1008 if (cache_keys)
953 GNUNET_assert (GNUNET_OK == 1009 GNUNET_assert (GNUNET_OK ==
954 GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name, 1010 GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name,
955 res, res_count, &block)); 1011 res, res_count, &block));
956 else 1012 else
957 GNUNET_assert (GNUNET_OK == 1013 GNUNET_assert (GNUNET_OK ==
958 GNUNET_GNSRECORD_block_create (zone_key, exp_time, name, 1014 GNUNET_GNSRECORD_block_create (zone_key, exp_time, name,
959 res, res_count, &block)); 1015 res, res_count, &block));
960 GNUNET_assert (NULL != block); 1016 GNUNET_assert (NULL != block);
961 GNUNET_IDENTITY_key_get_public (zone_key, &pkey); 1017 GNUNET_IDENTITY_key_get_public (zone_key, &pkey);
962 GNUNET_log ( 1018 GNUNET_log (
@@ -974,7 +1030,7 @@ refresh_block (struct NamestoreClient *nc,
974 cop->nc = nc; 1030 cop->nc = nc;
975 cop->zi = zi; 1031 cop->zi = zi;
976 if (NULL != zi) 1032 if (NULL != zi)
977 zi->cache_ops++; 1033 zi->cache_ops ++;
978 cop->rid = rid; 1034 cop->rid = rid;
979 GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop); 1035 GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop);
980 cop->qe = GNUNET_NAMECACHE_block_cache (namecache, 1036 cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
@@ -982,7 +1038,7 @@ refresh_block (struct NamestoreClient *nc,
982 &finish_cache_operation, 1038 &finish_cache_operation,
983 cop); 1039 cop);
984 GNUNET_free (block); 1040 GNUNET_free (block);
985 if (rd != res) 1041 if (rd_clean != res)
986 GNUNET_free (res); 1042 GNUNET_free (res);
987} 1043}
988 1044
@@ -1098,6 +1154,7 @@ client_disconnect_cb (void *cls,
1098 struct NamestoreClient *nc = app_ctx; 1154 struct NamestoreClient *nc = app_ctx;
1099 struct ZoneIteration *no; 1155 struct ZoneIteration *no;
1100 struct CacheOperation *cop; 1156 struct CacheOperation *cop;
1157 struct RecordsLock *lock;
1101 1158
1102 (void) cls; 1159 (void) cls;
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); 1160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
@@ -1148,6 +1205,15 @@ client_disconnect_cb (void *cls,
1148 for (cop = cop_head; NULL != cop; cop = cop->next) 1205 for (cop = cop_head; NULL != cop; cop = cop->next)
1149 if (nc == cop->nc) 1206 if (nc == cop->nc)
1150 cop->nc = NULL; 1207 cop->nc = NULL;
1208 for (lock = locks_head; NULL != lock; lock = lock->next)
1209 {
1210 if (nc != lock->client)
1211 continue;
1212 GNUNET_CONTAINER_DLL_remove (locks_head,
1213 locks_tail,
1214 lock);
1215 GNUNET_free (lock);
1216 }
1151 GNUNET_free (nc); 1217 GNUNET_free (nc);
1152} 1218}
1153 1219
@@ -1341,6 +1407,105 @@ check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1341 return GNUNET_OK; 1407 return GNUNET_OK;
1342} 1408}
1343 1409
1410static void
1411calculate_lock_hash (const char *label,
1412 const struct GNUNET_IDENTITY_PrivateKey *zone,
1413 struct GNUNET_HashCode *result)
1414{
1415 struct GNUNET_HashContext *hctx;
1416
1417 hctx = GNUNET_CRYPTO_hash_context_start ();
1418 GNUNET_CRYPTO_hash_context_read (hctx, label, strlen (label));
1419 GNUNET_CRYPTO_hash_context_read (hctx, zone,
1420 sizeof (*zone));
1421 GNUNET_CRYPTO_hash_context_finish (hctx, result);
1422}
1423
1424/**
1425 * Release a lock on a record set.
1426 * Does nothing if lock not held.
1427 *
1428 * @param label the label of the record set
1429 * @param zone the zone
1430 * @param nc the client releasing the lock
1431 */
1432static void
1433NST_label_lock_release (const char *label,
1434 const struct GNUNET_IDENTITY_PrivateKey *zone,
1435 const struct NamestoreClient *nc)
1436{
1437 struct GNUNET_HashCode label_hash;
1438 struct RecordsLock *lock;
1439
1440 calculate_lock_hash (label, zone, &label_hash);
1441 for (lock = locks_head; NULL != lock; lock = lock->next)
1442 if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash)))
1443 break;
1444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1445 "Record locked: %s\n", (NULL == lock) ? "No" : "Yes");
1446 if (NULL == lock)
1447 return;
1448 if (lock->client != nc)
1449 {
1450 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1451 "Lock is held by other client on `%s'\n", label);
1452 return;
1453 }
1454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1455 "Unocking %s\n", GNUNET_h2s (&label_hash));
1456 GNUNET_CONTAINER_DLL_remove (locks_head,
1457 locks_tail,
1458 lock);
1459 GNUNET_free (lock);
1460}
1461
1462/**
1463 * Get/set a lock on a record set.
1464 * May be called multiple times but will
1465 * not aquire additional locks.
1466 *
1467 * @param the label of the record set
1468 * @param the zone
1469 * @param the client doing the locking
1470 * @return GNUNET_YES if lock retrieved or set already.
1471 */
1472static enum GNUNET_GenericReturnValue
1473NST_label_lock (const char *label,
1474 const struct GNUNET_IDENTITY_PrivateKey *zone,
1475 struct NamestoreClient *nc)
1476{
1477 struct GNUNET_HashCode label_hash;
1478 struct RecordsLock *lock;
1479
1480 calculate_lock_hash (label, zone, &label_hash);
1481 for (lock = locks_head; NULL != lock; lock = lock->next)
1482 if (0 == memcmp (&label_hash, &lock->label_hash, sizeof (label_hash)))
1483 break;
1484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1485 "Record locked: %s\n", (NULL == lock) ? "No" : "Yes");
1486 if (NULL != lock)
1487 {
1488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1489 "Client holds lock: %s\n", (lock->client != nc) ? "No" : "Yes");
1490 if (lock->client != nc)
1491 {
1492 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1493 "Lock is held by other client on `%s'\n", label);
1494 return GNUNET_NO;
1495 }
1496 return GNUNET_YES;
1497 }
1498 lock = GNUNET_new (struct RecordsLock);
1499 lock->client = nc;
1500 memcpy (&lock->label_hash, &label_hash, sizeof (label_hash));
1501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1502 "Locking %s\n", GNUNET_h2s (&label_hash));
1503 GNUNET_CONTAINER_DLL_insert (locks_head,
1504 locks_tail,
1505 lock);
1506 return GNUNET_YES;
1507}
1508
1344 1509
1345/** 1510/**
1346 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message 1511 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
@@ -1355,13 +1520,14 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1355 struct GNUNET_MQ_Envelope *env; 1520 struct GNUNET_MQ_Envelope *env;
1356 struct LabelLookupResponseMessage *llr_msg; 1521 struct LabelLookupResponseMessage *llr_msg;
1357 struct RecordLookupContext rlc; 1522 struct RecordLookupContext rlc;
1523 struct RecordsLock *lock;
1524 struct GNUNET_HashCode label_hash;
1358 const char *name_tmp; 1525 const char *name_tmp;
1359 char *res_name; 1526 char *res_name;
1360 char *conv_name; 1527 char *conv_name;
1361 uint32_t name_len; 1528 uint32_t name_len;
1362 int res; 1529 int res;
1363 1530
1364 name_len = ntohl (ll_msg->label_len);
1365 name_tmp = (const char *) &ll_msg[1]; 1531 name_tmp = (const char *) &ll_msg[1];
1366 GNUNET_SERVICE_client_continue (nc->client); 1532 GNUNET_SERVICE_client_continue (nc->client);
1367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1377,6 +1543,29 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1377 GNUNET_SERVICE_client_drop (nc->client); 1543 GNUNET_SERVICE_client_drop (nc->client);
1378 return; 1544 return;
1379 } 1545 }
1546 name_len = strlen (conv_name) + 1;
1547 if (GNUNET_YES == ntohl (ll_msg->locking))
1548 {
1549 if (GNUNET_NO == NST_label_lock (conv_name, &ll_msg->zone, nc))
1550 {
1551 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1552 "Lock is held by other client on `%s'\n", conv_name);
1553 env =
1554 GNUNET_MQ_msg_extra (llr_msg,
1555 name_len,
1556 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1557 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1558 llr_msg->private_key = ll_msg->zone;
1559 llr_msg->name_len = htons (name_len);
1560 llr_msg->rd_count = htons (0);
1561 llr_msg->rd_len = htons (0);
1562 llr_msg->found = htons (GNUNET_SYSERR);
1563 GNUNET_memcpy (&llr_msg[1], conv_name, name_len);
1564 GNUNET_MQ_send (nc->mq, env);
1565 GNUNET_free (conv_name);
1566 return;
1567 }
1568 }
1380 rlc.label = conv_name; 1569 rlc.label = conv_name;
1381 rlc.found = GNUNET_NO; 1570 rlc.found = GNUNET_NO;
1382 rlc.res_rd_count = 0; 1571 rlc.res_rd_count = 0;
@@ -1388,7 +1577,6 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1388 conv_name, 1577 conv_name,
1389 &lookup_it, 1578 &lookup_it,
1390 &rlc); 1579 &rlc);
1391 GNUNET_free (conv_name);
1392 env = 1580 env =
1393 GNUNET_MQ_msg_extra (llr_msg, 1581 GNUNET_MQ_msg_extra (llr_msg,
1394 name_len + rlc.rd_ser_len, 1582 name_len + rlc.rd_ser_len,
@@ -1400,16 +1588,18 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1400 llr_msg->rd_len = htons (rlc.rd_ser_len); 1588 llr_msg->rd_len = htons (rlc.rd_ser_len);
1401 res_name = (char *) &llr_msg[1]; 1589 res_name = (char *) &llr_msg[1];
1402 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res)) 1590 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1403 llr_msg->found = ntohs (GNUNET_YES); 1591 llr_msg->found = htons (GNUNET_YES);
1404 else 1592 else
1405 llr_msg->found = ntohs (GNUNET_NO); 1593 llr_msg->found = htons (GNUNET_NO);
1406 GNUNET_memcpy (&llr_msg[1], name_tmp, name_len); 1594 GNUNET_memcpy (&llr_msg[1], conv_name, name_len);
1407 GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len); 1595 GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len);
1408 GNUNET_MQ_send (nc->mq, env); 1596 GNUNET_MQ_send (nc->mq, env);
1409 GNUNET_free (rlc.res_rd); 1597 GNUNET_free (rlc.res_rd);
1598 GNUNET_free (conv_name);
1410} 1599}
1411 1600
1412 1601
1602
1413/** 1603/**
1414 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message 1604 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1415 * 1605 *
@@ -1452,6 +1642,45 @@ check_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1452 1642
1453 1643
1454/** 1644/**
1645 * Check if set contains a tombstone, store if necessary
1646 *
1647 * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
1648 * @param seq sequence number of the record, MUST NOT BE ZERO
1649 * @param private_key the private key of the zone (unused)
1650 * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
1651 * @param rd_count number of records in @a rd
1652 * @param rd records stored under @a label in the zone
1653 */
1654static void
1655get_block_exp_existing (void *cls,
1656 uint64_t seq,
1657 const struct
1658 GNUNET_IDENTITY_PrivateKey *private_key,
1659 const char *label,
1660 unsigned int rd_count,
1661 const struct GNUNET_GNSRECORD_Data *rd)
1662{
1663 struct GNUNET_TIME_Absolute *exp = cls;
1664 struct GNUNET_GNSRECORD_Data rd_pub[rd_count];
1665 unsigned int rd_pub_count;
1666 char *emsg;
1667
1668 if (GNUNET_OK != GNUNET_GNSRECORD_convert_records_for_export (label,
1669 rd,
1670 rd_count,
1671 rd_pub,
1672 &rd_pub_count,
1673 exp,
1674 &emsg))
1675 {
1676 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1677 "%s\n", emsg);
1678 GNUNET_free (emsg);
1679 }
1680}
1681
1682
1683/**
1455 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message 1684 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1456 * 1685 *
1457 * @param cls client sending the message 1686 * @param cls client sending the message
@@ -1470,37 +1699,75 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1470 unsigned int rd_count; 1699 unsigned int rd_count;
1471 int res; 1700 int res;
1472 struct StoreActivity *sa; 1701 struct StoreActivity *sa;
1702 struct RecordsLock *lock;
1703 struct GNUNET_HashCode label_hash;
1704 struct GNUNET_TIME_Absolute existing_block_exp;
1705 struct GNUNET_TIME_Absolute new_block_exp;
1473 1706
1474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1707 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1475 "Received NAMESTORE_RECORD_STORE message\n"); 1708 "Received NAMESTORE_RECORD_STORE message\n");
1709 existing_block_exp = GNUNET_TIME_UNIT_ZERO_ABS;
1710 new_block_exp = GNUNET_TIME_UNIT_ZERO_ABS;
1476 rid = ntohl (rp_msg->gns_header.r_id); 1711 rid = ntohl (rp_msg->gns_header.r_id);
1477 name_len = ntohs (rp_msg->name_len); 1712 name_len = ntohs (rp_msg->name_len);
1478 rd_count = ntohs (rp_msg->rd_count); 1713 rd_count = ntohs (rp_msg->rd_count);
1479 rd_ser_len = ntohs (rp_msg->rd_len); 1714 rd_ser_len = ntohs (rp_msg->rd_len);
1480 GNUNET_break (0 == ntohs (rp_msg->reserved));
1481 name_tmp = (const char *) &rp_msg[1]; 1715 name_tmp = (const char *) &rp_msg[1];
1482 rd_ser = &name_tmp[name_len]; 1716 rd_ser = &name_tmp[name_len];
1483 { 1717 {
1484 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; 1718 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1485 1719 char *emsg;
1486 if (GNUNET_OK !=
1487 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
1488 {
1489 GNUNET_break (0);
1490 GNUNET_SERVICE_client_drop (nc->client);
1491 return;
1492 }
1493 1720
1494 /* Extracting and converting private key */ 1721 /* Extracting and converting private key */
1495 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp); 1722 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp);
1496 if (NULL == conv_name) 1723 if (NULL == conv_name)
1497 { 1724 {
1498 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1725 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1499 "Error converting name `%s'\n", 1726 "Error normalizing name `%s'\n",
1500 name_tmp); 1727 name_tmp);
1501 GNUNET_SERVICE_client_drop (nc->client); 1728 send_store_response (nc, GNUNET_SYSERR, _ ("Error normalizing name."),
1729 rid);
1730 GNUNET_SERVICE_client_continue (nc->client);
1731 return;
1732 }
1733
1734 /* Check name for validity */
1735 if (GNUNET_OK != GNUNET_GNSRECORD_label_check (conv_name, &emsg))
1736 {
1737 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1738 "Label invalid: `%s'\n",
1739 emsg);
1740 send_store_response (nc, GNUNET_SYSERR, emsg, rid);
1741 GNUNET_free (emsg);
1742 GNUNET_free (conv_name);
1743 GNUNET_SERVICE_client_continue (nc->client);
1744 return;
1745 }
1746
1747 if (GNUNET_OK !=
1748 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
1749 {
1750 send_store_response (nc, GNUNET_SYSERR,
1751 _ ("Error deserializing records."), rid);
1752 GNUNET_free (conv_name);
1753 GNUNET_SERVICE_client_continue (nc->client);
1502 return; 1754 return;
1503 } 1755 }
1756 if (GNUNET_YES == ntohl (rp_msg->locking))
1757 {
1758 if (GNUNET_NO == NST_label_lock (conv_name, &rp_msg->private_key, nc))
1759 {
1760 send_store_response (nc, GNUNET_SYSERR, _ ("Record set locked."), rid);
1761 GNUNET_SERVICE_client_continue (nc->client);
1762 GNUNET_free (conv_name);
1763 return;
1764 }
1765 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1766 "Client has lock on `%s', continuing.\n", conv_name);
1767 if (GNUNET_YES == ntohl (rp_msg->locking))
1768 NST_label_lock_release (conv_name, &rp_msg->private_key, nc);
1769 }
1770
1504 GNUNET_STATISTICS_update (statistics, 1771 GNUNET_STATISTICS_update (statistics,
1505 "Well-formed store requests received", 1772 "Well-formed store requests received",
1506 1, 1773 1,
@@ -1509,12 +1776,12 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1509 "Creating %u records for name `%s'\n", 1776 "Creating %u records for name `%s'\n",
1510 (unsigned int) rd_count, 1777 (unsigned int) rd_count,
1511 conv_name); 1778 conv_name);
1512 if ((0 == rd_count) && 1779 if ((GNUNET_NO == GSN_database->lookup_records (GSN_database->cls,
1513 (GNUNET_NO == GSN_database->lookup_records (GSN_database->cls,
1514 &rp_msg->private_key, 1780 &rp_msg->private_key,
1515 conv_name, 1781 conv_name,
1516 NULL, 1782 &get_block_exp_existing,
1517 0))) 1783 &existing_block_exp)) &&
1784 (rd_count == 0))
1518 { 1785 {
1519 /* This name does not exist, so cannot be removed */ 1786 /* This name does not exist, so cannot be removed */
1520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1787 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1525,9 +1792,18 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1525 else 1792 else
1526 { 1793 {
1527 /* remove "NICK" records, unless this is for the 1794 /* remove "NICK" records, unless this is for the
1528 #GNUNET_GNS_EMPTY_LABEL_AT label */ 1795 #GNUNET_GNS_EMPTY_LABEL_AT label
1796 We may need one additional record later for tombstone.
1797 FIXME: Since we must normalize the record set (check for
1798 consistency etc) we have to iterate the set twice.
1799 May be inefficient.
1800 We cannot really move the nick caching into GNSRECORD.
1801 */
1529 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)]; 1802 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)];
1803 struct GNUNET_GNSRECORD_Data rd_nf[GNUNET_NZL (rd_count) + 1];
1530 unsigned int rd_clean_off; 1804 unsigned int rd_clean_off;
1805 unsigned int rd_nf_count;
1806 char *emsg;
1531 int have_nick; 1807 int have_nick;
1532 1808
1533 rd_clean_off = 0; 1809 rd_clean_off = 0;
@@ -1535,6 +1811,7 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1535 for (unsigned int i = 0; i < rd_count; i++) 1811 for (unsigned int i = 0; i < rd_count; i++)
1536 { 1812 {
1537 rd_clean[rd_clean_off] = rd[i]; 1813 rd_clean[rd_clean_off] = rd[i];
1814
1538 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) || 1815 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) ||
1539 (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type)) 1816 (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type))
1540 rd_clean_off++; 1817 rd_clean_off++;
@@ -1546,6 +1823,38 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1546 have_nick = GNUNET_YES; 1823 have_nick = GNUNET_YES;
1547 } 1824 }
1548 } 1825 }
1826 if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (conv_name,
1827 rd_clean,
1828 rd_clean_off,
1829 rd_nf,
1830 &rd_nf_count,
1831 &new_block_exp,
1832 GNUNET_YES,
1833 &emsg))
1834 {
1835 send_store_response (nc, GNUNET_SYSERR, emsg, rid);
1836 GNUNET_free (emsg);
1837 GNUNET_SERVICE_client_continue (nc->client);
1838 GNUNET_free (conv_name);
1839 return;
1840 }
1841 /*
1842 * If existing_block_exp is 0, then there was not record set
1843 * and no tombstone.
1844 * Otherwise, if the existing block expiration is after the
1845 * new block expiration would be, we need to add a tombstone
1846 * or update it.
1847 */
1848 if (GNUNET_TIME_absolute_cmp (new_block_exp, <=, existing_block_exp))
1849 {
1850 rd_nf[rd_nf_count].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE;
1851 rd_nf[rd_nf_count].expiration_time =
1852 existing_block_exp.abs_value_us;
1853 rd_nf[rd_nf_count].data = NULL;
1854 rd_nf[rd_nf_count].data_size = 0;
1855 rd_nf[rd_nf_count].flags = GNUNET_GNSRECORD_RF_PRIVATE;
1856 rd_nf_count++;
1857 }
1549 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && 1858 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1550 (GNUNET_NO == have_nick)) 1859 (GNUNET_NO == have_nick))
1551 { 1860 {
@@ -1555,19 +1864,18 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1555 res = GSN_database->store_records (GSN_database->cls, 1864 res = GSN_database->store_records (GSN_database->cls,
1556 &rp_msg->private_key, 1865 &rp_msg->private_key,
1557 conv_name, 1866 conv_name,
1558 rd_clean_off, 1867 rd_nf_count,
1559 rd_clean); 1868 rd_nf);
1560 } 1869 }
1561 1870
1562 if (GNUNET_OK != res) 1871 if (GNUNET_OK != res)
1563 { 1872 {
1564 /* store not successful, not need to tell monitors */ 1873 /* store not successful, no need to tell monitors */
1565 send_store_response (nc, res, rid); 1874 send_store_response (nc, res, _ ("Store failed"), rid);
1566 GNUNET_SERVICE_client_continue (nc->client); 1875 GNUNET_SERVICE_client_continue (nc->client);
1567 GNUNET_free (conv_name); 1876 GNUNET_free (conv_name);
1568 return; 1877 return;
1569 } 1878 }
1570
1571 sa = GNUNET_malloc (sizeof(struct StoreActivity) 1879 sa = GNUNET_malloc (sizeof(struct StoreActivity)
1572 + ntohs (rp_msg->gns_header.header.size)); 1880 + ntohs (rp_msg->gns_header.header.size));
1573 GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa); 1881 GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa);
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h
index fd9a8ed47..0f3ffa837 100644
--- a/src/namestore/namestore.h
+++ b/src/namestore/namestore.h
@@ -68,6 +68,11 @@ struct RecordStoreMessage
68 struct GNUNET_TIME_AbsoluteNBO expire; 68 struct GNUNET_TIME_AbsoluteNBO expire;
69 69
70 /** 70 /**
71 * Unock the label with this request.
72 */
73 uint32_t locking GNUNET_PACKED;
74
75 /**
71 * Name length 76 * Name length
72 */ 77 */
73 uint16_t name_len GNUNET_PACKED; 78 uint16_t name_len GNUNET_PACKED;
@@ -83,7 +88,7 @@ struct RecordStoreMessage
83 uint16_t rd_count GNUNET_PACKED; 88 uint16_t rd_count GNUNET_PACKED;
84 89
85 /** 90 /**
86 * always zero (for alignment) 91 * Reserved for alignment.
87 */ 92 */
88 uint16_t reserved GNUNET_PACKED; 93 uint16_t reserved GNUNET_PACKED;
89 94
@@ -113,6 +118,20 @@ struct RecordStoreResponseMessage
113 * #GNUNET_SYSERR on failure, #GNUNET_OK on success 118 * #GNUNET_SYSERR on failure, #GNUNET_OK on success
114 */ 119 */
115 int32_t op_result GNUNET_PACKED; 120 int32_t op_result GNUNET_PACKED;
121
122 /**
123 * Error message length
124 */
125 uint16_t emsg_len GNUNET_PACKED;
126
127 /**
128 * Reserved for alignment.
129 */
130 uint16_t reserved GNUNET_PACKED;
131
132 /**
133 * Followed by error message
134 */
116}; 135};
117 136
118 137
@@ -132,6 +151,11 @@ struct LabelLookupMessage
132 uint32_t label_len GNUNET_PACKED; 151 uint32_t label_len GNUNET_PACKED;
133 152
134 /** 153 /**
154 * Lock the label with this lookup
155 */
156 uint32_t locking GNUNET_PACKED;
157
158 /**
135 * The private key of the zone to look up in 159 * The private key of the zone to look up in
136 */ 160 */
137 struct GNUNET_IDENTITY_PrivateKey zone; 161 struct GNUNET_IDENTITY_PrivateKey zone;
@@ -171,7 +195,7 @@ struct LabelLookupResponseMessage
171 * Was the label found in the database?? 195 * Was the label found in the database??
172 * #GNUNET_YES or #GNUNET_NO 196 * #GNUNET_YES or #GNUNET_NO
173 */ 197 */
174 uint16_t found GNUNET_PACKED; 198 int16_t found GNUNET_PACKED;
175 199
176 /** 200 /**
177 * The private key of the authority. 201 * The private key of the authority.
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index b24db9b26..a7380bbde 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -346,6 +346,44 @@ check_rd (size_t rd_len, const void *rd_buf, unsigned int rd_count)
346 return GNUNET_OK; 346 return GNUNET_OK;
347} 347}
348 348
349/**
350 * Handle an incoming message of type
351 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
352 *
353 * @param cls
354 * @param msg the message we received
355 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
356 */
357static int
358check_record_store_response (void *cls,
359 const struct RecordStoreResponseMessage *msg)
360{
361 const char *emsg;
362 size_t msg_len;
363 size_t emsg_len;
364
365 (void) cls;
366 msg_len = ntohs (msg->gns_header.header.size);
367 emsg_len = ntohs (msg->emsg_len);
368 if (0 != ntohs (msg->reserved))
369 {
370 GNUNET_break (0);
371 return GNUNET_SYSERR;
372 }
373 if (msg_len != sizeof(struct RecordStoreResponseMessage) + emsg_len)
374 {
375 GNUNET_break (0);
376 return GNUNET_SYSERR;
377 }
378 emsg = (const char *) &msg[1];
379 if ((0 != emsg_len) && ('\0' != emsg[emsg_len - 1]))
380 {
381 GNUNET_break (0);
382 return GNUNET_SYSERR;
383 }
384 return GNUNET_OK;
385}
386
349 387
350/** 388/**
351 * Handle an incoming message of type 389 * Handle an incoming message of type
@@ -364,19 +402,16 @@ handle_record_store_response (void *cls,
364 const char *emsg; 402 const char *emsg;
365 403
366 qe = find_qe (h, ntohl (msg->gns_header.r_id)); 404 qe = find_qe (h, ntohl (msg->gns_header.r_id));
405 emsg = (const char *) &msg[1];
367 res = ntohl (msg->op_result); 406 res = ntohl (msg->op_result);
368 LOG (GNUNET_ERROR_TYPE_DEBUG, 407 LOG (GNUNET_ERROR_TYPE_DEBUG,
369 "Received RECORD_STORE_RESPONSE with result %d\n", 408 "Received RECORD_STORE_RESPONSE with result %d\n",
370 res); 409 res);
371 /* TODO: add actual error message from namestore to response... */
372 if (GNUNET_SYSERR == res)
373 emsg = _ ("Namestore failed to store record\n");
374 else
375 emsg = NULL;
376 if (NULL == qe) 410 if (NULL == qe)
377 return; 411 return;
378 if (NULL != qe->cont) 412 if (NULL != qe->cont)
379 qe->cont (qe->cont_cls, res, emsg); 413 qe->cont (qe->cont_cls, res,
414 (GNUNET_OK == res) ? NULL : emsg);
380 free_qe (qe); 415 free_qe (qe);
381} 416}
382 417
@@ -444,8 +479,10 @@ handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
444 size_t name_len; 479 size_t name_len;
445 size_t rd_len; 480 size_t rd_len;
446 unsigned int rd_count; 481 unsigned int rd_count;
482 int16_t found = (int16_t) ntohs (msg->found);
447 483
448 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT\n"); 484 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT (found=%i)\n",
485 found);
449 qe = find_qe (h, ntohl (msg->gns_header.r_id)); 486 qe = find_qe (h, ntohl (msg->gns_header.r_id));
450 if (NULL == qe) 487 if (NULL == qe)
451 return; 488 return;
@@ -453,7 +490,7 @@ handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
453 rd_count = ntohs (msg->rd_count); 490 rd_count = ntohs (msg->rd_count);
454 name_len = ntohs (msg->name_len); 491 name_len = ntohs (msg->name_len);
455 name = (const char *) &msg[1]; 492 name = (const char *) &msg[1];
456 if (GNUNET_NO == ntohs (msg->found)) 493 if (GNUNET_NO == found)
457 { 494 {
458 /* label was not in namestore */ 495 /* label was not in namestore */
459 if (NULL != qe->proc) 496 if (NULL != qe->proc)
@@ -461,6 +498,13 @@ handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
461 free_qe (qe); 498 free_qe (qe);
462 return; 499 return;
463 } 500 }
501 if (GNUNET_SYSERR == found)
502 {
503 if (NULL != qe->error_cb)
504 qe->error_cb (qe->error_cb_cls);
505 free_qe (qe);
506 return;
507 }
464 508
465 rd_tmp = &name[name_len]; 509 rd_tmp = &name[name_len];
466 { 510 {
@@ -775,7 +819,7 @@ static void
775reconnect (struct GNUNET_NAMESTORE_Handle *h) 819reconnect (struct GNUNET_NAMESTORE_Handle *h)
776{ 820{
777 struct GNUNET_MQ_MessageHandler handlers[] = 821 struct GNUNET_MQ_MessageHandler handlers[] =
778 { GNUNET_MQ_hd_fixed_size (record_store_response, 822 { GNUNET_MQ_hd_var_size (record_store_response,
779 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE, 823 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE,
780 struct RecordStoreResponseMessage, 824 struct RecordStoreResponseMessage,
781 h), 825 h),
@@ -969,30 +1013,16 @@ warn_delay (void *cls)
969 GNUNET_NAMESTORE_cancel (qe); 1013 GNUNET_NAMESTORE_cancel (qe);
970} 1014}
971 1015
972
973/**
974 * Store an item in the namestore. If the item is already present,
975 * it is replaced with the new record. Use an empty array to
976 * remove all records under the given name.
977 *
978 * @param h handle to the namestore
979 * @param pkey private key of the zone
980 * @param label name that is being mapped (at most 255 characters long)
981 * @param rd_count number of records in the @a rd array
982 * @param rd array of records with data to store
983 * @param cont continuation to call when done
984 * @param cont_cls closure for @a cont
985 * @return handle to abort the request
986 */
987struct GNUNET_NAMESTORE_QueueEntry * 1016struct GNUNET_NAMESTORE_QueueEntry *
988GNUNET_NAMESTORE_records_store ( 1017records_store_ (
989 struct GNUNET_NAMESTORE_Handle *h, 1018 struct GNUNET_NAMESTORE_Handle *h,
990 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1019 const struct GNUNET_IDENTITY_PrivateKey *pkey,
991 const char *label, 1020 const char *label,
992 unsigned int rd_count, 1021 unsigned int rd_count,
993 const struct GNUNET_GNSRECORD_Data *rd, 1022 const struct GNUNET_GNSRECORD_Data *rd,
994 GNUNET_NAMESTORE_ContinuationWithStatus cont, 1023 GNUNET_NAMESTORE_ContinuationWithStatus cont,
995 void *cont_cls) 1024 void *cont_cls,
1025 int locking)
996{ 1026{
997 struct GNUNET_NAMESTORE_QueueEntry *qe; 1027 struct GNUNET_NAMESTORE_QueueEntry *qe;
998 struct GNUNET_MQ_Envelope *env; 1028 struct GNUNET_MQ_Envelope *env;
@@ -1037,8 +1067,9 @@ GNUNET_NAMESTORE_records_store (
1037 msg->name_len = htons (name_len); 1067 msg->name_len = htons (name_len);
1038 msg->rd_count = htons (rd_count); 1068 msg->rd_count = htons (rd_count);
1039 msg->rd_len = htons (rd_ser_len); 1069 msg->rd_len = htons (rd_ser_len);
1040 msg->reserved = htons (0); 1070 msg->reserved = ntohs(0);
1041 msg->private_key = *pkey; 1071 msg->private_key = *pkey;
1072 msg->locking = htonl (locking);
1042 1073
1043 name_tmp = (char *) &msg[1]; 1074 name_tmp = (char *) &msg[1];
1044 GNUNET_memcpy (name_tmp, label, name_len); 1075 GNUNET_memcpy (name_tmp, label, name_len);
@@ -1070,28 +1101,45 @@ GNUNET_NAMESTORE_records_store (
1070 return qe; 1101 return qe;
1071} 1102}
1072 1103
1104struct GNUNET_NAMESTORE_QueueEntry *
1105GNUNET_NAMESTORE_records_store (
1106 struct GNUNET_NAMESTORE_Handle *h,
1107 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1108 const char *label,
1109 unsigned int rd_count,
1110 const struct GNUNET_GNSRECORD_Data *rd,
1111 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1112 void *cont_cls)
1113{
1114 return records_store_ (h, pkey, label,
1115 rd_count, rd, cont, cont_cls, GNUNET_NO);
1116}
1117
1118struct GNUNET_NAMESTORE_QueueEntry *
1119GNUNET_NAMESTORE_records_commit (
1120 struct GNUNET_NAMESTORE_Handle *h,
1121 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1122 const char *label,
1123 unsigned int rd_count,
1124 const struct GNUNET_GNSRECORD_Data *rd,
1125 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1126 void *cont_cls)
1127{
1128 return records_store_ (h, pkey, label,
1129 rd_count, rd, cont, cont_cls, GNUNET_YES);
1130}
1131
1073 1132
1074/**
1075 * Lookup an item in the namestore.
1076 *
1077 * @param h handle to the namestore
1078 * @param pkey private key of the zone
1079 * @param label name that is being mapped (at most 255 characters long)
1080 * @param error_cb function to call on error (i.e. disconnect)
1081 * @param error_cb_cls closure for @a error_cb
1082 * @param rm function to call with the result (with 0 records if we don't have that label)
1083 * @param rm_cls closure for @a rm
1084 * @return handle to abort the request
1085 */
1086struct GNUNET_NAMESTORE_QueueEntry * 1133struct GNUNET_NAMESTORE_QueueEntry *
1087GNUNET_NAMESTORE_records_lookup ( 1134records_lookup_ (
1088 struct GNUNET_NAMESTORE_Handle *h, 1135 struct GNUNET_NAMESTORE_Handle *h,
1089 const struct GNUNET_IDENTITY_PrivateKey *pkey, 1136 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1090 const char *label, 1137 const char *label,
1091 GNUNET_SCHEDULER_TaskCallback error_cb, 1138 GNUNET_SCHEDULER_TaskCallback error_cb,
1092 void *error_cb_cls, 1139 void *error_cb_cls,
1093 GNUNET_NAMESTORE_RecordMonitor rm, 1140 GNUNET_NAMESTORE_RecordMonitor rm,
1094 void *rm_cls) 1141 void *rm_cls,
1142 int locking)
1095{ 1143{
1096 struct GNUNET_NAMESTORE_QueueEntry *qe; 1144 struct GNUNET_NAMESTORE_QueueEntry *qe;
1097 struct GNUNET_MQ_Envelope *env; 1145 struct GNUNET_MQ_Envelope *env;
@@ -1119,6 +1167,7 @@ GNUNET_NAMESTORE_records_lookup (
1119 msg->gns_header.r_id = htonl (qe->op_id); 1167 msg->gns_header.r_id = htonl (qe->op_id);
1120 msg->zone = *pkey; 1168 msg->zone = *pkey;
1121 msg->label_len = htonl (label_len); 1169 msg->label_len = htonl (label_len);
1170 msg->locking = htonl (locking);
1122 GNUNET_memcpy (&msg[1], label, label_len); 1171 GNUNET_memcpy (&msg[1], label, label_len);
1123 if (NULL == h->mq) 1172 if (NULL == h->mq)
1124 qe->env = env; 1173 qe->env = env;
@@ -1127,22 +1176,34 @@ GNUNET_NAMESTORE_records_lookup (
1127 return qe; 1176 return qe;
1128} 1177}
1129 1178
1179struct GNUNET_NAMESTORE_QueueEntry *
1180GNUNET_NAMESTORE_records_lookup (
1181 struct GNUNET_NAMESTORE_Handle *h,
1182 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1183 const char *label,
1184 GNUNET_SCHEDULER_TaskCallback error_cb,
1185 void *error_cb_cls,
1186 GNUNET_NAMESTORE_RecordMonitor rm,
1187 void *rm_cls)
1188{
1189 return records_lookup_ (h, pkey, label,
1190 error_cb, error_cb_cls, rm, rm_cls, GNUNET_NO);
1191}
1192
1193struct GNUNET_NAMESTORE_QueueEntry *
1194GNUNET_NAMESTORE_records_open (
1195 struct GNUNET_NAMESTORE_Handle *h,
1196 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1197 const char *label,
1198 GNUNET_SCHEDULER_TaskCallback error_cb,
1199 void *error_cb_cls,
1200 GNUNET_NAMESTORE_RecordMonitor rm,
1201 void *rm_cls)
1202{
1203 return records_lookup_ (h, pkey, label,
1204 error_cb, error_cb_cls, rm, rm_cls, GNUNET_YES);
1205}
1130 1206
1131/**
1132 * Look for an existing PKEY delegation record for a given public key.
1133 * Returns at most one result to the processor.
1134 *
1135 * @param h handle to the namestore
1136 * @param zone public key of the zone to look up in, never NULL
1137 * @param value_zone public key of the target zone (value), never NULL
1138 * @param error_cb function to call on error (i.e. disconnect)
1139 * @param error_cb_cls closure for @a error_cb
1140 * @param proc function to call on the matching records, or with
1141 * NULL (rd_count == 0) if there are no matching records
1142 * @param proc_cls closure for @a proc
1143 * @return a handle that can be used to
1144 * cancel
1145 */
1146struct GNUNET_NAMESTORE_QueueEntry * 1207struct GNUNET_NAMESTORE_QueueEntry *
1147GNUNET_NAMESTORE_zone_to_name ( 1208GNUNET_NAMESTORE_zone_to_name (
1148 struct GNUNET_NAMESTORE_Handle *h, 1209 struct GNUNET_NAMESTORE_Handle *h,
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c
index 7cb9b7ed0..0b3aac84f 100644
--- a/src/namestore/plugin_namestore_sqlite.c
+++ b/src/namestore/plugin_namestore_sqlite.c
@@ -329,6 +329,11 @@ namestore_sqlite_store_records (void *cls,
329 0, 329 0,
330 sizeof(pkey)); 330 sizeof(pkey));
331 for (unsigned int i = 0; i < rd_count; i++) 331 for (unsigned int i = 0; i < rd_count; i++)
332 {
333 LOG (GNUNET_ERROR_TYPE_DEBUG,
334 "Checking if `%d' is zonekey type\n",
335 rd[i].record_type);
336
332 if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type)) 337 if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
333 { 338 {
334 GNUNET_break (GNUNET_YES == 339 GNUNET_break (GNUNET_YES ==
@@ -336,8 +341,13 @@ namestore_sqlite_store_records (void *cls,
336 rd[i].data_size, 341 rd[i].data_size,
337 rd[i].record_type, 342 rd[i].record_type,
338 &pkey)); 343 &pkey));
344 LOG (GNUNET_ERROR_TYPE_DEBUG,
345 "Storing delegation zone record value `%s'\n",
346 GNUNET_GNSRECORD_z2s (&pkey));
347
339 break; 348 break;
340 } 349 }
350 }
341 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, 351 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
342 UINT64_MAX); 352 UINT64_MAX);
343 data_size = GNUNET_GNSRECORD_records_get_size (rd_count, 353 data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
diff --git a/src/namestore/test_namestore_api_lookup_nick.c b/src/namestore/test_namestore_api_lookup_nick.c
index 6ce969c9b..7decf39f8 100644
--- a/src/namestore/test_namestore_api_lookup_nick.c
+++ b/src/namestore/test_namestore_api_lookup_nick.c
@@ -262,12 +262,12 @@ nick_cont (void *cls, int32_t success, const char *emsg)
262 "Nick added : %s\n", 262 "Nick added : %s\n",
263 (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); 263 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
264 264
265 rd_orig.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; 265 rd_orig.expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
266 rd_orig.record_type = TEST_RECORD_TYPE; 266 rd_orig.record_type = TEST_RECORD_TYPE;
267 rd_orig.data_size = TEST_RECORD_DATALEN; 267 rd_orig.data_size = TEST_RECORD_DATALEN;
268 record_data = GNUNET_malloc (TEST_RECORD_DATALEN); 268 record_data = GNUNET_malloc (TEST_RECORD_DATALEN);
269 rd_orig.data = record_data; 269 rd_orig.data = record_data;
270 rd_orig.flags = 0; 270 rd_orig.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
271 memset ((char *) rd_orig.data, 'a', TEST_RECORD_DATALEN); 271 memset ((char *) rd_orig.data, 'a', TEST_RECORD_DATALEN);
272 272
273 nsqe = GNUNET_NAMESTORE_records_store (nsh, &privkey, 273 nsqe = GNUNET_NAMESTORE_records_store (nsh, &privkey,
diff --git a/src/namestore/test_namestore_api_lookup_public.c b/src/namestore/test_namestore_api_lookup_public.c
index 5e3e7bbd8..cd69b96ef 100644
--- a/src/namestore/test_namestore_api_lookup_public.c
+++ b/src/namestore/test_namestore_api_lookup_public.c
@@ -188,7 +188,7 @@ run (void *cls,
188 struct GNUNET_TESTING_Peer *peer) 188 struct GNUNET_TESTING_Peer *peer)
189{ 189{
190 struct GNUNET_GNSRECORD_Data rd; 190 struct GNUNET_GNSRECORD_Data rd;
191 const char *name = "dummy.dummy.gnunet"; 191 const char *name = "dummy";
192 192
193 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, 193 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
194 &endbadly, 194 &endbadly,
diff --git a/src/namestore/test_namestore_api_lookup_shadow.c b/src/namestore/test_namestore_api_lookup_shadow.c
index 79fa4c9c6..8f47d1280 100644
--- a/src/namestore/test_namestore_api_lookup_shadow.c
+++ b/src/namestore/test_namestore_api_lookup_shadow.c
@@ -223,7 +223,7 @@ run (void *cls,
223 struct GNUNET_TESTING_Peer *peer) 223 struct GNUNET_TESTING_Peer *peer)
224{ 224{
225 struct GNUNET_GNSRECORD_Data rd; 225 struct GNUNET_GNSRECORD_Data rd;
226 const char *name = "dummy.dummy.gnunet"; 226 const char *name = "dummy";
227 227
228 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, 228 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
229 &endbadly, 229 &endbadly,
diff --git a/src/namestore/test_namestore_api_lookup_shadow_filter.c b/src/namestore/test_namestore_api_lookup_shadow_filter.c
index 4fc197750..0bcd130f9 100644
--- a/src/namestore/test_namestore_api_lookup_shadow_filter.c
+++ b/src/namestore/test_namestore_api_lookup_shadow_filter.c
@@ -32,7 +32,7 @@
32 32
33#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT 33#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
34 34
35#define TEST_NAME "dummy.dummy.gnunet" 35#define TEST_NAME "gnunet"
36#define TEST_RECORD_DATALEN 123 36#define TEST_RECORD_DATALEN 123
37#define TEST_RECORD_DATA 'a' 37#define TEST_RECORD_DATA 'a'
38#define TEST_SHADOW_RECORD_DATA 'b' 38#define TEST_SHADOW_RECORD_DATA 'b'
diff --git a/src/namestore/test_namestore_api_remove.c b/src/namestore/test_namestore_api_remove.c
index b6254e531..e8124c595 100644
--- a/src/namestore/test_namestore_api_remove.c
+++ b/src/namestore/test_namestore_api_remove.c
@@ -153,7 +153,7 @@ run (void *cls,
153 struct GNUNET_TESTING_Peer *peer) 153 struct GNUNET_TESTING_Peer *peer)
154{ 154{
155 struct GNUNET_GNSRECORD_Data rd; 155 struct GNUNET_GNSRECORD_Data rd;
156 const char *name = "dummy.dummy.gnunet"; 156 const char *name = "dummy";
157 157
158 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, 158 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
159 &endbadly, 159 &endbadly,
diff --git a/src/namestore/test_namestore_api_remove_not_existing_record.c b/src/namestore/test_namestore_api_remove_not_existing_record.c
index e66992909..958ea4bf2 100644
--- a/src/namestore/test_namestore_api_remove_not_existing_record.c
+++ b/src/namestore/test_namestore_api_remove_not_existing_record.c
@@ -127,7 +127,7 @@ run (void *cls,
127 const struct GNUNET_CONFIGURATION_Handle *cfg, 127 const struct GNUNET_CONFIGURATION_Handle *cfg,
128 struct GNUNET_TESTING_Peer *peer) 128 struct GNUNET_TESTING_Peer *peer)
129{ 129{
130 const char *name = "dummy.dummy.gnunet"; 130 const char *name = "dummy";
131 131
132 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, 132 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
133 &endbadly, 133 &endbadly,
diff --git a/src/namestore/test_namestore_api_zone_to_name.c b/src/namestore/test_namestore_api_zone_to_name.c
index 3fd10e4a1..1e2f8248b 100644
--- a/src/namestore/test_namestore_api_zone_to_name.c
+++ b/src/namestore/test_namestore_api_zone_to_name.c
@@ -216,11 +216,11 @@ run (void *cls,
216 { 216 {
217 struct GNUNET_GNSRECORD_Data rd; 217 struct GNUNET_GNSRECORD_Data rd;
218 218
219 rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; 219 rd.expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
220 rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; 220 rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
221 rd.data_size = GNUNET_IDENTITY_key_get_length (&s_zone_value); 221 rd.data_size = sizeof (s_zone_value.ecdsa_key);
222 rd.data = &s_zone_value; 222 rd.data = &s_zone_value.ecdsa_key;
223 rd.flags = 0; 223 rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
224 224
225 nsh = GNUNET_NAMESTORE_connect (cfg); 225 nsh = GNUNET_NAMESTORE_connect (cfg);
226 GNUNET_break (NULL != nsh); 226 GNUNET_break (NULL != nsh);
@@ -230,7 +230,7 @@ run (void *cls,
230 1, 230 1,
231 &rd, 231 &rd,
232 &put_cont, 232 &put_cont,
233 NULL); 233 s_name);
234 } 234 }
235} 235}
236 236
diff --git a/src/namestore/test_namestore_delete.sh b/src/namestore/test_namestore_delete.sh
index 44ea1e66c..b861a4bc0 100755
--- a/src/namestore/test_namestore_delete.sh
+++ b/src/namestore/test_namestore_delete.sh
@@ -61,15 +61,7 @@ for LINE in $OUTPUT ;
61stop_peer 61stop_peer
62 62
63 63
64if [ $FOUND_NAME = false -a $FOUND_IP != false ] 64if [ $FOUND_IP = true ]
65then
66 echo "PASS: Delete name in namestore"
67 exit 0
68elif [ $FOUND_NAME = true ]
69then
70 echo "FAIL: Delete name in namestore: name returned"
71 exit 1
72elif [ $FOUND_IP = true ]
73then 65then
74 echo "FAIL: Delete name in namestore: IP returned" 66 echo "FAIL: Delete name in namestore: IP returned"
75 exit 1 67 exit 1
diff --git a/src/namestore/test_plugin_rest_namestore.sh b/src/namestore/test_plugin_rest_namestore.sh
index 8a45cebf5..50b3c8c12 100755
--- a/src/namestore/test_plugin_rest_namestore.sh
+++ b/src/namestore/test_plugin_rest_namestore.sh
@@ -78,15 +78,16 @@ curl_delete () {
78 78
79TEST_ID="test" 79TEST_ID="test"
80gnunet-arm -s -c test_namestore_api.conf 80gnunet-arm -s -c test_namestore_api.conf
81gnunet-arm -i rest -c test_namestore_api.conf
82#Test GET 81#Test GET
83gnunet-identity -C $TEST_ID -c test_namestore_api.conf 82gnunet-identity -C $TEST_ID -c test_namestore_api.conf
84test="$(gnunet-namestore -D -z $TEST_ID -c test_namestore_api.conf)" 83test="$(gnunet-namestore -D -z $TEST_ID -c test_namestore_api.conf)"
85name=$TEST_ID 84name=$TEST_ID
86public="$(gnunet-identity -d -c test_namestore_api.conf | grep $TEST_ID | awk 'NR==1{print $3}')" 85public="$(gnunet-identity -d -c test_namestore_api.conf | grep $TEST_ID | awk 'NR==1{print $3}')"
87echo "$name $public" 86echo "$name $public"
88valgrind gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf 87gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf
89#curl_get "${namestore_link}" "HTTP/1.1 200 OK" 88sleep 1
89gnunet-arm -i rest -c test_namestore_api.conf
90sleep 1
90curl_get "${namestore_link}/$name" "HTTP/1.1 200 OK" 91curl_get "${namestore_link}/$name" "HTTP/1.1 200 OK"
91curl_get "${namestore_link}/$public" "error" 92curl_get "${namestore_link}/$public" "error"
92gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf 93gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf
@@ -128,9 +129,6 @@ gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/
128#Test DELETE 129#Test DELETE
129gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf 130gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf
130curl_delete "${namestore_link}/$name/test_entry" "HTTP/1.1 204" 131curl_delete "${namestore_link}/$name/test_entry" "HTTP/1.1 204"
131curl_delete "${namestore_link}/$name/test_entry" "error"
132gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf
133curl_delete "${namestore_link}/$public/test_entry" "error"
134 132
135gnunet-arm -e -c test_namestore_api.conf 133gnunet-arm -e -c test_namestore_api.conf
136exit 0; 134exit 0;
diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c
index f41473f9f..bc6b835c9 100644
--- a/src/reclaim/reclaim_api.c
+++ b/src/reclaim/reclaim_api.c
@@ -1550,7 +1550,6 @@ GNUNET_RECLAIM_ticket_issue (
1550 struct IssueTicketMessage *tim; 1550 struct IssueTicketMessage *tim;
1551 size_t attr_len; 1551 size_t attr_len;
1552 1552
1553 fprintf (stderr, "Issuing ticket\n");
1554 op = GNUNET_new (struct GNUNET_RECLAIM_Operation); 1553 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1555 op->h = h; 1554 op->h = h;
1556 op->ti_cb = cb; 1555 op->ti_cb = cb;
diff --git a/src/reclaim/test_reclaim.conf b/src/reclaim/test_reclaim.conf
index ec19056e4..2dc53fe81 100644
--- a/src/reclaim/test_reclaim.conf
+++ b/src/reclaim/test_reclaim.conf
@@ -15,7 +15,7 @@ PLUGINS =
15 15
16[reclaim] 16[reclaim]
17START_ON_DEMAND = YES 17START_ON_DEMAND = YES
18TICKET_REFRESH_INTERVAL = 15s 18TICKET_REFRESH_INTERVAL = 30 s
19#PREFIX = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=$GNUNET_TMP/idplog 19#PREFIX = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=$GNUNET_TMP/idplog
20 20
21[gns] 21[gns]
diff --git a/src/reclaim/test_reclaim_consume.sh b/src/reclaim/test_reclaim_consume.sh
index 9186d3cb1..c012862c3 100755
--- a/src/reclaim/test_reclaim_consume.sh
+++ b/src/reclaim/test_reclaim_consume.sh
@@ -32,12 +32,14 @@ TEST_KEY=$(gnunet-identity -d -e testego -q -c test_reclaim.conf)
32gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf 32gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf
33gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf 33gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf
34TICKET=$(gnunet-reclaim -e testego -i "email,name" -r $SUBJECT_KEY -c test_reclaim.conf | awk '{print $1}') 34TICKET=$(gnunet-reclaim -e testego -i "email,name" -r $SUBJECT_KEY -c test_reclaim.conf | awk '{print $1}')
35gnunet-reclaim -e rpego -C $TICKET -c test_reclaim.conf >/dev/null 2>&1 35gnunet-reclaim -e rpego -C $TICKET -c test_reclaim.conf #>/dev/null 2>&1
36 36
37if test $? != 0 37RES=$?
38gnunet-identity -D testego -c test_reclaim.conf
39gnunet-identity -D rpego -c test_reclaim.conf
40gnunet-arm -e -c test_reclaim.conf
41if test $RES != 0
38then 42then
39 "Failed." 43 echo "Failed."
40 exit 1
41fi 44fi
42#curl http://localhost:7776/reclaim/tickets/testego 45
43gnunet-arm -e -c test_reclaim.conf
diff --git a/src/regex/plugin_block_regex.c b/src/regex/plugin_block_regex.c
index 0953830ab..61442ac10 100644
--- a/src/regex/plugin_block_regex.c
+++ b/src/regex/plugin_block_regex.c
@@ -93,242 +93,6 @@ block_plugin_regex_create_group (void *cls,
93 93
94 94
95/** 95/**
96 * Function called to validate a reply or a request of type
97 * #GNUNET_BLOCK_TYPE_REGEX.
98 * For request evaluation, pass "NULL" for the reply_block.
99 * Note that it is assumed that the reply has already been
100 * matched to the key (and signatures checked) as it would
101 * be done with the #GNUNET_BLOCK_get_key() function.
102 *
103 * @param cls closure
104 * @param type block type
105 * @param bg block group to evaluate against
106 * @param eo control flags
107 * @param query original query (hash)
108 * @param xquery extrended query data (can be NULL, depending on type)
109 * @param xquery_size number of bytes in @a xquery
110 * @param reply_block response to validate
111 * @param reply_block_size number of bytes in @a reply_block
112 * @return characterization of result
113 */
114static enum GNUNET_BLOCK_EvaluationResult
115evaluate_block_regex (void *cls,
116 enum GNUNET_BLOCK_Type type,
117 struct GNUNET_BLOCK_Group *bg,
118 enum GNUNET_BLOCK_EvaluationOptions eo,
119 const struct GNUNET_HashCode *query,
120 const void *xquery,
121 size_t xquery_size,
122 const void *reply_block,
123 size_t reply_block_size)
124{
125 struct GNUNET_HashCode chash;
126
127 if (NULL == reply_block)
128 {
129 if (0 != xquery_size)
130 {
131 const char *s;
132
133 s = (const char *) xquery;
134 if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */
135 {
136 GNUNET_break_op (0);
137 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
138 }
139 }
140 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
141 }
142 if (0 != xquery_size)
143 {
144 const char *s;
145
146 s = (const char *) xquery;
147 if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */
148 {
149 GNUNET_break_op (0);
150 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
151 }
152 }
153 else if (NULL != query)
154 {
155 /* xquery is required for regex GETs, at least an empty string */
156 GNUNET_break_op (0);
157 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "type %d, query %p, xquery %p\n",
158 type, query, xquery);
159 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
160 }
161 switch (REGEX_BLOCK_check (reply_block,
162 reply_block_size,
163 query,
164 xquery))
165 {
166 case GNUNET_SYSERR:
167 GNUNET_break_op (0);
168 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
169
170 case GNUNET_NO:
171 /* xquery mismatch, can happen */
172 return GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT;
173
174 default:
175 break;
176 }
177 GNUNET_CRYPTO_hash (reply_block,
178 reply_block_size,
179 &chash);
180 if (GNUNET_YES ==
181 GNUNET_BLOCK_GROUP_bf_test_and_set (bg,
182 &chash))
183 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
184 return GNUNET_BLOCK_EVALUATION_OK_MORE;
185}
186
187
188/**
189 * Function called to validate a reply or a request of type
190 * #GNUNET_BLOCK_TYPE_REGEX_ACCEPT.
191 * For request evaluation, pass "NULL" for the reply_block.
192 * Note that it is assumed that the reply has already been
193 * matched to the key (and signatures checked) as it would
194 * be done with the #GNUNET_BLOCK_get_key() function.
195 *
196 * @param cls closure
197 * @param type block type
198 * @param bg block group to evaluate against
199 * @param eo control flags
200 * @param query original query (hash)
201 * @param xquery extrended query data (can be NULL, depending on type)
202 * @param xquery_size number of bytes in @a xquery
203 * @param reply_block response to validate
204 * @param reply_block_size number of bytes in @a reply_block
205 * @return characterization of result
206 */
207static enum GNUNET_BLOCK_EvaluationResult
208evaluate_block_regex_accept (void *cls,
209 enum GNUNET_BLOCK_Type type,
210 struct GNUNET_BLOCK_Group *bg,
211 enum GNUNET_BLOCK_EvaluationOptions eo,
212 const struct GNUNET_HashCode *query,
213 const void *xquery,
214 size_t xquery_size, const void *reply_block,
215 size_t reply_block_size)
216{
217 const struct RegexAcceptBlock *rba;
218 struct GNUNET_HashCode chash;
219
220 if (0 != xquery_size)
221 {
222 GNUNET_break_op (0);
223 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
224 }
225 if (NULL == reply_block)
226 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
227 if (sizeof(struct RegexAcceptBlock) != reply_block_size)
228 {
229 GNUNET_break_op (0);
230 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
231 }
232 rba = reply_block;
233 if (ntohl (rba->purpose.size) !=
234 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
235 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
236 + sizeof(struct GNUNET_HashCode))
237 {
238 GNUNET_break_op (0);
239 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
240 }
241 if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (
242 rba->expiration_time)).
243 rel_value_us)
244 {
245 /* technically invalid, but can happen without an error, so
246 we're nice by reporting it as a 'duplicate' */
247 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
248 }
249 if (GNUNET_OK !=
250 GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT,
251 &rba->purpose,
252 &rba->signature,
253 &rba->peer.public_key))
254 {
255 GNUNET_break_op (0);
256 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
257 }
258 GNUNET_CRYPTO_hash (reply_block,
259 reply_block_size,
260 &chash);
261 if (GNUNET_YES ==
262 GNUNET_BLOCK_GROUP_bf_test_and_set (bg,
263 &chash))
264 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
265 return GNUNET_BLOCK_EVALUATION_OK_MORE;
266}
267
268
269/**
270 * Function called to validate a reply or a request. For
271 * request evaluation, simply pass "NULL" for the reply_block.
272 * Note that it is assumed that the reply has already been
273 * matched to the key (and signatures checked) as it would
274 * be done with the #GNUNET_BLOCK_get_key() function.
275 *
276 * @param cls closure
277 * @param ctx block context
278 * @param type block type
279 * @param bg group to evaluate against
280 * @param eo control flags
281 * @param query original query (hash)
282 * @param xquery extrended query data (can be NULL, depending on type)
283 * @param xquery_size number of bytes in xquery
284 * @param reply_block response to validate
285 * @param reply_block_size number of bytes in reply block
286 * @return characterization of result
287 */
288static enum GNUNET_BLOCK_EvaluationResult
289block_plugin_regex_evaluate (void *cls,
290 struct GNUNET_BLOCK_Context *ctx,
291 enum GNUNET_BLOCK_Type type,
292 struct GNUNET_BLOCK_Group *bg,
293 enum GNUNET_BLOCK_EvaluationOptions eo,
294 const struct GNUNET_HashCode *query,
295 const void *xquery,
296 size_t xquery_size,
297 const void *reply_block,
298 size_t reply_block_size)
299{
300 enum GNUNET_BLOCK_EvaluationResult result;
301
302 switch (type)
303 {
304 case GNUNET_BLOCK_TYPE_REGEX:
305 result = evaluate_block_regex (cls,
306 type,
307 bg,
308 eo,
309 query,
310 xquery, xquery_size,
311 reply_block, reply_block_size);
312 break;
313
314 case GNUNET_BLOCK_TYPE_REGEX_ACCEPT:
315 result = evaluate_block_regex_accept (cls,
316 type,
317 bg,
318 eo,
319 query,
320 xquery, xquery_size,
321 reply_block, reply_block_size);
322 break;
323
324 default:
325 result = GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
326 }
327 return result;
328}
329
330
331/**
332 * Function called to validate a query. 96 * Function called to validate a query.
333 * 97 *
334 * @param cls closure 98 * @param cls closure
@@ -341,10 +105,10 @@ block_plugin_regex_evaluate (void *cls,
341 */ 105 */
342static enum GNUNET_GenericReturnValue 106static enum GNUNET_GenericReturnValue
343block_plugin_regex_check_query (void *cls, 107block_plugin_regex_check_query (void *cls,
344 enum GNUNET_BLOCK_Type type, 108 enum GNUNET_BLOCK_Type type,
345 const struct GNUNET_HashCode *query, 109 const struct GNUNET_HashCode *query,
346 const void *xquery, 110 const void *xquery,
347 size_t xquery_size) 111 size_t xquery_size)
348{ 112{
349 switch (type) 113 switch (type)
350 { 114 {
@@ -380,7 +144,6 @@ block_plugin_regex_check_query (void *cls,
380 * 144 *
381 * @param cls closure 145 * @param cls closure
382 * @param type block type 146 * @param type block type
383 * @param query key for the block (hash), must match exactly
384 * @param block block data to validate 147 * @param block block data to validate
385 * @param block_size number of bytes in @a block 148 * @param block_size number of bytes in @a block
386 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 149 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
@@ -388,7 +151,6 @@ block_plugin_regex_check_query (void *cls,
388static enum GNUNET_GenericReturnValue 151static enum GNUNET_GenericReturnValue
389block_plugin_regex_check_block (void *cls, 152block_plugin_regex_check_block (void *cls,
390 enum GNUNET_BLOCK_Type type, 153 enum GNUNET_BLOCK_Type type,
391 const struct GNUNET_HashCode *query,
392 const void *block, 154 const void *block,
393 size_t block_size) 155 size_t block_size)
394{ 156{
@@ -398,7 +160,7 @@ block_plugin_regex_check_block (void *cls,
398 if (GNUNET_SYSERR == 160 if (GNUNET_SYSERR ==
399 REGEX_BLOCK_check (block, 161 REGEX_BLOCK_check (block,
400 block_size, 162 block_size,
401 query, 163 NULL,
402 NULL)) 164 NULL))
403 return GNUNET_NO; 165 return GNUNET_NO;
404 return GNUNET_OK; 166 return GNUNET_OK;
@@ -480,12 +242,7 @@ block_plugin_regex_check_reply (
480 const char *s; 242 const char *s;
481 243
482 s = (const char *) xquery; 244 s = (const char *) xquery;
483 if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */ 245 GNUNET_assert ('\0' == s[xquery_size - 1]);
484 {
485 /* Technically, the query is invalid ... */
486 GNUNET_break (0);
487 return GNUNET_BLOCK_REPLY_INVALID;
488 }
489 } 246 }
490 switch (REGEX_BLOCK_check (reply_block, 247 switch (REGEX_BLOCK_check (reply_block,
491 reply_block_size, 248 reply_block_size,
@@ -493,8 +250,7 @@ block_plugin_regex_check_reply (
493 xquery)) 250 xquery))
494 { 251 {
495 case GNUNET_SYSERR: 252 case GNUNET_SYSERR:
496 GNUNET_break_op (0); 253 GNUNET_assert (0);
497 return GNUNET_BLOCK_REPLY_INVALID;
498 case GNUNET_NO: 254 case GNUNET_NO:
499 /* xquery mismatch, can happen */ 255 /* xquery mismatch, can happen */
500 return GNUNET_BLOCK_REPLY_IRRELEVANT; 256 return GNUNET_BLOCK_REPLY_IRRELEVANT;
@@ -513,20 +269,12 @@ block_plugin_regex_check_reply (
513 { 269 {
514 const struct RegexAcceptBlock *rba; 270 const struct RegexAcceptBlock *rba;
515 271
516 if (sizeof(struct RegexAcceptBlock) != reply_block_size) 272 GNUNET_assert (sizeof(struct RegexAcceptBlock) == reply_block_size);
517 {
518 GNUNET_break_op (0);
519 return GNUNET_BLOCK_REPLY_INVALID;
520 }
521 rba = reply_block; 273 rba = reply_block;
522 if (ntohl (rba->purpose.size) != 274 GNUNET_assert (ntohl (rba->purpose.size) ==
523 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) 275 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
524 + sizeof(struct GNUNET_TIME_AbsoluteNBO) 276 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
525 + sizeof(struct GNUNET_HashCode)) 277 + sizeof(struct GNUNET_HashCode));
526 {
527 GNUNET_break_op (0);
528 return GNUNET_BLOCK_REPLY_INVALID;
529 }
530 GNUNET_CRYPTO_hash (reply_block, 278 GNUNET_CRYPTO_hash (reply_block,
531 reply_block_size, 279 reply_block_size,
532 &chash); 280 &chash);
@@ -552,8 +300,8 @@ block_plugin_regex_check_reply (
552 * @param block block to get the key for 300 * @param block block to get the key for
553 * @param block_size number of bytes in @a block 301 * @param block_size number of bytes in @a block
554 * @param key set to the key (query) for the given block 302 * @param key set to the key (query) for the given block
555 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 303 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported,
556 * (or if extracting a key from a block of this type does not work) 304 * #GNUNET_NO if extracting a key from a block of this type does not work
557 */ 305 */
558static enum GNUNET_GenericReturnValue 306static enum GNUNET_GenericReturnValue
559block_plugin_regex_get_key (void *cls, 307block_plugin_regex_get_key (void *cls,
@@ -571,14 +319,20 @@ block_plugin_regex_get_key (void *cls,
571 key)) 319 key))
572 { 320 {
573 GNUNET_break_op (0); 321 GNUNET_break_op (0);
574 return GNUNET_NO; 322 memset (key,
323 0,
324 sizeof (*key));
325 return GNUNET_OK;
575 } 326 }
576 return GNUNET_OK; 327 return GNUNET_OK;
577 case GNUNET_BLOCK_TYPE_REGEX_ACCEPT: 328 case GNUNET_BLOCK_TYPE_REGEX_ACCEPT:
578 if (sizeof(struct RegexAcceptBlock) != block_size) 329 if (sizeof(struct RegexAcceptBlock) != block_size)
579 { 330 {
580 GNUNET_break_op (0); 331 GNUNET_break_op (0);
581 return GNUNET_NO; 332 memset (key,
333 0,
334 sizeof (*key));
335 return GNUNET_OK;
582 } 336 }
583 *key = ((struct RegexAcceptBlock *) block)->key; 337 *key = ((struct RegexAcceptBlock *) block)->key;
584 return GNUNET_OK; 338 return GNUNET_OK;
@@ -603,7 +357,6 @@ libgnunet_plugin_block_regex_init (void *cls)
603 struct GNUNET_BLOCK_PluginFunctions *api; 357 struct GNUNET_BLOCK_PluginFunctions *api;
604 358
605 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 359 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
606 api->evaluate = &block_plugin_regex_evaluate;
607 api->get_key = &block_plugin_regex_get_key; 360 api->get_key = &block_plugin_regex_get_key;
608 api->check_query = &block_plugin_regex_check_query; 361 api->check_query = &block_plugin_regex_check_query;
609 api->check_block = &block_plugin_regex_check_block; 362 api->check_block = &block_plugin_regex_check_block;
diff --git a/src/revocation/gnunet-revocation-tvg.c b/src/revocation/gnunet-revocation-tvg.c
index 3ba5b56fa..a34a6bc98 100644
--- a/src/revocation/gnunet-revocation-tvg.c
+++ b/src/revocation/gnunet-revocation-tvg.c
@@ -159,6 +159,7 @@ run (void *cls,
159 print_bytes (pow, 159 print_bytes (pow,
160 GNUNET_REVOCATION_proof_get_size (pow), 160 GNUNET_REVOCATION_proof_get_size (pow),
161 8); 161 8);
162 GNUNET_free (ph);
162} 163}
163 164
164 165
diff --git a/src/revocation/plugin_block_revocation.c b/src/revocation/plugin_block_revocation.c
index 3beae60bb..12ec555e4 100644
--- a/src/revocation/plugin_block_revocation.c
+++ b/src/revocation/plugin_block_revocation.c
@@ -44,65 +44,6 @@ struct InternalContext
44 44
45 45
46/** 46/**
47 * Function called to validate a reply or a request. For
48 * request evaluation, simply pass "NULL" for the reply_block.
49 *
50 * @param cls our `struct InternalContext`
51 * @param ctx context
52 * @param type block type
53 * @param group block group to use
54 * @param eo control flags
55 * @param query original query (hash)
56 * @param xquery extrended query data (can be NULL, depending on type)
57 * @param xquery_size number of bytes in xquery
58 * @param reply_block response to validate
59 * @param reply_block_size number of bytes in reply block
60 * @return characterization of result
61 */
62static enum GNUNET_BLOCK_EvaluationResult
63block_plugin_revocation_evaluate (void *cls,
64 struct GNUNET_BLOCK_Context *ctx,
65 enum GNUNET_BLOCK_Type type,
66 struct GNUNET_BLOCK_Group *group,
67 enum GNUNET_BLOCK_EvaluationOptions eo,
68 const struct GNUNET_HashCode *query,
69 const void *xquery,
70 size_t xquery_size,
71 const void *reply_block,
72 size_t reply_block_size)
73{
74 struct InternalContext *ic = cls;
75 ssize_t pklen;
76 const struct RevokeMessage *rm = reply_block;
77
78 if (NULL == reply_block)
79 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
80 if (reply_block_size != sizeof(*rm))
81 {
82 GNUNET_break_op (0);
83 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
84 }
85 struct GNUNET_REVOCATION_PowP *pow = (struct GNUNET_REVOCATION_PowP *) &rm[1];
86 const struct GNUNET_IDENTITY_PublicKey *pk;
87 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
88 if (GNUNET_YES != GNUNET_REVOCATION_check_pow (pow,
89 ic->matching_bits,
90 ic->epoch_duration))
91 {
92 GNUNET_break_op (0);
93 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
94 }
95 pklen = GNUNET_IDENTITY_key_get_length (pk);
96 if (0 > pklen)
97 {
98 GNUNET_break_op (0);
99 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
100 }
101 return GNUNET_BLOCK_EVALUATION_OK_LAST;
102}
103
104
105/**
106 * Function called to validate a query. 47 * Function called to validate a query.
107 * 48 *
108 * @param cls closure 49 * @param cls closure
@@ -124,7 +65,10 @@ block_plugin_revocation_check_query (void *cls,
124 (void) query; 65 (void) query;
125 (void) xquery; 66 (void) xquery;
126 if (GNUNET_BLOCK_TYPE_REVOCATION != type) 67 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
68 {
69 GNUNET_break (0);
127 return GNUNET_SYSERR; 70 return GNUNET_SYSERR;
71 }
128 if (0 != xquery_size) 72 if (0 != xquery_size)
129 return GNUNET_NO; 73 return GNUNET_NO;
130 return GNUNET_OK; 74 return GNUNET_OK;
@@ -136,7 +80,6 @@ block_plugin_revocation_check_query (void *cls,
136 * 80 *
137 * @param cls closure 81 * @param cls closure
138 * @param type block type 82 * @param type block type
139 * @param query key for the block (hash), must match exactly
140 * @param block block data to validate 83 * @param block block data to validate
141 * @param block_size number of bytes in @a block 84 * @param block_size number of bytes in @a block
142 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 85 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
@@ -144,7 +87,6 @@ block_plugin_revocation_check_query (void *cls,
144static enum GNUNET_GenericReturnValue 87static enum GNUNET_GenericReturnValue
145block_plugin_revocation_check_block (void *cls, 88block_plugin_revocation_check_block (void *cls,
146 enum GNUNET_BLOCK_Type type, 89 enum GNUNET_BLOCK_Type type,
147 const struct GNUNET_HashCode *query,
148 const void *block, 90 const void *block,
149 size_t block_size) 91 size_t block_size)
150{ 92{
@@ -157,7 +99,10 @@ block_plugin_revocation_check_block (void *cls,
157 size_t left; 99 size_t left;
158 100
159 if (GNUNET_BLOCK_TYPE_REVOCATION != type) 101 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
102 {
103 GNUNET_break (0);
160 return GNUNET_SYSERR; 104 return GNUNET_SYSERR;
105 }
161 if (block_size < sizeof(*rm) + sizeof(*pow)) 106 if (block_size < sizeof(*rm) + sizeof(*pow))
162 { 107 {
163 GNUNET_break_op (0); 108 GNUNET_break_op (0);
@@ -224,7 +169,10 @@ block_plugin_revocation_check_reply (
224 (void) reply_block; 169 (void) reply_block;
225 (void) reply_block_size; 170 (void) reply_block_size;
226 if (GNUNET_BLOCK_TYPE_REVOCATION != type) 171 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
172 {
173 GNUNET_break (0);
227 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED; 174 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
175 }
228 return GNUNET_BLOCK_REPLY_OK_LAST; 176 return GNUNET_BLOCK_REPLY_OK_LAST;
229} 177}
230 178
@@ -255,7 +203,10 @@ block_plugin_revocation_get_key (void *cls,
255 size_t left; 203 size_t left;
256 204
257 if (GNUNET_BLOCK_TYPE_REVOCATION != type) 205 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
206 {
207 GNUNET_break (0);
258 return GNUNET_SYSERR; 208 return GNUNET_SYSERR;
209 }
259 if (block_size < sizeof(*rm) + sizeof(*pow)) 210 if (block_size < sizeof(*rm) + sizeof(*pow))
260 { 211 {
261 GNUNET_break_op (0); 212 GNUNET_break_op (0);
@@ -314,7 +265,6 @@ libgnunet_plugin_block_revocation_init (void *cls)
314 return NULL; 265 return NULL;
315 266
316 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 267 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
317 api->evaluate = &block_plugin_revocation_evaluate;
318 api->get_key = &block_plugin_revocation_get_key; 268 api->get_key = &block_plugin_revocation_get_key;
319 api->check_query = &block_plugin_revocation_check_query; 269 api->check_query = &block_plugin_revocation_check_query;
320 api->check_block = &block_plugin_revocation_check_block; 270 api->check_block = &block_plugin_revocation_check_block;
diff --git a/src/revocation/revocation_api.c b/src/revocation/revocation_api.c
index bc5dae021..9080ab862 100644
--- a/src/revocation/revocation_api.c
+++ b/src/revocation/revocation_api.c
@@ -758,13 +758,11 @@ GNUNET_REVOCATION_proof_get_size (const struct GNUNET_REVOCATION_PowP *pow)
758 size_t size; 758 size_t size;
759 size_t ksize; 759 size_t ksize;
760 const struct GNUNET_IDENTITY_PublicKey *pk; 760 const struct GNUNET_IDENTITY_PublicKey *pk;
761 const struct GNUNET_IDENTITY_Signature *sig;
762 761
763 size = sizeof (struct GNUNET_REVOCATION_PowP); 762 size = sizeof (struct GNUNET_REVOCATION_PowP);
764 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1]; 763 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
765 ksize = GNUNET_IDENTITY_key_get_length (pk); 764 ksize = GNUNET_IDENTITY_key_get_length (pk);
766 size += ksize; 765 size += ksize;
767 sig = (struct GNUNET_IDENTITY_Signature *) ((char*) &pow[1] + ksize);
768 size += GNUNET_IDENTITY_signature_get_raw_length_by_type (pk->type); 766 size += GNUNET_IDENTITY_signature_get_raw_length_by_type (pk->type);
769 return size; 767 return size;
770} 768}
diff --git a/src/set/plugin_block_set_test.c b/src/set/plugin_block_set_test.c
index 3d66831bb..cb5cef5ad 100644
--- a/src/set/plugin_block_set_test.c
+++ b/src/set/plugin_block_set_test.c
@@ -30,46 +30,9 @@
30 30
31 31
32/** 32/**
33 * Function called to validate a reply or a request. For
34 * request evaluation, simply pass "NULL" for the reply_block.
35 *
36 * @param cls closure
37 * @param ctx block context
38 * @param type block type
39 * @param group block group to use
40 * @param eo control flags
41 * @param query original query (hash)
42 * @param xquery extrended query data (can be NULL, depending on type)
43 * @param xquery_size number of bytes in xquery
44 * @param reply_block response to validate
45 * @param reply_block_size number of bytes in reply block
46 * @return characterization of result
47 */
48static enum GNUNET_BLOCK_EvaluationResult
49block_plugin_set_test_evaluate (void *cls,
50 struct GNUNET_BLOCK_Context *ctx,
51 enum GNUNET_BLOCK_Type type,
52 struct GNUNET_BLOCK_Group *group,
53 enum GNUNET_BLOCK_EvaluationOptions eo,
54 const struct GNUNET_HashCode *query,
55 const void *xquery,
56 size_t xquery_size,
57 const void *reply_block,
58 size_t reply_block_size)
59{
60 if ((NULL == reply_block) ||
61 (reply_block_size == 0) ||
62 (0 != ((char *) reply_block)[0]))
63 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
64 return GNUNET_BLOCK_EVALUATION_OK_MORE;
65}
66
67
68/**
69 * Function called to validate a query. 33 * Function called to validate a query.
70 * 34 *
71 * @param cls closure 35 * @param cls closure
72 * @param ctx block context
73 * @param type block type 36 * @param type block type
74 * @param query original query (hash) 37 * @param query original query (hash)
75 * @param xquery extrended query data (can be NULL, depending on type) 38 * @param xquery extrended query data (can be NULL, depending on type)
@@ -92,7 +55,6 @@ block_plugin_set_test_check_query (void *cls,
92 * 55 *
93 * @param cls closure 56 * @param cls closure
94 * @param type block type 57 * @param type block type
95 * @param query key for the block (hash), must match exactly
96 * @param block block data to validate 58 * @param block block data to validate
97 * @param block_size number of bytes in @a block 59 * @param block_size number of bytes in @a block
98 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 60 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
@@ -100,7 +62,6 @@ block_plugin_set_test_check_query (void *cls,
100static enum GNUNET_GenericReturnValue 62static enum GNUNET_GenericReturnValue
101block_plugin_set_test_check_block (void *cls, 63block_plugin_set_test_check_block (void *cls,
102 enum GNUNET_BLOCK_Type type, 64 enum GNUNET_BLOCK_Type type,
103 const struct GNUNET_HashCode *query,
104 const void *block, 65 const void *block,
105 size_t block_size) 66 size_t block_size)
106{ 67{
@@ -141,7 +102,7 @@ block_plugin_set_test_check_reply (void *cls,
141 if ((NULL == reply_block) || 102 if ((NULL == reply_block) ||
142 (0 == reply_block_size) || 103 (0 == reply_block_size) ||
143 (0 != ((char *) reply_block)[0])) 104 (0 != ((char *) reply_block)[0]))
144 return GNUNET_BLOCK_REPLY_INVALID; 105 GNUNET_assert (0);
145 return GNUNET_BLOCK_REPLY_OK_MORE; 106 return GNUNET_BLOCK_REPLY_OK_MORE;
146} 107}
147 108
@@ -164,7 +125,7 @@ block_plugin_set_test_get_key (void *cls,
164 size_t block_size, 125 size_t block_size,
165 struct GNUNET_HashCode *key) 126 struct GNUNET_HashCode *key)
166{ 127{
167 return GNUNET_SYSERR; 128 return GNUNET_NO;
168} 129}
169 130
170 131
@@ -181,7 +142,6 @@ libgnunet_plugin_block_set_test_init (void *cls)
181 struct GNUNET_BLOCK_PluginFunctions *api; 142 struct GNUNET_BLOCK_PluginFunctions *api;
182 143
183 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 144 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
184 api->evaluate = &block_plugin_set_test_evaluate;
185 api->get_key = &block_plugin_set_test_get_key; 145 api->get_key = &block_plugin_set_test_get_key;
186 api->check_query = &block_plugin_set_test_check_query; 146 api->check_query = &block_plugin_set_test_check_query;
187 api->check_block = &block_plugin_set_test_check_block; 147 api->check_block = &block_plugin_set_test_check_block;
diff --git a/src/seti/plugin_block_seti_test.c b/src/seti/plugin_block_seti_test.c
index af86e1af6..5b9196cef 100644
--- a/src/seti/plugin_block_seti_test.c
+++ b/src/seti/plugin_block_seti_test.c
@@ -30,42 +30,6 @@
30 30
31 31
32/** 32/**
33 * Function called to validate a reply or a request. For
34 * request evaluation, simply pass "NULL" for the reply_block.
35 *
36 * @param cls closure
37 * @param ctx block context
38 * @param type block type
39 * @param group block group to use
40 * @param eo control flags
41 * @param query original query (hash)
42 * @param xquery extrended query data (can be NULL, depending on type)
43 * @param xquery_size number of bytes in xquery
44 * @param reply_block response to validate
45 * @param reply_block_size number of bytes in reply block
46 * @return characterization of result
47 */
48static enum GNUNET_BLOCK_EvaluationResult
49block_plugin_seti_test_evaluate (void *cls,
50 struct GNUNET_BLOCK_Context *ctx,
51 enum GNUNET_BLOCK_Type type,
52 struct GNUNET_BLOCK_Group *group,
53 enum GNUNET_BLOCK_EvaluationOptions eo,
54 const struct GNUNET_HashCode *query,
55 const void *xquery,
56 size_t xquery_size,
57 const void *reply_block,
58 size_t reply_block_size)
59{
60 if ((NULL == reply_block) ||
61 (reply_block_size == 0) ||
62 (0 != ((char *) reply_block)[0]))
63 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
64 return GNUNET_BLOCK_EVALUATION_OK_MORE;
65}
66
67
68/**
69 * Function called to validate a query. 33 * Function called to validate a query.
70 * 34 *
71 * @param cls closure 35 * @param cls closure
@@ -83,6 +47,16 @@ block_plugin_seti_test_check_query (void *cls,
83 const void *xquery, 47 const void *xquery,
84 size_t xquery_size) 48 size_t xquery_size)
85{ 49{
50 if (GNUNET_BLOCK_TYPE_SETI_TEST != type)
51 {
52 GNUNET_break (0);
53 return GNUNET_SYSERR;
54 }
55 if (0 != xquery_size)
56 {
57 GNUNET_break_op (0);
58 return GNUNET_NO;
59 }
86 return GNUNET_OK; 60 return GNUNET_OK;
87} 61}
88 62
@@ -92,7 +66,6 @@ block_plugin_seti_test_check_query (void *cls,
92 * 66 *
93 * @param cls closure 67 * @param cls closure
94 * @param type block type 68 * @param type block type
95 * @param query key for the block (hash), must match exactly
96 * @param block block data to validate 69 * @param block block data to validate
97 * @param block_size number of bytes in @a block 70 * @param block_size number of bytes in @a block
98 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 71 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
@@ -100,10 +73,15 @@ block_plugin_seti_test_check_query (void *cls,
100static enum GNUNET_GenericReturnValue 73static enum GNUNET_GenericReturnValue
101block_plugin_seti_test_check_block (void *cls, 74block_plugin_seti_test_check_block (void *cls,
102 enum GNUNET_BLOCK_Type type, 75 enum GNUNET_BLOCK_Type type,
103 const struct GNUNET_HashCode *query,
104 const void *block, 76 const void *block,
105 size_t block_size) 77 size_t block_size)
106{ 78{
79 (void) cls;
80 if (GNUNET_BLOCK_TYPE_SETI_TEST != type)
81 {
82 GNUNET_break (0);
83 return GNUNET_SYSERR;
84 }
107 if ((NULL == block) || 85 if ((NULL == block) ||
108 (0 == block_size) || 86 (0 == block_size) ||
109 (0 != ((char *) block)[0])) 87 (0 != ((char *) block)[0]))
@@ -138,10 +116,18 @@ block_plugin_seti_test_check_reply (void *cls,
138 const void *reply_block, 116 const void *reply_block,
139 size_t reply_block_size) 117 size_t reply_block_size)
140{ 118{
119 (void) cls;
120 (void) xquery;
121 (void) xquery_size;
122 if (GNUNET_BLOCK_TYPE_SETI_TEST != type)
123 {
124 GNUNET_break (0);
125 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
126 }
141 if ( (NULL == reply_block) || 127 if ( (NULL == reply_block) ||
142 (0 == reply_block_size) || 128 (0 == reply_block_size) ||
143 (0 != ((char *) reply_block)[0]) ) 129 (0 != ((char *) reply_block)[0]) )
144 return GNUNET_BLOCK_REPLY_INVALID; 130 GNUNET_assert (0);
145 return GNUNET_BLOCK_REPLY_OK_MORE; 131 return GNUNET_BLOCK_REPLY_OK_MORE;
146} 132}
147 133
@@ -164,7 +150,12 @@ block_plugin_seti_test_get_key (void *cls,
164 size_t block_size, 150 size_t block_size,
165 struct GNUNET_HashCode *key) 151 struct GNUNET_HashCode *key)
166{ 152{
167 return GNUNET_SYSERR; 153 if (GNUNET_BLOCK_TYPE_SETI_TEST != type)
154 {
155 GNUNET_break (0);
156 return GNUNET_SYSERR;
157 }
158 return GNUNET_NO;
168} 159}
169 160
170 161
@@ -181,7 +172,6 @@ libgnunet_plugin_block_seti_test_init (void *cls)
181 struct GNUNET_BLOCK_PluginFunctions *api; 172 struct GNUNET_BLOCK_PluginFunctions *api;
182 173
183 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 174 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
184 api->evaluate = &block_plugin_seti_test_evaluate;
185 api->get_key = &block_plugin_seti_test_get_key; 175 api->get_key = &block_plugin_seti_test_get_key;
186 api->check_query = &block_plugin_seti_test_check_query; 176 api->check_query = &block_plugin_seti_test_check_query;
187 api->check_block = &block_plugin_seti_test_check_block; 177 api->check_block = &block_plugin_seti_test_check_block;
diff --git a/src/setu/plugin_block_setu_test.c b/src/setu/plugin_block_setu_test.c
index 9872bba39..178ad3314 100644
--- a/src/setu/plugin_block_setu_test.c
+++ b/src/setu/plugin_block_setu_test.c
@@ -23,49 +23,12 @@
23 * @brief set test block, recognizes elements with non-zero first byte as invalid 23 * @brief set test block, recognizes elements with non-zero first byte as invalid
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26
27#include "platform.h" 26#include "platform.h"
28#include "gnunet_block_plugin.h" 27#include "gnunet_block_plugin.h"
29#include "gnunet_block_group_lib.h" 28#include "gnunet_block_group_lib.h"
30 29
31 30
32/** 31/**
33 * Function called to validate a reply or a request. For
34 * request evaluation, simply pass "NULL" for the reply_block.
35 *
36 * @param cls closure
37 * @param ctx block context
38 * @param type block type
39 * @param group block group to use
40 * @param eo control flags
41 * @param query original query (hash)
42 * @param xquery extrended query data (can be NULL, depending on type)
43 * @param xquery_size number of bytes in xquery
44 * @param reply_block response to validate
45 * @param reply_block_size number of bytes in reply block
46 * @return characterization of result
47 */
48static enum GNUNET_BLOCK_EvaluationResult
49block_plugin_setu_test_evaluate (void *cls,
50 struct GNUNET_BLOCK_Context *ctx,
51 enum GNUNET_BLOCK_Type type,
52 struct GNUNET_BLOCK_Group *group,
53 enum GNUNET_BLOCK_EvaluationOptions eo,
54 const struct GNUNET_HashCode *query,
55 const void *xquery,
56 size_t xquery_size,
57 const void *reply_block,
58 size_t reply_block_size)
59{
60 if ((NULL == reply_block) ||
61 (reply_block_size == 0) ||
62 (0 != ((char *) reply_block)[0]))
63 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
64 return GNUNET_BLOCK_EVALUATION_OK_MORE;
65}
66
67
68/**
69 * Function called to validate a query. 32 * Function called to validate a query.
70 * 33 *
71 * @param cls closure 34 * @param cls closure
@@ -83,6 +46,16 @@ block_plugin_setu_test_check_query (void *cls,
83 const void *xquery, 46 const void *xquery,
84 size_t xquery_size) 47 size_t xquery_size)
85{ 48{
49 if (GNUNET_BLOCK_TYPE_SETU_TEST != type)
50 {
51 GNUNET_break (0);
52 return GNUNET_SYSERR;
53 }
54 if (0 != xquery_size)
55 {
56 GNUNET_break_op (0);
57 return GNUNET_NO;
58 }
86 return GNUNET_OK; 59 return GNUNET_OK;
87} 60}
88 61
@@ -92,7 +65,6 @@ block_plugin_setu_test_check_query (void *cls,
92 * 65 *
93 * @param cls closure 66 * @param cls closure
94 * @param type block type 67 * @param type block type
95 * @param query key for the block (hash), must match exactly
96 * @param block block data to validate 68 * @param block block data to validate
97 * @param block_size number of bytes in @a block 69 * @param block_size number of bytes in @a block
98 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 70 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
@@ -100,14 +72,18 @@ block_plugin_setu_test_check_query (void *cls,
100static enum GNUNET_GenericReturnValue 72static enum GNUNET_GenericReturnValue
101block_plugin_setu_test_check_block (void *cls, 73block_plugin_setu_test_check_block (void *cls,
102 enum GNUNET_BLOCK_Type type, 74 enum GNUNET_BLOCK_Type type,
103 const struct GNUNET_HashCode *query,
104 const void *block, 75 const void *block,
105 size_t block_size) 76 size_t block_size)
106{ 77{
78 if (GNUNET_BLOCK_TYPE_SETU_TEST != type)
79 {
80 GNUNET_break (0);
81 return GNUNET_SYSERR;
82 }
107 if ( (NULL == block) || 83 if ( (NULL == block) ||
108 (0 == block_size) || 84 (0 == block_size) ||
109 (0 != ((char *) block)[0]) ) 85 (0 != ((char *) block)[0]) )
110 return GNUNET_SYSERR; 86 return GNUNET_NO;
111 return GNUNET_OK; 87 return GNUNET_OK;
112} 88}
113 89
@@ -138,10 +114,18 @@ block_plugin_setu_test_check_reply (void *cls,
138 const void *reply_block, 114 const void *reply_block,
139 size_t reply_block_size) 115 size_t reply_block_size)
140{ 116{
117 (void) cls;
118 (void) xquery;
119 (void) xquery_size;
120 if (GNUNET_BLOCK_TYPE_SETU_TEST != type)
121 {
122 GNUNET_break (0);
123 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
124 }
141 if ( (NULL == reply_block) || 125 if ( (NULL == reply_block) ||
142 (0 == reply_block_size) || 126 (0 == reply_block_size) ||
143 (0 != ((char *) reply_block)[0]) ) 127 (0 != ((char *) reply_block)[0]) )
144 return GNUNET_BLOCK_REPLY_INVALID; 128 GNUNET_assert (0);
145 return GNUNET_BLOCK_REPLY_OK_MORE; 129 return GNUNET_BLOCK_REPLY_OK_MORE;
146} 130}
147 131
@@ -164,7 +148,12 @@ block_plugin_setu_test_get_key (void *cls,
164 size_t block_size, 148 size_t block_size,
165 struct GNUNET_HashCode *key) 149 struct GNUNET_HashCode *key)
166{ 150{
167 return GNUNET_SYSERR; 151 if (GNUNET_BLOCK_TYPE_SETU_TEST != type)
152 {
153 GNUNET_break (0);
154 return GNUNET_SYSERR;
155 }
156 return GNUNET_NO;
168} 157}
169 158
170 159
@@ -175,13 +164,12 @@ void *
175libgnunet_plugin_block_setu_test_init (void *cls) 164libgnunet_plugin_block_setu_test_init (void *cls)
176{ 165{
177 static enum GNUNET_BLOCK_Type types[] = { 166 static enum GNUNET_BLOCK_Type types[] = {
178 GNUNET_BLOCK_TYPE_SETU_TEST, 167 GNUNET_BLOCK_TYPE_SETU_TEST,
179 GNUNET_BLOCK_TYPE_ANY /* end of list */ 168 GNUNET_BLOCK_TYPE_ANY /* end of list */
180 }; 169 };
181 struct GNUNET_BLOCK_PluginFunctions *api; 170 struct GNUNET_BLOCK_PluginFunctions *api;
182 171
183 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 172 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
184 api->evaluate = &block_plugin_setu_test_evaluate;
185 api->get_key = &block_plugin_setu_test_get_key; 173 api->get_key = &block_plugin_setu_test_get_key;
186 api->check_query = &block_plugin_setu_test_check_query; 174 api->check_query = &block_plugin_setu_test_check_query;
187 api->check_block = &block_plugin_setu_test_check_block; 175 api->check_block = &block_plugin_setu_test_check_block;
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index ec00bc917..69b05fb13 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -773,6 +773,8 @@ TESTS += \
773endif 773endif
774endif 774endif
775 775
776# Only test TNG if we run experimental
777if HAVE_EXPERIMENTAL
776check_SCRIPTS= \ 778check_SCRIPTS= \
777 test_transport_simple_send_string.sh \ 779 test_transport_simple_send_string.sh \
778 test_transport_simple_send.sh \ 780 test_transport_simple_send.sh \
@@ -780,6 +782,7 @@ check_SCRIPTS= \
780 test_transport_udp_backchannel.sh \ 782 test_transport_udp_backchannel.sh \
781 test_transport_simple_send_dv_circle.sh 783 test_transport_simple_send_dv_circle.sh
782 # test_transport_simple_send_dv_inverse.sh 784 # test_transport_simple_send_dv_inverse.sh
785endif
783 786
784test_transport_start_with_config_SOURCES = \ 787test_transport_start_with_config_SOURCES = \
785 test_transport_start_with_config.c 788 test_transport_start_with_config.c
@@ -1521,7 +1524,10 @@ test_transport_api_slow_ats_LDADD = \
1521 1524
1522 1525
1523EXTRA_DIST = \ 1526EXTRA_DIST = \
1524$(check_SCRIPTS) \ 1527test_transport_simple_send_string.sh \
1528test_transport_simple_send.sh \
1529test_transport_simple_send_broadcast.sh \
1530test_transport_udp_backchannel.sh \
1525gnunet-transport-certificate-creation.in \ 1531gnunet-transport-certificate-creation.in \
1526communicator-unix.conf \ 1532communicator-unix.conf \
1527test_plugin_hostkey \ 1533test_plugin_hostkey \
diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c
index 3bfdeaa90..be75fa0e8 100644
--- a/src/transport/gnunet-communicator-tcp.c
+++ b/src/transport/gnunet-communicator-tcp.c
@@ -143,7 +143,7 @@ struct TcpHandshakeSignature
143 /** 143 /**
144 * Challenge value used to protect against replay attack, if there is no stored monotonic time value. 144 * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
145 */ 145 */
146 struct ChallengeNonceP challenge; 146 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
147}; 147};
148 148
149/** 149/**
@@ -176,7 +176,7 @@ struct TcpHandshakeAckSignature
176 /** 176 /**
177 * Challenge value used to protect against replay attack, if there is no stored monotonic time value. 177 * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
178 */ 178 */
179 struct ChallengeNonceP challenge; 179 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
180}; 180};
181 181
182/** 182/**
@@ -203,7 +203,7 @@ struct TCPConfirmation
203 /** 203 /**
204 * Challenge value used to protect against replay attack, if there is no stored monotonic time value. 204 * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
205 */ 205 */
206 struct ChallengeNonceP challenge; 206 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
207 207
208}; 208};
209 209
@@ -238,7 +238,7 @@ struct TCPConfirmationAck
238 /** 238 /**
239 * Challenge value used to protect against replay attack, if there is no stored monotonic time value. 239 * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
240 */ 240 */
241 struct ChallengeNonceP challenge; 241 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
242 242
243}; 243};
244 244
@@ -587,12 +587,12 @@ struct Queue
587 /** 587 /**
588 * Challenge value used to protect against replay attack, if there is no stored monotonic time value. 588 * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
589 */ 589 */
590 struct ChallengeNonceP challenge; 590 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
591 591
592 /** 592 /**
593 * Challenge value received. In case of inbound connection we have to remember the value, because we send the challenge back later after we received the GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK. 593 * Challenge value received. In case of inbound connection we have to remember the value, because we send the challenge back later after we received the GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK.
594 */ 594 */
595 struct ChallengeNonceP challenge_received; 595 struct GNUNET_CRYPTO_ChallengeNonceP challenge_received;
596 596
597 /** 597 /**
598 * Iteration Context for retrieving the monotonic time send with key for rekeying. 598 * Iteration Context for retrieving the monotonic time send with key for rekeying.
@@ -1447,7 +1447,7 @@ handshake_ack_monotime_cb (void *cls,
1447 * @param queue The queue context. 1447 * @param queue The queue context.
1448 */ 1448 */
1449static void 1449static void
1450send_challenge (struct ChallengeNonceP challenge, struct Queue *queue) 1450send_challenge (struct GNUNET_CRYPTO_ChallengeNonceP challenge, struct Queue *queue)
1451{ 1451{
1452 struct TCPConfirmationAck tca; 1452 struct TCPConfirmationAck tca;
1453 struct TcpHandshakeAckSignature thas; 1453 struct TcpHandshakeAckSignature thas;
@@ -1680,7 +1680,7 @@ try_handle_plaintext (struct Queue *queue)
1680 uint16_t type; 1680 uint16_t type;
1681 size_t size = 0; /* make compiler happy */ 1681 size_t size = 0; /* make compiler happy */
1682 struct TcpHandshakeAckSignature thas; 1682 struct TcpHandshakeAckSignature thas;
1683 const struct ChallengeNonceP challenge = queue->challenge; 1683 const struct GNUNET_CRYPTO_ChallengeNonceP challenge = queue->challenge;
1684 1684
1685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1686 "try handle plaintext!\n"); 1686 "try handle plaintext!\n");
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
index 0427bd229..21c9be05c 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -581,7 +581,7 @@ struct DvInitPS
581 /** 581 /**
582 * Challenge value used by the initiator to re-identify the path. 582 * Challenge value used by the initiator to re-identify the path.
583 */ 583 */
584 struct ChallengeNonceP challenge; 584 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
585}; 585};
586 586
587 587
@@ -621,7 +621,7 @@ struct DvHopPS
621 /** 621 /**
622 * Challenge value used by the initiator to re-identify the path. 622 * Challenge value used by the initiator to re-identify the path.
623 */ 623 */
624 struct ChallengeNonceP challenge; 624 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
625}; 625};
626 626
627 627
@@ -715,7 +715,7 @@ struct TransportDVLearnMessage
715 /** 715 /**
716 * Challenge value used by the initiator to re-identify the path. 716 * Challenge value used by the initiator to re-identify the path.
717 */ 717 */
718 struct ChallengeNonceP challenge; 718 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
719 719
720 /* Followed by @e num_hops `struct DVPathEntryP` values, 720 /* Followed by @e num_hops `struct DVPathEntryP` values,
721 excluding the initiator of the DV trace; the last entry is the 721 excluding the initiator of the DV trace; the last entry is the
@@ -834,7 +834,7 @@ struct TransportValidationChallengeMessage
834 /** 834 /**
835 * Challenge to be signed by the receiving peer. 835 * Challenge to be signed by the receiving peer.
836 */ 836 */
837 struct ChallengeNonceP challenge; 837 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
838 838
839 /** 839 /**
840 * Timestamp of the sender, to be copied into the reply to allow 840 * Timestamp of the sender, to be copied into the reply to allow
@@ -864,7 +864,7 @@ struct TransportValidationPS
864 /** 864 /**
865 * Challenge signed by the receiving peer. 865 * Challenge signed by the receiving peer.
866 */ 866 */
867 struct ChallengeNonceP challenge; 867 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
868}; 868};
869 869
870 870
@@ -893,7 +893,7 @@ struct TransportValidationResponseMessage
893 /** 893 /**
894 * The challenge that was signed by the receiving peer. 894 * The challenge that was signed by the receiving peer.
895 */ 895 */
896 struct ChallengeNonceP challenge; 896 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
897 897
898 /** 898 /**
899 * Original timestamp of the sender (was @code{sender_time}), 899 * Original timestamp of the sender (was @code{sender_time}),
@@ -1056,7 +1056,7 @@ struct LearnLaunchEntry
1056 /** 1056 /**
1057 * Challenge that uniquely identifies this activity. 1057 * Challenge that uniquely identifies this activity.
1058 */ 1058 */
1059 struct ChallengeNonceP challenge; 1059 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
1060 1060
1061 /** 1061 /**
1062 * When did we transmit the DV learn message (used to calculate RTT) and 1062 * When did we transmit the DV learn message (used to calculate RTT) and
@@ -2569,7 +2569,7 @@ struct ValidationState
2569 * (We must not rotate more often as otherwise we may discard valid answers 2569 * (We must not rotate more often as otherwise we may discard valid answers
2570 * due to packet losses, latency and reorderings on the network). 2570 * due to packet losses, latency and reorderings on the network).
2571 */ 2571 */
2572 struct ChallengeNonceP challenge; 2572 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
2573 2573
2574 /** 2574 /**
2575 * Claimed address of the peer. 2575 * Claimed address of the peer.
@@ -6886,7 +6886,7 @@ static int
6886validate_dv_initiator_signature ( 6886validate_dv_initiator_signature (
6887 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time, 6887 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
6888 const struct GNUNET_PeerIdentity *init, 6888 const struct GNUNET_PeerIdentity *init,
6889 const struct ChallengeNonceP *challenge, 6889 const struct GNUNET_CRYPTO_ChallengeNonceP *challenge,
6890 const struct GNUNET_CRYPTO_EddsaSignature *init_sig) 6890 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
6891{ 6891{
6892 struct DvInitPS ip = { .purpose.purpose = htonl ( 6892 struct DvInitPS ip = { .purpose.purpose = htonl (
@@ -8340,7 +8340,7 @@ struct CheckKnownChallengeContext
8340 /** 8340 /**
8341 * Set to the challenge we are looking for. 8341 * Set to the challenge we are looking for.
8342 */ 8342 */
8343 const struct ChallengeNonceP *challenge; 8343 const struct GNUNET_CRYPTO_ChallengeNonceP *challenge;
8344 8344
8345 /** 8345 /**
8346 * Set to a matching validation state, if one was found. 8346 * Set to a matching validation state, if one was found.
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index 24cc6464a..fad2ca4a1 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -1628,8 +1628,8 @@ GST_receive_callback (void *cls,
1628 GST_neighbours_notify_data_recv (address, message); 1628 GST_neighbours_notify_data_recv (address, message);
1629 switch (type) 1629 switch (type)
1630 { 1630 {
1631 case GNUNET_MESSAGE_TYPE_HELLO_LEGACY: 1631 case GNUNET_MESSAGE_TYPE_HELLO_URI:
1632 /* Legacy HELLO message, discard */ 1632 /* Future HELLO message, discard */
1633 return ret; 1633 return ret;
1634 1634
1635 case GNUNET_MESSAGE_TYPE_HELLO: 1635 case GNUNET_MESSAGE_TYPE_HELLO:
diff --git a/src/transport/test_transport_simple_send.sh b/src/transport/test_transport_simple_send.sh
index 3d5266622..0250070be 100755
--- a/src/transport/test_transport_simple_send.sh
+++ b/src/transport/test_transport_simple_send.sh
@@ -2,9 +2,10 @@
2if ! [ -d "/run/netns" ]; then 2if ! [ -d "/run/netns" ]; then
3 echo You have to create the directory /run/netns. 3 echo You have to create the directory /run/netns.
4fi 4fi
5if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" == 1 ]; then 5if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
6 exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_simple_send_topo.conf" 6 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
7else
8 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n" 7 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
9 exit 78 8 exit 78
9 fi
10fi 10fi
11exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_simple_send_topo.conf"
diff --git a/src/transport/test_transport_simple_send_broadcast.sh b/src/transport/test_transport_simple_send_broadcast.sh
index f264b1203..a4801bf70 100755
--- a/src/transport/test_transport_simple_send_broadcast.sh
+++ b/src/transport/test_transport_simple_send_broadcast.sh
@@ -2,10 +2,10 @@
2if ! [ -d "/run/netns" ]; then 2if ! [ -d "/run/netns" ]; then
3 echo You have to create the directory /run/netns. 3 echo You have to create the directory /run/netns.
4fi 4fi
5if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" == 1 ]; then 5if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
6 # exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; valgrind --leak-check=full --track-origins=yes --trace-children=yes --trace-children-skip=/usr/bin/awk,/usr/bin/cut,/usr/bin/seq,/sbin/ip/sed/bash ./test_transport_start_with_config test_transport_simple_send_broadcast_topo.conf" 6 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
7 exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_simple_send_broadcast_topo.conf"
8else
9 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n" 7 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
10 exit 78 8 exit 78
9 fi
11fi 10fi
11exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_simple_send_broadcast_topo.conf"
diff --git a/src/transport/test_transport_simple_send_dv.sh b/src/transport/test_transport_simple_send_dv.sh
index fa127cfa4..b57ee0629 100755
--- a/src/transport/test_transport_simple_send_dv.sh
+++ b/src/transport/test_transport_simple_send_dv.sh
@@ -2,10 +2,10 @@
2if ! [ -d "/run/netns" ]; then 2if ! [ -d "/run/netns" ]; then
3 echo You have to create the directory /run/netns. 3 echo You have to create the directory /run/netns.
4fi 4fi
5if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" == 1 ]; then 5if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
6 # exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; valgrind --leak-check=full --track-origins=yes --trace-children=yes --trace-children-skip=/usr/bin/awk,/usr/bin/cut,/usr/bin/seq,/sbin/ip/sed/bash ./test_transport_start_with_config test_transport_distance_vector_topo.conf" 6 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
7 exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_distance_vector_topo.conf"
8else
9 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n" 7 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
10 exit 78 8 exit 78
9 fi
11fi 10fi
11exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_distance_vector_topo.conf"
diff --git a/src/transport/test_transport_simple_send_dv_circle.sh b/src/transport/test_transport_simple_send_dv_circle.sh
index de16df356..bd5f00abe 100755
--- a/src/transport/test_transport_simple_send_dv_circle.sh
+++ b/src/transport/test_transport_simple_send_dv_circle.sh
@@ -2,11 +2,10 @@
2if ! [ -d "/run/netns" ]; then 2if ! [ -d "/run/netns" ]; then
3 echo You have to create the directory /run/netns. 3 echo You have to create the directory /run/netns.
4fi 4fi
5if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" == 1 ]; then 5if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
6 # exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; valgrind --leak-check=full --track-origins=yes --trace-children=yes --trace-children-skip=/usr/bin/awk,/usr/bin/cut,/usr/bin/seq,/sbin/ip/sed/bash ./test_transport_start_with_config test_transport_distance_vector_topo.conf" 6 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
7 exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_distance_vector_circle_topo.conf"
8 #./test_transport_start_with_config test_transport_distance_vector_circle_topo.conf
9else
10 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n" 7 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
11 exit 78 8 exit 78
9 fi
12fi 10fi
11exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_distance_vector_circle_topo.conf"
diff --git a/src/transport/test_transport_simple_send_string.sh b/src/transport/test_transport_simple_send_string.sh
index b2bd05d5f..211abb494 100755
--- a/src/transport/test_transport_simple_send_string.sh
+++ b/src/transport/test_transport_simple_send_string.sh
@@ -11,9 +11,11 @@ EOF
11if ! [ -d "/run/netns" ]; then 11if ! [ -d "/run/netns" ]; then
12 echo You have to create the directory /run/netns. 12 echo You have to create the directory /run/netns.
13fi 13fi
14if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" == 1 ]; then 14if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
15 exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config -s '$string'" 15 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
16else
17 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n" 16 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
18 exit 78 17 exit 78
18 fi
19fi 19fi
20
21exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config -s '$string'"
diff --git a/src/transport/test_transport_udp_backchannel.sh b/src/transport/test_transport_udp_backchannel.sh
index c52734a55..1a7c83385 100755
--- a/src/transport/test_transport_udp_backchannel.sh
+++ b/src/transport/test_transport_udp_backchannel.sh
@@ -5,11 +5,10 @@ fi
5if ! [ -d "/run/netns" ]; then 5if ! [ -d "/run/netns" ]; then
6 echo You have to create the directory /run/netns. 6 echo You have to create the directory /run/netns.
7fi 7fi
8if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" == 1 ]; then 8if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
9#exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; valgrind --leak-check=full --track-origins=yes --trace-children=yes --trace-children-skip=/usr/bin/awk,/usr/bin/cut,/usr/bin/seq,/sbin/ip ./test_transport_start_with_config test_transport_udp_backchannel_topo.conf" 9 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
10exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; GNUNET_FORCE_LOG=';;;;DEBUG' GNUNET_FORCE_LOGFILE='test.out' ./test_transport_start_with_config test_transport_udp_backchannel_topo.conf"
11# exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; valgrind --leak-check=full --track-origins=yes ./test_transport_start_with_config test_transport_udp_backchannel_topo.conf"
12else
13 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n" 10 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
14 exit 78 11 exit 78
12 fi
15fi 13fi
14exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; GNUNET_FORCE_LOG=';;;;DEBUG' GNUNET_FORCE_LOGFILE='test.out' ./test_transport_start_with_config test_transport_udp_backchannel_topo.conf"
diff --git a/src/util/common_logging.c b/src/util/common_logging.c
index cba37cd2f..b07f3fc0b 100644
--- a/src/util/common_logging.c
+++ b/src/util/common_logging.c
@@ -321,6 +321,28 @@ log_rotate (const char *new_name)
321} 321}
322 322
323 323
324const char *
325GNUNET_b2s (const void *buf,
326 size_t buf_size)
327{
328 static GNUNET_THREAD_LOCAL char ret[9];
329 struct GNUNET_HashCode hc;
330 char *tmp;
331
332 GNUNET_CRYPTO_hash (buf,
333 buf_size,
334 &hc);
335 tmp = GNUNET_STRINGS_data_to_string_alloc (&hc,
336 sizeof (hc));
337 memcpy (ret,
338 tmp,
339 8);
340 GNUNET_free (tmp);
341 ret[8] = '\0';
342 return ret;
343}
344
345
324/** 346/**
325 * Setup the log file. 347 * Setup the log file.
326 * 348 *
@@ -1015,7 +1037,8 @@ mylog (enum GNUNET_ErrorType kind,
1015 else 1037 else
1016 { 1038 {
1017 /* RFC 3339 timestamp, with snprintf placeholder for microseconds */ 1039 /* RFC 3339 timestamp, with snprintf placeholder for microseconds */
1018 if (0 == strftime (date2, DATE_STR_SIZE, "%Y-%m-%dT%H:%M:%S.%%06u%z", tmptr)) 1040 if (0 == strftime (date2, DATE_STR_SIZE, "%Y-%m-%dT%H:%M:%S.%%06u%z",
1041 tmptr))
1019 abort (); 1042 abort ();
1020 /* Fill in microseconds */ 1043 /* Fill in microseconds */
1021 if (0 > snprintf (date, sizeof(date), date2, timeofday.tv_usec)) 1044 if (0 > snprintf (date, sizeof(date), date2, timeofday.tv_usec))
diff --git a/src/util/crypto_cs.c b/src/util/crypto_cs.c
index c89ba5d83..4c6648229 100644
--- a/src/util/crypto_cs.c
+++ b/src/util/crypto_cs.c
@@ -40,11 +40,6 @@
40 */ 40 */
41 41
42 42
43/**
44 * Create a new random private key.
45 *
46 * @param[out] priv where to write the fresh private key
47 */
48void 43void
49GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv) 44GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv)
50{ 45{
@@ -52,16 +47,10 @@ GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv)
52} 47}
53 48
54 49
55/**
56 * Extract the public key of the given private key.
57 *
58 * @param priv the private key
59 * @param[out] pub where to write the public key
60 */
61void 50void
62GNUNET_CRYPTO_cs_private_key_get_public (const struct 51GNUNET_CRYPTO_cs_private_key_get_public (
63 GNUNET_CRYPTO_CsPrivateKey *priv, 52 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
64 struct GNUNET_CRYPTO_CsPublicKey *pub) 53 struct GNUNET_CRYPTO_CsPublicKey *pub)
65{ 54{
66 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (pub->point.y, 55 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (pub->point.y,
67 priv->scalar.d)); 56 priv->scalar.d));
@@ -69,63 +58,40 @@ GNUNET_CRYPTO_cs_private_key_get_public (const struct
69 58
70 59
71/** 60/**
72 * maps 32 random bytes to a scalar 61 * Maps 32 random bytes to a scalar. This is necessary because libsodium
73 * this is necessary because libsodium expects scalar to be in the prime order subgroup 62 * expects scalar to be in the prime order subgroup.
74 * @param[out] scalar containing 32 byte char array, is modified to be in prime order subgroup 63 *
64 * @param[in,out] scalar containing 32 byte char array, is modified to be in prime order subgroup
75 */ 65 */
76static void 66static void
77map_to_scalar_subgroup (struct GNUNET_CRYPTO_Cs25519Scalar *scalar) 67map_to_scalar_subgroup (struct GNUNET_CRYPTO_Cs25519Scalar *scalar)
78{ 68{
79 // perform clamping as described in RFC7748 69 /* perform clamping as described in RFC7748 */
80 scalar->d[0] &= 248; 70 scalar->d[0] &= 248;
81 scalar->d[31] &= 127; 71 scalar->d[31] &= 127;
82 scalar->d[31] |= 64; 72 scalar->d[31] |= 64;
83} 73}
84 74
85 75
86/**
87 * Derive a new secret r pair r0 and r1.
88 * In original papers r is generated randomly
89 * To provide abort-idempotency, r needs to be derived but still needs to be UNPREDICTABLE
90 * To ensure unpredictability a new nonce should be used when a new r needs to be derived.
91 * Uses HKDF internally.
92 * Comment: Can be done in one HKDF shot and split output.
93 *
94 * @param nonce is a random nonce
95 * @param lts is a long-term-secret in form of a private key
96 * @param[out] r array containing derived secrets r0 and r1
97 */
98void 76void
99GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce, 77GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce,
78 const char *seed,
100 const struct GNUNET_CRYPTO_CsPrivateKey *lts, 79 const struct GNUNET_CRYPTO_CsPrivateKey *lts,
101 struct GNUNET_CRYPTO_CsRSecret r[2]) 80 struct GNUNET_CRYPTO_CsRSecret r[2])
102{ 81{
103 GNUNET_assert (GNUNET_YES == 82 GNUNET_assert (
104 GNUNET_CRYPTO_hkdf (r, 83 GNUNET_YES ==
105 sizeof (struct GNUNET_CRYPTO_CsRSecret) 84 GNUNET_CRYPTO_kdf (
106 * 2, 85 r, sizeof (struct GNUNET_CRYPTO_CsRSecret) * 2,
107 GCRY_MD_SHA512, 86 seed, strlen (seed),
108 GCRY_MD_SHA256, 87 lts, sizeof (*lts),
109 "r", 88 nonce, sizeof (*nonce),
110 strlen ("r"), 89 NULL, 0));
111 lts,
112 sizeof (*lts),
113 nonce,
114 sizeof (*nonce),
115 NULL,
116 0));
117
118 map_to_scalar_subgroup (&r[0].scalar); 90 map_to_scalar_subgroup (&r[0].scalar);
119 map_to_scalar_subgroup (&r[1].scalar); 91 map_to_scalar_subgroup (&r[1].scalar);
120} 92}
121 93
122 94
123/**
124 * Extract the public R of the given secret r.
125 *
126 * @param r_priv the private key
127 * @param[out] r_pub where to write the public key
128 */
129void 95void
130GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv, 96GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
131 struct GNUNET_CRYPTO_CsRPublic *r_pub) 97 struct GNUNET_CRYPTO_CsRPublic *r_pub)
@@ -135,36 +101,23 @@ GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
135} 101}
136 102
137 103
138/**
139 * Derives new random blinding factors.
140 * In original papers blinding factors are generated randomly
141 * To provide abort-idempotency, blinding factors need to be derived but still need to be UNPREDICTABLE
142 * To ensure unpredictability a new nonce has to be used.
143 * Uses HKDF internally
144 *
145 * @param secret is secret to derive blinding factors
146 * @param secret_len secret length
147 * @param[out] bs array containing the two derived blinding secrets
148 */
149void 104void
150GNUNET_CRYPTO_cs_blinding_secrets_derive (const struct 105GNUNET_CRYPTO_cs_blinding_secrets_derive (
151 GNUNET_CRYPTO_CsNonce *blind_seed, 106 const struct GNUNET_CRYPTO_CsNonce *blind_seed,
152 struct GNUNET_CRYPTO_CsBlindingSecret 107 struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
153 bs[2])
154{ 108{
155 GNUNET_assert (GNUNET_YES == 109 GNUNET_assert (
156 GNUNET_CRYPTO_hkdf (bs, 110 GNUNET_YES ==
157 sizeof (struct 111 GNUNET_CRYPTO_hkdf (bs,
158 GNUNET_CRYPTO_CsBlindingSecret) 112 sizeof (struct GNUNET_CRYPTO_CsBlindingSecret) * 2,
159 * 2, 113 GCRY_MD_SHA512,
160 GCRY_MD_SHA512, 114 GCRY_MD_SHA256,
161 GCRY_MD_SHA256, 115 "alphabeta",
162 "alphabeta", 116 strlen ("alphabeta"),
163 strlen ("alphabeta"), 117 blind_seed,
164 blind_seed, 118 sizeof(*blind_seed),
165 sizeof(*blind_seed), 119 NULL,
166 NULL, 120 0));
167 0));
168 map_to_scalar_subgroup (&bs[0].alpha); 121 map_to_scalar_subgroup (&bs[0].alpha);
169 map_to_scalar_subgroup (&bs[0].beta); 122 map_to_scalar_subgroup (&bs[0].beta);
170 map_to_scalar_subgroup (&bs[1].alpha); 123 map_to_scalar_subgroup (&bs[1].alpha);
@@ -205,11 +158,16 @@ cs_full_domain_hash (const struct GNUNET_CRYPTO_CsRPublic *r_dash,
205 memcpy (r_m_concat, r_dash, sizeof(struct GNUNET_CRYPTO_CsRPublic)); 158 memcpy (r_m_concat, r_dash, sizeof(struct GNUNET_CRYPTO_CsRPublic));
206 memcpy (r_m_concat + sizeof(struct GNUNET_CRYPTO_CsRPublic), msg, msg_len); 159 memcpy (r_m_concat + sizeof(struct GNUNET_CRYPTO_CsRPublic), msg, msg_len);
207 struct GNUNET_HashCode prehash; 160 struct GNUNET_HashCode prehash;
208 GNUNET_CRYPTO_hash (r_m_concat, r_m_concat_len, &prehash); 161
162 GNUNET_CRYPTO_hash (r_m_concat,
163 r_m_concat_len,
164 &prehash);
209 165
210 // modulus converted to MPI representation 166 // modulus converted to MPI representation
211 gcry_mpi_t l_mpi; 167 gcry_mpi_t l_mpi;
212 GNUNET_CRYPTO_mpi_scan_unsigned (&l_mpi, L_BIG_ENDIAN, sizeof(L_BIG_ENDIAN)); 168 GNUNET_CRYPTO_mpi_scan_unsigned (&l_mpi,
169 L_BIG_ENDIAN,
170 sizeof(L_BIG_ENDIAN));
213 171
214 // calculate full domain hash 172 // calculate full domain hash
215 gcry_mpi_t c_mpi; 173 gcry_mpi_t c_mpi;
@@ -224,7 +182,9 @@ cs_full_domain_hash (const struct GNUNET_CRYPTO_CsRPublic *r_dash,
224 182
225 // convert c from mpi 183 // convert c from mpi
226 unsigned char c_big_endian[256 / 8]; 184 unsigned char c_big_endian[256 / 8];
227 GNUNET_CRYPTO_mpi_print_unsigned (c_big_endian, sizeof(c_big_endian), c_mpi); 185 GNUNET_CRYPTO_mpi_print_unsigned (c_big_endian,
186 sizeof(c_big_endian),
187 c_mpi);
228 gcry_mpi_release (c_mpi); 188 gcry_mpi_release (c_mpi);
229 for (size_t i = 0; i<32; i++) 189 for (size_t i = 0; i<32; i++)
230 c->scalar.d[i] = c_big_endian[31 - i]; 190 c->scalar.d[i] = c_big_endian[31 - i];
@@ -266,28 +226,15 @@ calc_r_dash (const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
266} 226}
267 227
268 228
269/**
270 * Calculate two blinded c's
271 * Comment: One would be insecure due to Wagner's algorithm solving ROS
272 *
273 * @param bs array of the two blinding factor structs each containing alpha and beta
274 * @param r_pub array of the two signer's nonce R
275 * @param pub the public key of the signer
276 * @param msg the message to blind in preparation for signing
277 * @param msg_len length of message msg
278 * @param[out] blinded_c array of the two blinded c's
279 * @param[out] blinded_r_pub array of the two blinded R
280 */
281void 229void
282GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret 230GNUNET_CRYPTO_cs_calc_blinded_c (
283 bs[2], 231 const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
284 const struct GNUNET_CRYPTO_CsRPublic r_pub[2], 232 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
285 const struct GNUNET_CRYPTO_CsPublicKey *pub, 233 const struct GNUNET_CRYPTO_CsPublicKey *pub,
286 const void *msg, 234 const void *msg,
287 size_t msg_len, 235 size_t msg_len,
288 struct GNUNET_CRYPTO_CsC blinded_c[2], 236 struct GNUNET_CRYPTO_CsC blinded_c[2],
289 struct GNUNET_CRYPTO_CsRPublic 237 struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2])
290 blinded_r_pub[2])
291{ 238{
292 // for i 0/1: R'i = Ri + alpha i*G + beta i*pub 239 // for i 0/1: R'i = Ri + alpha i*G + beta i*pub
293 calc_r_dash (&bs[0], &r_pub[0], pub, &blinded_r_pub[0]); 240 calc_r_dash (&bs[0], &r_pub[0], pub, &blinded_r_pub[0]);
@@ -309,30 +256,13 @@ GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret
309} 256}
310 257
311 258
312/**
313 * Sign a blinded c
314 * This function derives b from a nonce and a longterm secret
315 * In original papers b is generated randomly
316 * To provide abort-idempotency, b needs to be derived but still need to be UNPREDICTABLE.
317 * To ensure unpredictability a new nonce has to be used for every signature
318 * HKDF is used internally for derivation
319 * r0 and r1 can be derived prior by using GNUNET_CRYPTO_cs_r_derive
320 *
321 * @param priv private key to use for the signing and as LTS in HKDF
322 * @param r array of the two secret nonce from the signer
323 * @param c array of the two blinded c to sign c_b
324 * @param nonce is a random nonce
325 * @param[out] blinded_signature_scalar where to write the signature
326 * @return 0 or 1 for b (see Clause Blind Signature Scheme)
327 */
328unsigned int 259unsigned int
329GNUNET_CRYPTO_cs_sign_derive (const struct GNUNET_CRYPTO_CsPrivateKey *priv, 260GNUNET_CRYPTO_cs_sign_derive (
330 const struct GNUNET_CRYPTO_CsRSecret r[2], 261 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
331 const struct GNUNET_CRYPTO_CsC c[2], 262 const struct GNUNET_CRYPTO_CsRSecret r[2],
332 const struct GNUNET_CRYPTO_CsNonce *nonce, 263 const struct GNUNET_CRYPTO_CsC c[2],
333 struct GNUNET_CRYPTO_CsBlindS * 264 const struct GNUNET_CRYPTO_CsNonce *nonce,
334 blinded_signature_scalar 265 struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar)
335 )
336{ 266{
337 uint32_t hkdf_out; 267 uint32_t hkdf_out;
338 268
@@ -365,18 +295,11 @@ GNUNET_CRYPTO_cs_sign_derive (const struct GNUNET_CRYPTO_CsPrivateKey *priv,
365} 295}
366 296
367 297
368/**
369 * Unblind a blind-signed signature using a c that was blinded
370 *
371 * @param blinded_signature_scalar the signature made on the blinded c
372 * @param bs the blinding factors used in the blinding
373 * @param[out] signature_scalar where to write the unblinded signature
374 */
375void 298void
376GNUNET_CRYPTO_cs_unblind (const struct 299GNUNET_CRYPTO_cs_unblind (
377 GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar, 300 const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
378 const struct GNUNET_CRYPTO_CsBlindingSecret *bs, 301 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
379 struct GNUNET_CRYPTO_CsS *signature_scalar) 302 struct GNUNET_CRYPTO_CsS *signature_scalar)
380{ 303{
381 crypto_core_ed25519_scalar_add (signature_scalar->scalar.d, 304 crypto_core_ed25519_scalar_add (signature_scalar->scalar.d,
382 blinded_signature_scalar->scalar.d, 305 blinded_signature_scalar->scalar.d,
@@ -384,16 +307,6 @@ GNUNET_CRYPTO_cs_unblind (const struct
384} 307}
385 308
386 309
387/**
388 * Verify whether the given message corresponds to the given signature and the
389 * signature is valid with respect to the given public key.
390 *
391 * @param sig signature that is being validated
392 * @param pub public key of the signer
393 * @param msg is the message that should be signed by @a sig (message is used to calculate c)
394 * @param msg_len is the message length
395 * @returns #GNUNET_YES on success, #GNUNET_SYSERR if signature invalid
396 */
397enum GNUNET_GenericReturnValue 310enum GNUNET_GenericReturnValue
398GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig, 311GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
399 const struct GNUNET_CRYPTO_CsPublicKey *pub, 312 const struct GNUNET_CRYPTO_CsPublicKey *pub,
@@ -402,7 +315,12 @@ GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
402{ 315{
403 // calculate c' = H(R, m) 316 // calculate c' = H(R, m)
404 struct GNUNET_CRYPTO_CsC c_dash; 317 struct GNUNET_CRYPTO_CsC c_dash;
405 cs_full_domain_hash (&sig->r_point, msg, msg_len, pub, &c_dash); 318
319 cs_full_domain_hash (&sig->r_point,
320 msg,
321 msg_len,
322 pub,
323 &c_dash);
406 324
407 // s'G ?= R' + c' pub 325 // s'G ?= R' + c' pub
408 struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base; 326 struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;
diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c
index dcd46e5f9..f516f5474 100644
--- a/src/util/crypto_hash.c
+++ b/src/util/crypto_hash.c
@@ -76,7 +76,8 @@ GNUNET_CRYPTO_hash_from_string2 (const char *enc,
76 char upper_enc[enclen]; 76 char upper_enc[enclen];
77 char *up_ptr = upper_enc; 77 char *up_ptr = upper_enc;
78 78
79 GNUNET_STRINGS_utf8_toupper (enc, up_ptr); 79 if (GNUNET_OK != GNUNET_STRINGS_utf8_toupper (enc, up_ptr))
80 return GNUNET_SYSERR;
80 81
81 return GNUNET_STRINGS_string_to_data (upper_enc, enclen, 82 return GNUNET_STRINGS_string_to_data (upper_enc, enclen,
82 (unsigned char *) result, 83 (unsigned char *) result,
diff --git a/src/util/dnsstub.c b/src/util/dnsstub.c
index 1ac274c92..c2f2a441f 100644
--- a/src/util/dnsstub.c
+++ b/src/util/dnsstub.c
@@ -324,24 +324,50 @@ do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
324 found = GNUNET_NO; 324 found = GNUNET_NO;
325 for (struct DnsServer *ds = ctx->dns_head; NULL != ds; ds = ds->next) 325 for (struct DnsServer *ds = ctx->dns_head; NULL != ds; ds = ds->next)
326 { 326 {
327 if (0 == memcmp (&addr, 327 if (ds->ss.ss_family != addr.ss_family)
328 &ds->ss, 328 continue;
329 GNUNET_MIN (sizeof(struct sockaddr_storage), addrlen))) 329 if (addr.ss_family == AF_INET)
330 { 330 {
331 found = GNUNET_YES; 331 struct sockaddr_in *v4 = (struct sockaddr_in *) &addr;
332 break; 332 struct sockaddr_in *ds_v4 = (struct sockaddr_in *) &ds->ss;
333
334
335 if ((0 == memcmp (&v4->sin_addr,
336 &ds_v4->sin_addr,
337 sizeof(struct sockaddr_in))) &&
338 (v4->sin_port == ds_v4->sin_port))
339 {
340 found = GNUNET_YES;
341 break;
342 }
343 }
344 else
345 {
346 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *) &addr;
347 struct sockaddr_in6 *ds_v6 = (struct sockaddr_in6 *) &ds->ss;
348
349 if (0 == memcmp (&v6->sin6_addr,
350 &ds_v6->sin6_addr,
351 sizeof (v6->sin6_addr)) &&
352 (v6->sin6_port == ds_v6->sin6_port))
353 {
354 found = GNUNET_YES;
355 break;
356 }
357
333 } 358 }
334 } 359 }
335 if (GNUNET_NO == found) 360 if (GNUNET_NO == found)
336 { 361 {
337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 362 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
338 "Received DNS response from server we never asked (ignored)"); 363 "Received DNS response from server we never asked (ignored)\n");
364
339 return GNUNET_NO; 365 return GNUNET_NO;
340 } 366 }
341 if (sizeof(struct GNUNET_TUN_DnsHeader) > (size_t) r) 367 if (sizeof(struct GNUNET_TUN_DnsHeader) > (size_t) r)
342 { 368 {
343 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 369 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
344 _ ("Received DNS response that is too small (%u bytes)"), 370 _ ("Received DNS response that is too small (%u bytes)\n"),
345 (unsigned int) r); 371 (unsigned int) r);
346 return GNUNET_NO; 372 return GNUNET_NO;
347 } 373 }
@@ -648,7 +674,7 @@ GNUNET_DNSSTUB_add_dns_sa (struct GNUNET_DNSSTUB_Context *ctx,
648 ds = GNUNET_new (struct DnsServer); 674 ds = GNUNET_new (struct DnsServer);
649 switch (sa->sa_family) 675 switch (sa->sa_family)
650 { 676 {
651 case AF_INET: 677 case AF_INET :
652 GNUNET_memcpy (&ds->ss, sa, sizeof(struct sockaddr_in)); 678 GNUNET_memcpy (&ds->ss, sa, sizeof(struct sockaddr_in));
653 break; 679 break;
654 680
diff --git a/src/util/getopt_helpers.c b/src/util/getopt_helpers.c
index 917aa440b..96aee40e3 100644
--- a/src/util/getopt_helpers.c
+++ b/src/util/getopt_helpers.c
@@ -174,7 +174,8 @@ OUTER:
174 i++; 174 i++;
175 } 175 }
176 pd = GNUNET_OS_project_data_get (); 176 pd = GNUNET_OS_project_data_get ();
177 printf ("Report bugs to %s.\n" 177 printf ("\n"
178 "Report bugs to %s.\n"
178 "Home page: %s\n", 179 "Home page: %s\n",
179 pd->bug_email, 180 pd->bug_email,
180 pd->homepage); 181 pd->homepage);
diff --git a/src/util/gnunet-crypto-tvg.c b/src/util/gnunet-crypto-tvg.c
index 6b2a7f472..0071f3e90 100644
--- a/src/util/gnunet-crypto-tvg.c
+++ b/src/util/gnunet-crypto-tvg.c
@@ -852,7 +852,7 @@ checkvec (const char *operation,
852 return GNUNET_SYSERR; 852 return GNUNET_SYSERR;
853 } 853 }
854 854
855 if ((b != 1)&& (b != 0)) 855 if ((b != 1) && (b != 0))
856 { 856 {
857 GNUNET_break (0); 857 GNUNET_break (0);
858 return GNUNET_SYSERR; 858 return GNUNET_SYSERR;
@@ -869,9 +869,14 @@ checkvec (const char *operation,
869 unsigned int b_comp; 869 unsigned int b_comp;
870 870
871 871
872 GNUNET_CRYPTO_cs_r_derive (&nonce, &priv, r_priv_comp); 872 GNUNET_CRYPTO_cs_r_derive (&nonce,
873 GNUNET_CRYPTO_cs_r_get_public (&r_priv_comp[0], &r_pub_comp[0]); 873 "rw",
874 GNUNET_CRYPTO_cs_r_get_public (&r_priv_comp[1], &r_pub_comp[1]); 874 &priv,
875 r_priv_comp);
876 GNUNET_CRYPTO_cs_r_get_public (&r_priv_comp[0],
877 &r_pub_comp[0]);
878 GNUNET_CRYPTO_cs_r_get_public (&r_priv_comp[1],
879 &r_pub_comp[1]);
875 GNUNET_assert (0 == memcmp (&r_priv_comp, 880 GNUNET_assert (0 == memcmp (&r_priv_comp,
876 &r_priv, 881 &r_priv,
877 sizeof(struct GNUNET_CRYPTO_CsRSecret) * 2)); 882 sizeof(struct GNUNET_CRYPTO_CsRSecret) * 2));
@@ -1316,9 +1321,14 @@ output_vectors ()
1316 strlen ("nonce_secret"), 1321 strlen ("nonce_secret"),
1317 NULL, 1322 NULL,
1318 0)); 1323 0));
1319 GNUNET_CRYPTO_cs_r_derive (&nonce, &priv, r_priv); 1324 GNUNET_CRYPTO_cs_r_derive (&nonce,
1320 GNUNET_CRYPTO_cs_r_get_public (&r_priv[0], &r_pub[0]); 1325 "rw",
1321 GNUNET_CRYPTO_cs_r_get_public (&r_priv[1], &r_pub[1]); 1326 &priv,
1327 r_priv);
1328 GNUNET_CRYPTO_cs_r_get_public (&r_priv[0],
1329 &r_pub[0]);
1330 GNUNET_CRYPTO_cs_r_get_public (&r_priv[1],
1331 &r_pub[1]);
1322 GNUNET_CRYPTO_cs_blinding_secrets_derive (&nonce, 1332 GNUNET_CRYPTO_cs_blinding_secrets_derive (&nonce,
1323 bs); 1333 bs);
1324 GNUNET_CRYPTO_cs_calc_blinded_c (bs, 1334 GNUNET_CRYPTO_cs_calc_blinded_c (bs,
diff --git a/src/util/network.c b/src/util/network.c
index 688c37665..2f77bc54e 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -350,7 +350,8 @@ initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
350 350
351 if (h->fd >= FD_SETSIZE) 351 if (h->fd >= FD_SETSIZE)
352 { 352 {
353 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h)); 353 GNUNET_break (GNUNET_OK ==
354 GNUNET_NETWORK_socket_close (h));
354 errno = EMFILE; 355 errno = EMFILE;
355 return GNUNET_SYSERR; 356 return GNUNET_SYSERR;
356 } 357 }
diff --git a/src/util/plugin.c b/src/util/plugin.c
index 39874a588..6ee41eec9 100644
--- a/src/util/plugin.c
+++ b/src/util/plugin.c
@@ -289,12 +289,12 @@ GNUNET_PLUGIN_unload (const char *library_name,
289 done = resolve_function (pos, 289 done = resolve_function (pos,
290 "done"); 290 "done");
291 ret = NULL; 291 ret = NULL;
292 if (NULL != done)
293 ret = done (arg);
294 if (NULL == prev) 292 if (NULL == prev)
295 plugins = pos->next; 293 plugins = pos->next;
296 else 294 else
297 prev->next = pos->next; 295 prev->next = pos->next;
296 if (NULL != done)
297 ret = done (arg);
298 lt_dlclose (pos->handle); 298 lt_dlclose (pos->handle);
299 GNUNET_free (pos->name); 299 GNUNET_free (pos->name);
300 GNUNET_free (pos); 300 GNUNET_free (pos);
diff --git a/src/util/strings.c b/src/util/strings.c
index ece096f72..7e218cc59 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -390,7 +390,7 @@ GNUNET_STRINGS_conv (const char *input,
390 ret[encoded_string_length] = '\0'; 390 ret[encoded_string_length] = '\0';
391 free (encoded_string); 391 free (encoded_string);
392 return ret; 392 return ret;
393fail: 393 fail:
394 LOG (GNUNET_ERROR_TYPE_WARNING, 394 LOG (GNUNET_ERROR_TYPE_WARNING,
395 _ ("Character sets requested were `%s'->`%s'\n"), 395 _ ("Character sets requested were `%s'->`%s'\n"),
396 "UTF-8", 396 "UTF-8",
@@ -426,24 +426,27 @@ GNUNET_STRINGS_from_utf8 (const char *input,
426} 426}
427 427
428 428
429void 429char *
430GNUNET_STRINGS_utf8_normalize (const char *input, 430GNUNET_STRINGS_utf8_normalize (const char *input)
431 char *output)
432{ 431{
433 uint8_t *tmp; 432 uint8_t *tmp;
434 size_t len; 433 size_t len;
435 434 char *output;
436 tmp = u8_normalize (UNINORM_NFC, 435 tmp = u8_normalize (UNINORM_NFC,
437 (uint8_t *) input, 436 (uint8_t *) input,
438 strlen ((char*) input), 437 strlen ((char*) input),
439 NULL, 438 NULL,
440 &len); 439 &len);
440 if (NULL == tmp)
441 return NULL;
442 output = GNUNET_malloc (len + 1);
441 GNUNET_memcpy (output, tmp, len); 443 GNUNET_memcpy (output, tmp, len);
442 output[len] = '\0'; 444 output[len] = '\0';
443 free (tmp); 445 free (tmp);
446 return output;
444} 447}
445 448
446void 449enum GNUNET_GenericReturnValue
447GNUNET_STRINGS_utf8_tolower (const char *input, 450GNUNET_STRINGS_utf8_tolower (const char *input,
448 char *output) 451 char *output)
449{ 452{
@@ -456,13 +459,16 @@ GNUNET_STRINGS_utf8_tolower (const char *input,
456 UNINORM_NFD, 459 UNINORM_NFD,
457 NULL, 460 NULL,
458 &len); 461 &len);
462 if (NULL == tmp_in)
463 return GNUNET_SYSERR;
459 GNUNET_memcpy (output, tmp_in, len); 464 GNUNET_memcpy (output, tmp_in, len);
460 output[len] = '\0'; 465 output[len] = '\0';
461 free (tmp_in); 466 GNUNET_free (tmp_in);
467 return GNUNET_OK;
462} 468}
463 469
464 470
465void 471enum GNUNET_GenericReturnValue
466GNUNET_STRINGS_utf8_toupper (const char *input, 472GNUNET_STRINGS_utf8_toupper (const char *input,
467 char *output) 473 char *output)
468{ 474{
@@ -475,9 +481,13 @@ GNUNET_STRINGS_utf8_toupper (const char *input,
475 UNINORM_NFD, 481 UNINORM_NFD,
476 NULL, 482 NULL,
477 &len); 483 &len);
484 if (NULL == tmp_in)
485 return GNUNET_SYSERR;
486 /* 0-terminator does not fit */
478 GNUNET_memcpy (output, tmp_in, len); 487 GNUNET_memcpy (output, tmp_in, len);
479 output[len] = '\0'; 488 output[len] = '\0';
480 free (tmp_in); 489 GNUNET_free (tmp_in);
490 return GNUNET_OK;
481} 491}
482 492
483 493
@@ -1604,7 +1614,7 @@ GNUNET_STRINGS_base64_encode (const void *in,
1604 char *opt; 1614 char *opt;
1605 1615
1606 ret = 0; 1616 ret = 0;
1607 GNUNET_assert (len < SIZE_MAX / 4 * 3 ); 1617 GNUNET_assert (len < SIZE_MAX / 4 * 3);
1608 opt = GNUNET_malloc (2 + (len * 4 / 3) + 8); 1618 opt = GNUNET_malloc (2 + (len * 4 / 3) + 8);
1609 for (size_t i = 0; i < len; ++i) 1619 for (size_t i = 0; i < len; ++i)
1610 { 1620 {
@@ -1741,7 +1751,7 @@ GNUNET_STRINGS_base64_decode (const char *data,
1741 output[ret++] = c; 1751 output[ret++] = c;
1742 } 1752 }
1743 } 1753 }
1744END: 1754 END:
1745 *out = output; 1755 *out = output;
1746 return ret; 1756 return ret;
1747} 1757}
@@ -1803,12 +1813,19 @@ GNUNET_STRINGS_urldecode (const char *data,
1803 char *wpos = *out; 1813 char *wpos = *out;
1804 size_t resl = 0; 1814 size_t resl = 0;
1805 1815
1806 while ('\0' != *rpos) 1816 while ( ('\0' != *rpos) &&
1817 (data + len != rpos) )
1807 { 1818 {
1808 unsigned int num; 1819 unsigned int num;
1809 switch (*rpos) 1820 switch (*rpos)
1810 { 1821 {
1811 case '%': 1822 case '%':
1823 if (rpos + 3 > data + len)
1824 {
1825 GNUNET_break_op (0);
1826 GNUNET_free (*out);
1827 return 0;
1828 }
1812 if (1 != sscanf (rpos + 1, "%2x", &num)) 1829 if (1 != sscanf (rpos + 1, "%2x", &num))
1813 break; 1830 break;
1814 *wpos = (char) ((unsigned char) num); 1831 *wpos = (char) ((unsigned char) num);
diff --git a/src/util/test_crypto_cs.c b/src/util/test_crypto_cs.c
index d3406516e..914ded9bc 100644
--- a/src/util/test_crypto_cs.c
+++ b/src/util/test_crypto_cs.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2014,2015 GNUnet e.V. 3 Copyright (C) 2021,2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -30,148 +30,168 @@
30 30
31#define ITER 25 31#define ITER 25
32 32
33void 33static void
34test_create_priv (struct GNUNET_CRYPTO_CsPrivateKey *priv) 34test_create_priv (struct GNUNET_CRYPTO_CsPrivateKey *priv)
35{ 35{
36 /* TEST 1 36 /* TEST 1
37 * Check that privkey is set 37 * Check that privkey is set
38 */ 38 */
39 struct GNUNET_CRYPTO_CsPrivateKey other_priv; 39 struct GNUNET_CRYPTO_CsPrivateKey other_priv;
40 memcpy (&other_priv.scalar, &priv->scalar, sizeof(other_priv.scalar));
41 40
41 other_priv = *priv;
42 GNUNET_CRYPTO_cs_private_key_generate (priv); 42 GNUNET_CRYPTO_cs_private_key_generate (priv);
43 43 GNUNET_assert (0 !=
44 GNUNET_assert (0 != memcmp (&other_priv.scalar, 44 GNUNET_memcmp (&other_priv.scalar,
45 &priv->scalar, 45 &priv->scalar));
46 sizeof(other_priv.scalar)));
47} 46}
48 47
49 48
50void 49static void
51test_generate_pub (const struct GNUNET_CRYPTO_CsPrivateKey *priv, 50test_generate_pub (const struct GNUNET_CRYPTO_CsPrivateKey *priv,
52 struct GNUNET_CRYPTO_CsPublicKey *pub) 51 struct GNUNET_CRYPTO_CsPublicKey *pub)
53{ 52{
54 /* TEST 1 53 /* TEST 1
55 * Check that pubkey is set 54 * Check that pubkey is set
56 */ 55 */
57 struct GNUNET_CRYPTO_CsPublicKey other_pub; 56 struct GNUNET_CRYPTO_CsPublicKey other_pub;
58 memcpy (&other_pub.point, &pub->point, sizeof(other_pub.point));
59
60 GNUNET_CRYPTO_cs_private_key_get_public (priv, pub);
61 57
62 GNUNET_assert (0 != memcmp (&other_pub.point, 58 other_pub = *pub;
63 &pub->point, 59 GNUNET_CRYPTO_cs_private_key_get_public (priv,
64 sizeof(other_pub.point))); 60 pub);
61 GNUNET_assert (0 !=
62 GNUNET_memcmp (&other_pub.point,
63 &pub->point));
65 64
66 /* TEST 2 65 /* TEST 2
67 * Check that pubkey is a valid point 66 * Check that pubkey is a valid point
68 */ 67 */
69 GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (pub->point.y)); 68 GNUNET_assert (1 ==
69 crypto_core_ed25519_is_valid_point (pub->point.y));
70 70
71 /* TEST 3 71 /* TEST 3
72 * Check if function gives the same result for the same output 72 * Check if function gives the same result for the same output
73 */ 73 */
74 memcpy (&other_pub.point, &pub->point, sizeof(other_pub.point)); 74 other_pub = *pub;
75 75 for (unsigned int i = 0; i<ITER; i++)
76 for (int i = 0; i<ITER; i++) { 76 {
77 GNUNET_CRYPTO_cs_private_key_get_public (priv, pub); 77 GNUNET_CRYPTO_cs_private_key_get_public (priv,
78 GNUNET_assert (0 == memcmp (&other_pub.point, 78 pub);
79 &pub->point, 79 GNUNET_assert (0 ==
80 sizeof(other_pub.point))); 80 GNUNET_memcmp (&other_pub.point,
81 &pub->point));
81 } 82 }
82} 83}
83 84
84 85
85void 86static void
86test_derive_rsecret (const struct GNUNET_CRYPTO_CsNonce *nonce, 87test_derive_rsecret (const struct GNUNET_CRYPTO_CsNonce *nonce,
87 const struct GNUNET_CRYPTO_CsPrivateKey *priv, 88 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
88 struct GNUNET_CRYPTO_CsRSecret r[2]) 89 struct GNUNET_CRYPTO_CsRSecret r[2])
89{ 90{
90 /* TEST 1 91 /* TEST 1
91 * Check that r are set 92 * Check that r are set
92 */ 93 */
93 struct GNUNET_CRYPTO_CsPrivateKey other_r[2]; 94 struct GNUNET_CRYPTO_CsPrivateKey other_r[2];
94 memcpy (&other_r[0], &r[0], sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2);
95 95
96 GNUNET_CRYPTO_cs_r_derive (nonce, priv, r); 96 memcpy (other_r,
97 97 r,
98 GNUNET_assert (0 != memcmp (&other_r[0], 98 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2);
99 &r[0], 99 GNUNET_CRYPTO_cs_r_derive (nonce,
100 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2)); 100 "nw",
101 priv,
102 r);
103 GNUNET_assert (0 !=
104 memcmp (&other_r[0],
105 &r[0],
106 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2));
101 107
102 /* TEST 2 108 /* TEST 2
103 * Check if function gives the same result for the same input. 109 * Check if function gives the same result for the same input.
104 * This test ensures that the derivation is deterministic. 110 * This test ensures that the derivation is deterministic.
105 */ 111 */
106 memcpy (&other_r[0], &r[0], sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2); 112 memcpy (other_r,
107 for (int i = 0; i<ITER; i++) { 113 r,
108 GNUNET_CRYPTO_cs_r_derive (nonce, priv, r); 114 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2);
109 GNUNET_assert (0 == memcmp (&other_r[0], 115 for (unsigned int i = 0; i<ITER; i++)
110 &r[0], 116 {
111 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2)); 117 GNUNET_CRYPTO_cs_r_derive (nonce,
118 "nw",
119 priv,
120 r);
121 GNUNET_assert (0 ==
122 memcmp (other_r,
123 r,
124 sizeof(struct GNUNET_CRYPTO_CsPrivateKey) * 2));
112 } 125 }
113} 126}
114 127
115 128
116void 129static void
117test_generate_rpublic (const struct GNUNET_CRYPTO_CsRSecret *r_priv, 130test_generate_rpublic (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
118 struct GNUNET_CRYPTO_CsRPublic *r_pub) 131 struct GNUNET_CRYPTO_CsRPublic *r_pub)
119{ 132{
120 /* TEST 1 133 /* TEST 1
121 * Check that r_pub is set 134 * Check that r_pub is set
122 */ 135 */
123 struct GNUNET_CRYPTO_CsRPublic other_r_pub; 136 struct GNUNET_CRYPTO_CsRPublic other_r_pub;
124 memcpy (&other_r_pub.point, &r_pub->point, sizeof(other_r_pub.point));
125
126 GNUNET_CRYPTO_cs_r_get_public (r_priv, r_pub);
127
128 GNUNET_assert (0 != memcmp (&other_r_pub.point,
129 &r_pub->point,
130 sizeof(other_r_pub.point)));
131 137
138 other_r_pub = *r_pub;
139 GNUNET_CRYPTO_cs_r_get_public (r_priv,
140 r_pub);
141 GNUNET_assert (0 !=
142 GNUNET_memcmp (&other_r_pub.point,
143 &r_pub->point));
132 /* TEST 2 144 /* TEST 2
133 * Check that r_pub is a valid point 145 * Check that r_pub is a valid point
134 */ 146 */
135 GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (r_pub->point.y)); 147 GNUNET_assert (1 ==
148 crypto_core_ed25519_is_valid_point (r_pub->point.y));
136 149
137 /* TEST 3 150 /* TEST 3
138 * Check if function gives the same result for the same output 151 * Check if function gives the same result for the same output
139 */ 152 */
140 memcpy (&other_r_pub.point, &r_pub->point, sizeof(other_r_pub.point)); 153 other_r_pub.point = r_pub->point;
141 for (int i = 0; i<ITER; i++) { 154 for (int i = 0; i<ITER; i++)
142 GNUNET_CRYPTO_cs_r_get_public (r_priv, r_pub); 155 {
143 GNUNET_assert (0 == memcmp (&other_r_pub.point, 156 GNUNET_CRYPTO_cs_r_get_public (r_priv,
144 &r_pub->point, 157 r_pub);
145 sizeof(other_r_pub.point))); 158 GNUNET_assert (0 ==
159 GNUNET_memcmp (&other_r_pub.point,
160 &r_pub->point));
146 } 161 }
147} 162}
148 163
149 164
150void 165static void
151test_derive_blindingsecrets (const struct GNUNET_CRYPTO_CsNonce *blind_seed, 166test_derive_blindingsecrets (const struct GNUNET_CRYPTO_CsNonce *blind_seed,
152 struct GNUNET_CRYPTO_CsBlindingSecret bs[2]) 167 struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
153{ 168{
154 /* TEST 1 169 /* TEST 1
155 * Check that blinding secrets are set 170 * Check that blinding secrets are set
156 */ 171 */
157 struct GNUNET_CRYPTO_CsBlindingSecret other_bs[2]; 172 struct GNUNET_CRYPTO_CsBlindingSecret other_bs[2];
158 memcpy (&other_bs[0], &bs[0], sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) 173
159 * 2); 174 memcpy (other_bs,
175 bs,
176 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) * 2);
160 177
161 GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed, bs); 178 GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed, bs);
162 179
163 GNUNET_assert (0 != memcmp (&other_bs[0], 180 GNUNET_assert (0 !=
164 &bs[0], 181 memcmp (other_bs,
165 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) 182 bs,
166 * 2)); 183 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret)
184 * 2));
167 185
168 /* TEST 2 186 /* TEST 2
169 * Check if function gives the same result for the same input. 187 * Check if function gives the same result for the same input.
170 * This test ensures that the derivation is deterministic. 188 * This test ensures that the derivation is deterministic.
171 */ 189 */
172 memcpy (&other_bs[0], &bs[0], sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) 190 memcpy (other_bs,
173 * 2); 191 bs,
174 for (int i = 0; i<ITER; i++) { 192 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) * 2);
193 for (unsigned int i = 0; i<ITER; i++)
194 {
175 GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed, bs); 195 GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed, bs);
176 GNUNET_assert (0 == memcmp (&other_bs[0], 196 GNUNET_assert (0 == memcmp (&other_bs[0],
177 &bs[0], 197 &bs[0],
@@ -181,19 +201,20 @@ test_derive_blindingsecrets (const struct GNUNET_CRYPTO_CsNonce *blind_seed,
181} 201}
182 202
183 203
184void 204static void
185test_calc_blindedc (const struct GNUNET_CRYPTO_CsBlindingSecret bs[2], 205test_calc_blindedc (const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
186 const struct GNUNET_CRYPTO_CsRPublic r_pub[2], 206 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
187 const struct GNUNET_CRYPTO_CsPublicKey *pub, 207 const struct GNUNET_CRYPTO_CsPublicKey *pub,
188 const void *msg, 208 const void *msg,
189 size_t msg_len, 209 size_t msg_len,
190 struct GNUNET_CRYPTO_CsC blinded_cs[2], 210 struct GNUNET_CRYPTO_CsC blinded_cs[2],
191 struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2]) 211 struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2])
192{ 212{
193 /* TEST 1 213 /* TEST 1
194 * Check that the blinded c's and blinded r's 214 * Check that the blinded c's and blinded r's
195 */ 215 */
196 struct GNUNET_CRYPTO_CsC other_blinded_c[2]; 216 struct GNUNET_CRYPTO_CsC other_blinded_c[2];
217
197 memcpy (&other_blinded_c[0], 218 memcpy (&other_blinded_c[0],
198 &blinded_cs[0], 219 &blinded_cs[0],
199 sizeof(struct GNUNET_CRYPTO_CsC) * 2); 220 sizeof(struct GNUNET_CRYPTO_CsC) * 2);
@@ -222,7 +243,8 @@ test_calc_blindedc (const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
222 * Check if R' - aG -bX = R for b = 0 243 * Check if R' - aG -bX = R for b = 0
223 * This test does the opposite operations and checks wether the equation is still correct. 244 * This test does the opposite operations and checks wether the equation is still correct.
224 */ 245 */
225 for (unsigned int b = 0; b <= 1; b++) { 246 for (unsigned int b = 0; b <= 1; b++)
247 {
226 struct GNUNET_CRYPTO_Cs25519Point aG; 248 struct GNUNET_CRYPTO_Cs25519Point aG;
227 struct GNUNET_CRYPTO_Cs25519Point bX; 249 struct GNUNET_CRYPTO_Cs25519Point bX;
228 struct GNUNET_CRYPTO_Cs25519Point r_min_aG; 250 struct GNUNET_CRYPTO_Cs25519Point r_min_aG;
@@ -252,7 +274,6 @@ test_calc_blindedc (const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
252 } 274 }
253 275
254 276
255
256 /* TEST 3 277 /* TEST 3
257 * Check that the blinded r_pubs' are valid points 278 * Check that the blinded r_pubs' are valid points
258 */ 279 */
@@ -271,7 +292,8 @@ test_calc_blindedc (const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
271 &blinded_r_pub[0], 292 &blinded_r_pub[0],
272 sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2); 293 sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2);
273 294
274 for (int i = 0; i<ITER; i++) { 295 for (unsigned int i = 0; i<ITER; i++)
296 {
275 GNUNET_CRYPTO_cs_calc_blinded_c (bs, 297 GNUNET_CRYPTO_cs_calc_blinded_c (bs,
276 r_pub, 298 r_pub,
277 pub, 299 pub,
@@ -289,13 +311,13 @@ test_calc_blindedc (const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
289} 311}
290 312
291 313
292void 314static void
293test_blind_sign (unsigned int *b, 315test_blind_sign (unsigned int *b,
294 const struct GNUNET_CRYPTO_CsPrivateKey *priv, 316 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
295 const struct GNUNET_CRYPTO_CsRSecret r[2], 317 const struct GNUNET_CRYPTO_CsRSecret r[2],
296 const struct GNUNET_CRYPTO_CsC c[2], 318 const struct GNUNET_CRYPTO_CsC c[2],
297 const struct GNUNET_CRYPTO_CsNonce *nonce, 319 const struct GNUNET_CRYPTO_CsNonce *nonce,
298 struct GNUNET_CRYPTO_CsBlindS *blinded_s) 320 struct GNUNET_CRYPTO_CsBlindS *blinded_s)
299{ 321{
300 /* TEST 1 322 /* TEST 1
301 * Check that blinded_s is set 323 * Check that blinded_s is set
@@ -336,8 +358,10 @@ test_blind_sign (unsigned int *b,
336 * Check if function gives the same result for the same input. 358 * Check if function gives the same result for the same input.
337 */ 359 */
338 memcpy (&other_blinded_s, blinded_s, sizeof(struct GNUNET_CRYPTO_CsBlindS)); 360 memcpy (&other_blinded_s, blinded_s, sizeof(struct GNUNET_CRYPTO_CsBlindS));
339 unsigned int other_b; 361 for (unsigned int i = 0; i<ITER; i++)
340 for (int i = 0; i<ITER; i++) { 362 {
363 unsigned int other_b;
364
341 other_b = GNUNET_CRYPTO_cs_sign_derive (priv, r, c, nonce, blinded_s); 365 other_b = GNUNET_CRYPTO_cs_sign_derive (priv, r, c, nonce, blinded_s);
342 366
343 GNUNET_assert (other_b == *b); 367 GNUNET_assert (other_b == *b);
@@ -348,10 +372,10 @@ test_blind_sign (unsigned int *b,
348} 372}
349 373
350 374
351void 375static void
352test_unblinds (const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar, 376test_unblinds (const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
353 const struct GNUNET_CRYPTO_CsBlindingSecret *bs, 377 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
354 struct GNUNET_CRYPTO_CsS *signature_scalar) 378 struct GNUNET_CRYPTO_CsS *signature_scalar)
355{ 379{
356 /* TEST 1 380 /* TEST 1
357 * Check that signature_scalar is set 381 * Check that signature_scalar is set
@@ -387,7 +411,8 @@ test_unblinds (const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
387 memcpy (&other_signature_scalar, signature_scalar, 411 memcpy (&other_signature_scalar, signature_scalar,
388 sizeof(struct GNUNET_CRYPTO_CsS)); 412 sizeof(struct GNUNET_CRYPTO_CsS));
389 413
390 for (int i = 0; i<ITER; i++) { 414 for (unsigned int i = 0; i<ITER; i++)
415 {
391 GNUNET_CRYPTO_cs_unblind (blinded_signature_scalar, bs, signature_scalar); 416 GNUNET_CRYPTO_cs_unblind (blinded_signature_scalar, bs, signature_scalar);
392 GNUNET_assert (0 == memcmp (&other_signature_scalar, 417 GNUNET_assert (0 == memcmp (&other_signature_scalar,
393 signature_scalar, 418 signature_scalar,
@@ -396,10 +421,10 @@ test_unblinds (const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
396} 421}
397 422
398 423
399void 424static void
400test_blind_verify (const struct GNUNET_CRYPTO_CsSignature *sig, 425test_blind_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
401 const struct GNUNET_CRYPTO_CsPublicKey *pub, 426 const struct GNUNET_CRYPTO_CsPublicKey *pub,
402 const struct GNUNET_CRYPTO_CsC *c) 427 const struct GNUNET_CRYPTO_CsC *c)
403{ 428{
404 /* TEST 1 429 /* TEST 1
405 * Test verifies the blinded signature sG == Rb + cbX 430 * Test verifies the blinded signature sG == Rb + cbX
@@ -425,28 +450,30 @@ test_blind_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
425} 450}
426 451
427 452
428void 453static void
429test_verify (const struct GNUNET_CRYPTO_CsSignature *sig, 454test_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
430 const struct GNUNET_CRYPTO_CsPublicKey *pub, 455 const struct GNUNET_CRYPTO_CsPublicKey *pub,
431 const void *msg, 456 const void *msg,
432 size_t msg_len) 457 size_t msg_len)
433{ 458{
434 /* TEST 1 459 /* TEST 1
435 * Test simple verification 460 * Test simple verification
436 */ 461 */
437 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_cs_verify (sig, 462 GNUNET_assert (GNUNET_YES ==
438 pub, 463 GNUNET_CRYPTO_cs_verify (sig,
439 msg, 464 pub,
440 msg_len)); 465 msg,
466 msg_len));
441 /* TEST 2 467 /* TEST 2
442 * Test verification of "wrong" message 468 * Test verification of "wrong" message
443 */ 469 */
444 char other_msg[] = "test massege"; 470 char other_msg[] = "test massege";
445 size_t other_msg_len = strlen ("test massege"); 471 size_t other_msg_len = strlen ("test massege");
446 GNUNET_assert (GNUNET_SYSERR == GNUNET_CRYPTO_cs_verify (sig, 472 GNUNET_assert (GNUNET_SYSERR ==
447 pub, 473 GNUNET_CRYPTO_cs_verify (sig,
448 other_msg, 474 pub,
449 other_msg_len)); 475 other_msg,
476 other_msg_len));
450} 477}
451 478
452 479
@@ -461,71 +488,122 @@ main (int argc,
461 size_t message_len = strlen ("test message"); 488 size_t message_len = strlen ("test message");
462 489
463 struct GNUNET_CRYPTO_CsPrivateKey priv; 490 struct GNUNET_CRYPTO_CsPrivateKey priv;
491
492 memset (&priv,
493 42,
494 sizeof (priv));
464 test_create_priv (&priv); 495 test_create_priv (&priv);
465 496
466 struct GNUNET_CRYPTO_CsPublicKey pub; 497 struct GNUNET_CRYPTO_CsPublicKey pub;
467 test_generate_pub (&priv, &pub); 498
499 memset (&pub,
500 42,
501 sizeof (pub));
502 test_generate_pub (&priv,
503 &pub);
468 504
469 // derive nonce 505 // derive nonce
470 struct GNUNET_CRYPTO_CsNonce nonce; 506 struct GNUNET_CRYPTO_CsNonce nonce;
471 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_hkdf (nonce.nonce, 507 GNUNET_assert (GNUNET_YES ==
472 sizeof(nonce.nonce), 508 GNUNET_CRYPTO_kdf (nonce.nonce,
473 GCRY_MD_SHA512, 509 sizeof(nonce.nonce),
474 GCRY_MD_SHA256, 510 "nonce",
475 "nonce", 511 strlen ("nonce"),
476 strlen ("nonce"), 512 "nonce_secret",
477 "nonce_secret", 513 strlen ("nonce_secret"),
478 strlen ("nonce_secret"), 514 NULL,
479 NULL, 515 0));
480 0));
481 516
482 // generate r, R 517 // generate r, R
483 struct GNUNET_CRYPTO_CsRSecret r_secrets[2]; 518 struct GNUNET_CRYPTO_CsRSecret r_secrets[2];
484 test_derive_rsecret (&nonce, &priv, r_secrets); 519
520 memset (r_secrets,
521 42,
522 sizeof (r_secrets));
523 test_derive_rsecret (&nonce,
524 &priv,
525 r_secrets);
485 526
486 struct GNUNET_CRYPTO_CsRPublic r_publics[2]; 527 struct GNUNET_CRYPTO_CsRPublic r_publics[2];
487 test_generate_rpublic (&r_secrets[0], &r_publics[0]); 528
488 test_generate_rpublic (&r_secrets[1], &r_publics[1]); 529 memset (r_publics,
530 42,
531 sizeof (r_publics));
532 test_generate_rpublic (&r_secrets[0],
533 &r_publics[0]);
534 test_generate_rpublic (&r_secrets[1],
535 &r_publics[1]);
489 536
490 // ---------- actions performed by user 537 // ---------- actions performed by user
491 538
492 // generate blinding secrets 539 // generate blinding secrets
493 struct GNUNET_CRYPTO_CsBlindingSecret blindingsecrets[2]; 540 struct GNUNET_CRYPTO_CsBlindingSecret blindingsecrets[2];
541
542 memset (blindingsecrets,
543 42,
544 sizeof (blindingsecrets));
494 test_derive_blindingsecrets (&nonce, 545 test_derive_blindingsecrets (&nonce,
495 blindingsecrets); 546 blindingsecrets);
496 547
497 // calculate blinded c's 548 // calculate blinded c's
498 struct GNUNET_CRYPTO_CsC blinded_cs[2]; 549 struct GNUNET_CRYPTO_CsC blinded_cs[2];
499 struct GNUNET_CRYPTO_CsRPublic blinded_r_pubs[2]; 550 struct GNUNET_CRYPTO_CsRPublic blinded_r_pubs[2];
551
552 memset (blinded_cs,
553 42,
554 sizeof (blinded_cs));
555 memset (blinded_r_pubs,
556 42,
557 sizeof (blinded_r_pubs));
500 test_calc_blindedc (blindingsecrets, 558 test_calc_blindedc (blindingsecrets,
501 r_publics, 559 r_publics,
502 &pub, 560 &pub,
503 message, 561 message,
504 message_len, 562 message_len,
505 blinded_cs, 563 blinded_cs,
506 blinded_r_pubs); 564 blinded_r_pubs);
507 565
508 // ---------- actions performed by signer 566 // ---------- actions performed by signer
509 // sign blinded c's and get b and s in return 567 // sign blinded c's and get b and s in return
510 unsigned int b; 568 unsigned int b;
511 struct GNUNET_CRYPTO_CsBlindS blinded_s; 569 struct GNUNET_CRYPTO_CsBlindS blinded_s;
512 test_blind_sign (&b, &priv, r_secrets, blinded_cs, &nonce, &blinded_s); 570
571 memset (&blinded_s,
572 42,
573 sizeof (blinded_s));
574 test_blind_sign (&b,
575 &priv,
576 r_secrets,
577 blinded_cs,
578 &nonce,
579 &blinded_s);
513 580
514 // verify blinded signature 581 // verify blinded signature
515 struct GNUNET_CRYPTO_CsSignature blinded_signature; 582 struct GNUNET_CRYPTO_CsSignature blinded_signature;
583
516 blinded_signature.r_point = r_publics[b]; 584 blinded_signature.r_point = r_publics[b];
517 blinded_signature.s_scalar.scalar = blinded_s.scalar; 585 blinded_signature.s_scalar.scalar = blinded_s.scalar;
518 test_blind_verify (&blinded_signature, &pub, &blinded_cs[b]); 586 test_blind_verify (&blinded_signature,
587 &pub,
588 &blinded_cs[b]);
519 589
520 // ---------- actions performed by user 590 // ---------- actions performed by user
521 struct GNUNET_CRYPTO_CsS sig_scalar; 591 struct GNUNET_CRYPTO_CsS sig_scalar;
522 test_unblinds (&blinded_s, &blindingsecrets[b], &sig_scalar); 592
593 memset (&sig_scalar,
594 42,
595 sizeof (sig_scalar));
596 test_unblinds (&blinded_s,
597 &blindingsecrets[b],
598 &sig_scalar);
523 599
524 // verify unblinded signature 600 // verify unblinded signature
525 struct GNUNET_CRYPTO_CsSignature signature; 601 struct GNUNET_CRYPTO_CsSignature signature;
526 signature.r_point = blinded_r_pubs[b]; 602 signature.r_point = blinded_r_pubs[b];
527 signature.s_scalar = sig_scalar; 603 signature.s_scalar = sig_scalar;
528 test_verify (&signature, &pub, message, message_len); 604 test_verify (&signature,
529 605 &pub,
606 message,
607 message_len);
530 return 0; 608 return 0;
531} 609}
diff --git a/src/util/test_strings.c b/src/util/test_strings.c
index 1ecd31464..cccffcaf5 100644
--- a/src/util/test_strings.c
+++ b/src/util/test_strings.c
@@ -114,10 +114,9 @@ main (int argc, char *argv[])
114 /* Normalization */ 114 /* Normalization */
115 r = "q\u0307\u0323"; /* Non-canonical order */ 115 r = "q\u0307\u0323"; /* Non-canonical order */
116 116
117 GNUNET_STRINGS_utf8_normalize (r, 117 b = GNUNET_STRINGS_utf8_normalize (r);
118 buf); 118 GNUNET_assert (0 == strcmp ("q\u0323\u0307", b));
119 GNUNET_assert (0 == strcmp ("q\u0323\u0307", buf)); 119 GNUNET_free (b);
120
121 b = GNUNET_STRINGS_to_utf8 ("TEST", 4, "ASCII"); 120 b = GNUNET_STRINGS_to_utf8 ("TEST", 4, "ASCII");
122 WANT ("TEST", b); 121 WANT ("TEST", b);
123 122
diff --git a/src/util/time.c b/src/util/time.c
index 83b39b4e8..68a6937a0 100644
--- a/src/util/time.c
+++ b/src/util/time.c
@@ -695,6 +695,13 @@ GNUNET_TIME_timestamp_from_s (uint64_t s_after_epoch)
695} 695}
696 696
697 697
698uint64_t
699GNUNET_TIME_timestamp_to_s (struct GNUNET_TIME_Timestamp ts)
700{
701 return ts.abs_time.abs_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
702}
703
704
698struct GNUNET_TIME_Absolute 705struct GNUNET_TIME_Absolute
699GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a) 706GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
700{ 707{
diff --git a/src/zonemaster/gnunet-service-zonemaster-monitor.c b/src/zonemaster/gnunet-service-zonemaster-monitor.c
index 3392a19d7..748a0f342 100644
--- a/src/zonemaster/gnunet-service-zonemaster-monitor.c
+++ b/src/zonemaster/gnunet-service-zonemaster-monitor.c
@@ -29,7 +29,6 @@
29#include "gnunet_namestore_service.h" 29#include "gnunet_namestore_service.h"
30#include "gnunet_statistics_service.h" 30#include "gnunet_statistics_service.h"
31 31
32
33#define LOG_STRERROR_FILE(kind, syscall, \ 32#define LOG_STRERROR_FILE(kind, syscall, \
34 filename) GNUNET_log_from_strerror_file (kind, "util", \ 33 filename) GNUNET_log_from_strerror_file (kind, "util", \
35 syscall, \ 34 syscall, \
@@ -58,7 +57,6 @@
58 */ 57 */
59#define DHT_GNS_REPLICATION_LEVEL 5 58#define DHT_GNS_REPLICATION_LEVEL 5
60 59
61
62/** 60/**
63 * Handle for DHT PUT activity triggered from the namestore monitor. 61 * Handle for DHT PUT activity triggered from the namestore monitor.
64 */ 62 */
@@ -197,39 +195,6 @@ dht_put_monitor_continuation (void *cls)
197 195
198 196
199/** 197/**
200 * Convert namestore records from the internal format to that
201 * suitable for publication (removes private records, converts
202 * to absolute expiration time).
203 *
204 * @param rd input records
205 * @param rd_count size of the @a rd and @a rd_public arrays
206 * @param rd_public where to write the converted records
207 * @return number of records written to @a rd_public
208 */
209static unsigned int
210convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
211 unsigned int rd_count,
212 struct GNUNET_GNSRECORD_Data *rd_public)
213{
214 struct GNUNET_TIME_Absolute now;
215 unsigned int rd_public_count;
216
217 rd_public_count = 0;
218 now = GNUNET_TIME_absolute_get ();
219 for (unsigned int i = 0; i < rd_count; i++)
220 {
221 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
222 continue;
223 if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
224 (rd[i].expiration_time < now.abs_value_us))
225 continue; /* record already expired, skip it */
226 rd_public[rd_public_count++] = rd[i];
227 }
228 return rd_public_count;
229}
230
231
232/**
233 * Store GNS records in the DHT. 198 * Store GNS records in the DHT.
234 * 199 *
235 * @param key key of the zone 200 * @param key key of the zone
@@ -244,16 +209,14 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
244 const char *label, 209 const char *label,
245 const struct GNUNET_GNSRECORD_Data *rd_public, 210 const struct GNUNET_GNSRECORD_Data *rd_public,
246 unsigned int rd_public_count, 211 unsigned int rd_public_count,
212 struct GNUNET_TIME_Absolute expire,
247 struct DhtPutActivity *ma) 213 struct DhtPutActivity *ma)
248{ 214{
249 struct GNUNET_GNSRECORD_Block *block; 215 struct GNUNET_GNSRECORD_Block *block;
250 struct GNUNET_HashCode query; 216 struct GNUNET_HashCode query;
251 struct GNUNET_TIME_Absolute expire;
252 size_t block_size; 217 size_t block_size;
253 struct GNUNET_DHT_PutHandle *ret; 218 struct GNUNET_DHT_PutHandle *ret;
254 219
255 expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
256 rd_public);
257 if (cache_keys) 220 if (cache_keys)
258 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key, 221 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key,
259 expire, 222 expire,
@@ -301,7 +264,6 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
301 return ret; 264 return ret;
302} 265}
303 266
304
305/** 267/**
306 * Process a record that was stored in the namestore 268 * Process a record that was stored in the namestore
307 * (invoked by the monitor). 269 * (invoked by the monitor).
@@ -322,6 +284,8 @@ handle_monitor_event (void *cls,
322 struct GNUNET_GNSRECORD_Data rd_public[rd_count]; 284 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
323 unsigned int rd_public_count; 285 unsigned int rd_public_count;
324 struct DhtPutActivity *ma; 286 struct DhtPutActivity *ma;
287 struct GNUNET_TIME_Absolute expire;
288 char *emsg;
325 289
326 (void) cls; 290 (void) cls;
327 GNUNET_STATISTICS_update (statistics, 291 GNUNET_STATISTICS_update (statistics,
@@ -334,9 +298,21 @@ handle_monitor_event (void *cls,
334 label); 298 label);
335 /* filter out records that are not public, and convert to 299 /* filter out records that are not public, and convert to
336 absolute expiration time. */ 300 absolute expiration time. */
337 rd_public_count = convert_records_for_export (rd, 301 if (GNUNET_OK != GNUNET_GNSRECORD_convert_records_for_export (label,
338 rd_count, 302 rd,
339 rd_public); 303 rd_count,
304 rd_public,
305 &rd_public_count,
306 &expire,
307 &emsg))
308 {
309 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
310 "Zonemaster-monitor failed: %s\n", emsg);
311 GNUNET_free (emsg);
312 GNUNET_NAMESTORE_zone_monitor_next (zmon,
313 1);
314 return; /* nothing to do */
315 }
340 if (0 == rd_public_count) 316 if (0 == rd_public_count)
341 { 317 {
342 GNUNET_NAMESTORE_zone_monitor_next (zmon, 318 GNUNET_NAMESTORE_zone_monitor_next (zmon,
@@ -347,8 +323,9 @@ handle_monitor_event (void *cls,
347 ma->start_date = GNUNET_TIME_absolute_get (); 323 ma->start_date = GNUNET_TIME_absolute_get ();
348 ma->ph = perform_dht_put (zone, 324 ma->ph = perform_dht_put (zone,
349 label, 325 label,
350 rd, 326 rd_public,
351 rd_count, 327 rd_public_count,
328 expire,
352 ma); 329 ma);
353 if (NULL == ma->ph) 330 if (NULL == ma->ph)
354 { 331 {
diff --git a/src/zonemaster/gnunet-service-zonemaster.c b/src/zonemaster/gnunet-service-zonemaster.c
index bacafb97c..c6b86bf71 100644
--- a/src/zonemaster/gnunet-service-zonemaster.c
+++ b/src/zonemaster/gnunet-service-zonemaster.c
@@ -30,7 +30,6 @@
30#include "gnunet_namestore_service.h" 30#include "gnunet_namestore_service.h"
31#include "gnunet_statistics_service.h" 31#include "gnunet_statistics_service.h"
32 32
33
34#define LOG_STRERROR_FILE(kind, syscall, \ 33#define LOG_STRERROR_FILE(kind, syscall, \
35 filename) GNUNET_log_from_strerror_file (kind, "util", \ 34 filename) GNUNET_log_from_strerror_file (kind, "util", \
36 syscall, \ 35 syscall, \
@@ -90,7 +89,6 @@
90 */ 89 */
91#define DHT_GNS_REPLICATION_LEVEL 5 90#define DHT_GNS_REPLICATION_LEVEL 5
92 91
93
94/** 92/**
95 * Handle for DHT PUT activity triggered from the namestore monitor. 93 * Handle for DHT PUT activity triggered from the namestore monitor.
96 */ 94 */
@@ -527,46 +525,6 @@ dht_put_continuation (void *cls)
527} 525}
528 526
529 527
530/**
531 * Convert namestore records from the internal format to that
532 * suitable for publication (removes private records, converts
533 * to absolute expiration time).
534 *
535 * @param rd input records
536 * @param rd_count size of the @a rd and @a rd_public arrays
537 * @param rd_public where to write the converted records
538 * @return number of records written to @a rd_public
539 */
540static unsigned int
541convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd,
542 unsigned int rd_count,
543 struct GNUNET_GNSRECORD_Data *rd_public)
544{
545 struct GNUNET_TIME_Absolute now;
546 unsigned int rd_public_count;
547
548 rd_public_count = 0;
549 now = GNUNET_TIME_absolute_get ();
550 for (unsigned int i = 0; i < rd_count; i++)
551 {
552 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
553 continue;
554 if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
555 (rd[i].expiration_time < now.abs_value_us))
556 continue; /* record already expired, skip it */
557 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
558 {
559 /* GNUNET_GNSRECORD_block_create will convert to absolute time;
560 we just need to adjust our iteration frequency */
561 min_relative_record_time.rel_value_us =
562 GNUNET_MIN (rd[i].expiration_time,
563 min_relative_record_time.rel_value_us);
564 }
565 rd_public[rd_public_count++] = rd[i];
566 }
567 return rd_public_count;
568}
569
570 528
571/** 529/**
572 * Store GNS records in the DHT. 530 * Store GNS records in the DHT.
@@ -583,30 +541,28 @@ perform_dht_put (const struct GNUNET_IDENTITY_PrivateKey *key,
583 const char *label, 541 const char *label,
584 const struct GNUNET_GNSRECORD_Data *rd_public, 542 const struct GNUNET_GNSRECORD_Data *rd_public,
585 unsigned int rd_public_count, 543 unsigned int rd_public_count,
544 const struct GNUNET_TIME_Absolute expire,
586 struct DhtPutActivity *ma) 545 struct DhtPutActivity *ma)
587{ 546{
588 struct GNUNET_GNSRECORD_Block *block; 547 struct GNUNET_GNSRECORD_Block *block;
589 struct GNUNET_HashCode query; 548 struct GNUNET_HashCode query;
590 struct GNUNET_TIME_Absolute expire;
591 size_t block_size; 549 size_t block_size;
592 struct GNUNET_DHT_PutHandle *ret; 550 struct GNUNET_DHT_PutHandle *ret;
593 551
594 expire = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count,
595 rd_public);
596 if (cache_keys) 552 if (cache_keys)
597 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key, 553 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create2 (key,
598 expire, 554 expire,
599 label, 555 label,
600 rd_public, 556 rd_public,
601 rd_public_count, 557 rd_public_count,
602 &block)); 558 &block));
603 else 559 else
604 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key, 560 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_create (key,
605 expire, 561 expire,
606 label, 562 label,
607 rd_public, 563 rd_public,
608 rd_public_count, 564 rd_public_count,
609 &block)); 565 &block));
610 if (NULL == block) 566 if (NULL == block)
611 { 567 {
612 GNUNET_break (0); 568 GNUNET_break (0);
@@ -713,7 +669,6 @@ zone_iteration_finished (void *cls)
713 } 669 }
714} 670}
715 671
716
717/** 672/**
718 * Function used to put all records successively into the DHT. 673 * Function used to put all records successively into the DHT.
719 * 674 *
@@ -733,12 +688,26 @@ put_gns_record (void *cls,
733 struct GNUNET_GNSRECORD_Data rd_public[rd_count]; 688 struct GNUNET_GNSRECORD_Data rd_public[rd_count];
734 unsigned int rd_public_count; 689 unsigned int rd_public_count;
735 struct DhtPutActivity *ma; 690 struct DhtPutActivity *ma;
691 struct GNUNET_TIME_Absolute expire;
692 char *emsg;
736 693
737 (void) cls; 694 (void) cls;
738 ns_iteration_left--; 695 ns_iteration_left--;
739 rd_public_count = convert_records_for_export (rd, 696 if (GNUNET_OK != GNUNET_GNSRECORD_convert_records_for_export (label,
740 rd_count, 697 rd,
741 rd_public); 698 rd_count,
699 rd_public,
700 &rd_public_count,
701 &expire,
702 &emsg))
703 {
704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
705 "Record set inconsistent, moving to next record set: %s\n",
706 emsg);
707 GNUNET_free (emsg);
708 check_zone_namestore_next ();
709 return;
710 }
742 if (0 == rd_public_count) 711 if (0 == rd_public_count)
743 { 712 {
744 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -746,15 +715,30 @@ put_gns_record (void *cls,
746 check_zone_namestore_next (); 715 check_zone_namestore_next ();
747 return; 716 return;
748 } 717 }
718 for (unsigned int i = 0; i < rd_public_count; i++)
719 {
720 if (0 != (rd_public[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
721 {
722 /* GNUNET_GNSRECORD_block_create will convert to absolute time;
723 we just need to adjust our iteration frequency */
724 min_relative_record_time.rel_value_us =
725 GNUNET_MIN (rd_public[i].expiration_time,
726 min_relative_record_time.rel_value_us);
727 }
728 }
729
730
749 /* We got a set of records to publish */ 731 /* We got a set of records to publish */
750 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
751 "Starting DHT PUT\n"); 733 "Starting DHT PUT\n");
734
752 ma = GNUNET_new (struct DhtPutActivity); 735 ma = GNUNET_new (struct DhtPutActivity);
753 ma->start_date = GNUNET_TIME_absolute_get (); 736 ma->start_date = GNUNET_TIME_absolute_get ();
754 ma->ph = perform_dht_put (key, 737 ma->ph = perform_dht_put (key,
755 label, 738 label,
756 rd_public, 739 rd_public,
757 rd_public_count, 740 rd_public_count,
741 expire,
758 ma); 742 ma);
759 put_cnt++; 743 put_cnt++;
760 if (0 == put_cnt % DELTA_INTERVAL) 744 if (0 == put_cnt % DELTA_INTERVAL)
@@ -788,7 +772,6 @@ put_gns_record (void *cls,
788 } 772 }
789} 773}
790 774
791
792/** 775/**
793 * Periodically iterate over all zones and store everything in DHT 776 * Periodically iterate over all zones and store everything in DHT
794 * 777 *