aboutsummaryrefslogtreecommitdiff
path: root/src/plugin/gns
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugin/gns')
-rw-r--r--src/plugin/gns/Makefile.am59
-rw-r--r--src/plugin/gns/meson.build17
-rw-r--r--src/plugin/gns/plugin_block_gns.c289
-rw-r--r--src/plugin/gns/plugin_gnsrecord_gns.c515
4 files changed, 880 insertions, 0 deletions
diff --git a/src/plugin/gns/Makefile.am b/src/plugin/gns/Makefile.am
new file mode 100644
index 000000000..8dc9ef2b2
--- /dev/null
+++ b/src/plugin/gns/Makefile.am
@@ -0,0 +1,59 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if HAVE_LIBIDN
5 LIBIDN= -lidn
6else
7 LIBIDN=
8endif
9
10if HAVE_LIBIDN2
11 LIBIDN2= -lidn2
12else
13 LIBIDN2=
14endif
15
16USE_VPN = $(top_builddir)/src/service/vpn/libgnunetvpn.la
17
18if USE_COVERAGE
19 AM_CFLAGS = --coverage -O0
20endif
21
22pkgcfgdir = $(pkgdatadir)/config.d/
23
24libexecdir= $(pkglibdir)/libexec/
25
26plugindir = $(libdir)/gnunet
27
28plugin_LTLIBRARIES = \
29 libgnunet_plugin_block_gns.la \
30 libgnunet_plugin_gnsrecord_gns.la
31
32
33libgnunet_plugin_gnsrecord_gns_la_SOURCES = \
34 plugin_gnsrecord_gns.c
35libgnunet_plugin_gnsrecord_gns_la_LIBADD = \
36 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \
37 $(top_builddir)/src/lib/util/libgnunetutil.la \
38 $(LTLIBINTL)
39libgnunet_plugin_gnsrecord_gns_la_LDFLAGS = \
40 $(GN_PLUGIN_LDFLAGS)
41
42
43libgnunet_plugin_block_gns_la_SOURCES = \
44 plugin_block_gns.c
45libgnunet_plugin_block_gns_la_LIBADD = \
46 $(top_builddir)/src/lib/util/libgnunetutil.la \
47 $(top_builddir)/src/lib/block/libgnunetblock.la \
48 $(top_builddir)/src/lib/block/libgnunetblockgroup.la \
49 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la
50libgnunet_plugin_block_gns_la_LDFLAGS = \
51 $(GN_LIBINTL) \
52 $(GN_PLUGIN_LDFLAGS)
53
54if ENABLE_TEST_RUN
55if HAVE_SQLITE
56 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
57 TESTS = $(check_SCRIPTS)
58endif
59endif
diff --git a/src/plugin/gns/meson.build b/src/plugin/gns/meson.build
new file mode 100644
index 000000000..2cdf770f8
--- /dev/null
+++ b/src/plugin/gns/meson.build
@@ -0,0 +1,17 @@
1shared_module('gnunet_plugin_gnsrecord_gns',
2 ['plugin_gnsrecord_gns.c'],
3 dependencies: [libgnunetutil_dep,
4 libgnunetgnsrecord_dep,
5 ],
6 include_directories: [incdir, configuration_inc],
7 install: true,
8 install_dir: get_option('libdir')/'gnunet')
9shared_module('gnunet_plugin_block_gns',
10 ['plugin_block_gns.c'],
11 dependencies: [libgnunetutil_dep,
12 libgnunetgnsrecord_dep,
13 libgnunetblockgroup_dep],
14 include_directories: [incdir, configuration_inc],
15 install:true,
16 install_dir: get_option('libdir')/'gnunet')
17
diff --git a/src/plugin/gns/plugin_block_gns.c b/src/plugin/gns/plugin_block_gns.c
new file mode 100644
index 000000000..75e182092
--- /dev/null
+++ b/src/plugin/gns/plugin_block_gns.c
@@ -0,0 +1,289 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2013, 2021, 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 gns/plugin_block_gns.c
23 * @brief blocks used for GNS records
24 * @author Martin Schanzenbach
25 * @author Christian Grothoff
26 */
27
28#include "platform.h"
29#include "gnunet_block_group_lib.h"
30#include "gnunet_block_plugin.h"
31#include "gnunet_namestore_service.h"
32#include "gnunet_signatures.h"
33
34/**
35 * Number of bits we set per entry in the bloomfilter.
36 * Do not change! -from fs
37 */
38#define BLOOMFILTER_K 16
39
40/**
41 * How big is the BF we use for GNS blocks?
42 */
43#define GNS_BF_SIZE 8
44
45
46/**
47 * Create a new block group.
48 *
49 * @param ctx block context in which the block group is created
50 * @param type type of the block for which we are creating the group
51 * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
52 * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
53 * @param va variable arguments specific to @a type
54 * @return block group handle, NULL if block groups are not supported
55 * by this @a type of block (this is not an error)
56 */
57static struct GNUNET_BLOCK_Group *
58block_plugin_gns_create_group (void *cls,
59 enum GNUNET_BLOCK_Type type,
60 const void *raw_data,
61 size_t raw_data_size,
62 va_list va)
63{
64 unsigned int bf_size;
65 const char *guard;
66
67 guard = va_arg (va, const char *);
68 if (0 == strcmp (guard,
69 "seen-set-size"))
70 bf_size = GNUNET_BLOCK_GROUP_compute_bloomfilter_size (va_arg (va, unsigned
71 int),
72 BLOOMFILTER_K);
73 else if (0 == strcmp (guard,
74 "filter-size"))
75 bf_size = va_arg (va, unsigned int);
76 else
77 {
78 GNUNET_break (0);
79 bf_size = GNS_BF_SIZE;
80 }
81 GNUNET_break (NULL == va_arg (va, const char *));
82 return GNUNET_BLOCK_GROUP_bf_create (cls,
83 bf_size,
84 BLOOMFILTER_K,
85 type,
86 raw_data,
87 raw_data_size);
88}
89
90
91/**
92 * Function called to obtain the key for a block.
93 * If the @a block is malformed, the function should
94 * zero-out @a key and return #GNUNET_OK.
95 *
96 * @param cls closure
97 * @param type block type
98 * @param reply_block block to get the key for
99 * @param reply_block_size number of bytes in @a reply_block
100 * @param key set to the key (query) for the given block
101 * @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
102 */
103static enum GNUNET_GenericReturnValue
104block_plugin_gns_get_key (void *cls,
105 enum GNUNET_BLOCK_Type type,
106 const void *reply_block,
107 size_t reply_block_size,
108 struct GNUNET_HashCode *key)
109{
110 const struct GNUNET_GNSRECORD_Block *block;
111
112 if (GNUNET_BLOCK_TYPE_GNS_NAMERECORD != type)
113 {
114 GNUNET_break (0);
115 return GNUNET_SYSERR;
116 }
117 if (reply_block_size < sizeof(struct GNUNET_GNSRECORD_Block))
118 {
119 GNUNET_break_op (0);
120 memset (key,
121 0,
122 sizeof (*key));
123 return GNUNET_OK;
124 }
125 block = reply_block;
126 GNUNET_GNSRECORD_query_from_block (block,
127 key);
128 return GNUNET_OK;
129}
130
131
132/**
133 * Function called to validate a query.
134 *
135 * @param cls closure
136 * @param type block type
137 * @param query original query (hash)
138 * @param xquery extrended query data (can be NULL, depending on type)
139 * @param xquery_size number of bytes in @a xquery
140 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
141 */
142static enum GNUNET_GenericReturnValue
143block_plugin_gns_check_query (void *cls,
144 enum GNUNET_BLOCK_Type type,
145 const struct GNUNET_HashCode *query,
146 const void *xquery,
147 size_t xquery_size)
148{
149 if (GNUNET_BLOCK_TYPE_GNS_NAMERECORD != type)
150 {
151 GNUNET_break (0);
152 return GNUNET_SYSERR;
153 }
154 if (0 != xquery_size)
155 {
156 GNUNET_break_op (0);
157 return GNUNET_NO;
158 }
159 return GNUNET_OK;
160}
161
162
163/**
164 * Function called to validate a block for storage.
165 *
166 * @param cls closure
167 * @param type block type
168 * @param block block data to validate
169 * @param block_size number of bytes in @a block
170 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
171 */
172static enum GNUNET_GenericReturnValue
173block_plugin_gns_check_block (void *cls,
174 enum GNUNET_BLOCK_Type type,
175 const void *block,
176 size_t block_size)
177{
178 const struct GNUNET_GNSRECORD_Block *gblock;
179
180 if (GNUNET_BLOCK_TYPE_GNS_NAMERECORD != type)
181 {
182 GNUNET_break (0);
183 return GNUNET_SYSERR;
184 }
185 if (block_size < sizeof(struct GNUNET_GNSRECORD_Block))
186 {
187 GNUNET_break_op (0);
188 return GNUNET_NO;
189 }
190 gblock = block;
191 if (GNUNET_GNSRECORD_block_get_size (gblock) > block_size)
192 {
193 GNUNET_break_op (0);
194 return GNUNET_NO;
195 }
196 if (GNUNET_OK !=
197 GNUNET_GNSRECORD_block_verify (gblock))
198 {
199 GNUNET_break_op (0);
200 return GNUNET_NO;
201 }
202 return GNUNET_OK;
203}
204
205
206/**
207 * Function called to validate a reply to a request. Note that it is assumed
208 * that the reply has already been matched to the key (and signatures checked)
209 * as it would be done with the GetKeyFunction and the
210 * BlockEvaluationFunction.
211 *
212 * @param cls closure
213 * @param type block type
214 * @param group which block group to use for evaluation
215 * @param query original query (hash)
216 * @param xquery extrended query data (can be NULL, depending on type)
217 * @param xquery_size number of bytes in @a xquery
218 * @param reply_block response to validate
219 * @param reply_block_size number of bytes in @a reply_block
220 * @return characterization of result
221 */
222static enum GNUNET_BLOCK_ReplyEvaluationResult
223block_plugin_gns_check_reply (void *cls,
224 enum GNUNET_BLOCK_Type type,
225 struct GNUNET_BLOCK_Group *group,
226 const struct GNUNET_HashCode *query,
227 const void *xquery,
228 size_t xquery_size,
229 const void *reply_block,
230 size_t reply_block_size)
231{
232 const struct GNUNET_GNSRECORD_Block *block = reply_block;
233 struct GNUNET_HashCode chash;
234
235 if (GNUNET_BLOCK_TYPE_GNS_NAMERECORD != type)
236 {
237 GNUNET_break (0);
238 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
239 }
240 GNUNET_assert (reply_block_size >= sizeof(struct GNUNET_GNSRECORD_Block));
241 GNUNET_assert (reply_block_size >= GNUNET_GNSRECORD_block_get_size (block));
242 GNUNET_CRYPTO_hash (reply_block,
243 reply_block_size,
244 &chash);
245 if (GNUNET_YES ==
246 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
247 &chash))
248 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
249 return GNUNET_BLOCK_REPLY_OK_MORE;
250}
251
252
253/**
254 * Entry point for the plugin.
255 */
256void *
257libgnunet_plugin_block_gns_init (void *cls)
258{
259 static const enum GNUNET_BLOCK_Type types[] = {
260 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
261 GNUNET_BLOCK_TYPE_ANY /* end of list */
262 };
263 struct GNUNET_BLOCK_PluginFunctions *api;
264
265 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
266 api->get_key = &block_plugin_gns_get_key;
267 api->create_group = &block_plugin_gns_create_group;
268 api->check_query = &block_plugin_gns_check_query;
269 api->check_block = &block_plugin_gns_check_block;
270 api->check_reply = &block_plugin_gns_check_reply;
271 api->types = types;
272 return api;
273}
274
275
276/**
277 * Exit point from the plugin.
278 */
279void *
280libgnunet_plugin_block_gns_done (void *cls)
281{
282 struct GNUNET_BLOCK_PluginFunctions *api = cls;
283
284 GNUNET_free (api);
285 return NULL;
286}
287
288
289/* end of plugin_block_gns.c */
diff --git a/src/plugin/gns/plugin_gnsrecord_gns.c b/src/plugin/gns/plugin_gnsrecord_gns.c
new file mode 100644
index 000000000..36e0c9fde
--- /dev/null
+++ b/src/plugin/gns/plugin_gnsrecord_gns.c
@@ -0,0 +1,515 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014, 2016 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 gns/plugin_gnsrecord_gns.c
23 * @brief gnsrecord plugin to provide the API for fundamental GNS records
24 * This includes the VPN record because GNS resolution
25 * is expected to understand VPN records and (if needed)
26 * map the result to A/AAAA.
27 * @author Christian Grothoff
28 */
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_gnsrecord_lib.h"
32#include "gnunet_gnsrecord_plugin.h"
33#include <inttypes.h>
34
35
36/**
37 * Convert the 'value' of a record to a string.
38 *
39 * @param cls closure, unused
40 * @param type type of the record
41 * @param data value in binary encoding
42 * @param data_size number of bytes in @a data
43 * @return NULL on error, otherwise human-readable representation of the value
44 */
45static char *
46gns_value_to_string (void *cls,
47 uint32_t type,
48 const void *data,
49 size_t data_size)
50{
51 const char *cdata;
52 struct GNUNET_CRYPTO_PublicKey pk;
53
54 switch (type)
55 {
56 case GNUNET_GNSRECORD_TYPE_PKEY:
57 case GNUNET_GNSRECORD_TYPE_EDKEY:
58 if (GNUNET_OK !=
59 GNUNET_GNSRECORD_identity_from_data (data,
60 data_size,
61 type,
62 &pk))
63 return NULL;
64 return GNUNET_CRYPTO_public_key_to_string (&pk);
65
66 case GNUNET_GNSRECORD_TYPE_NICK:
67 case GNUNET_GNSRECORD_TYPE_REDIRECT:
68 case GNUNET_GNSRECORD_TYPE_LEHO:
69 return GNUNET_strndup (data, data_size);
70
71 case GNUNET_GNSRECORD_TYPE_GNS2DNS: {
72 char *ns;
73 char *ip;
74 size_t off;
75 char *nstr;
76
77 off = 0;
78 ns = GNUNET_DNSPARSER_parse_name (data, data_size, &off);
79 if (NULL == ns)
80 {
81 GNUNET_break_op (0);
82 GNUNET_free (ns);
83 return NULL;
84 }
85 /* DNS server IP/name must be UTF-8 */
86 ip = GNUNET_strdup (&((const char*) data)[off]);
87 GNUNET_asprintf (&nstr, "%s@%s", ns, ip);
88 GNUNET_free (ns);
89 GNUNET_free (ip);
90 return nstr;
91 }
92
93 case GNUNET_GNSRECORD_TYPE_VPN: {
94 struct GNUNET_TUN_GnsVpnRecord vpn;
95 char *vpn_str;
96
97 cdata = data;
98 if ((data_size <= sizeof(vpn)) || ('\0' != cdata[data_size - 1]))
99 return NULL; /* malformed */
100 /* need to memcpy for alignment */
101 GNUNET_memcpy (&vpn, data, sizeof(vpn));
102 GNUNET_asprintf (&vpn_str,
103 "%u %s %s",
104 (unsigned int) ntohs (vpn.proto),
105 (const char *) GNUNET_i2s_full (&vpn.peer),
106 (const char *) &cdata[sizeof(vpn)]);
107 return vpn_str;
108 }
109
110 case GNUNET_GNSRECORD_TYPE_BOX: {
111 struct GNUNET_GNSRECORD_BoxRecord box;
112 uint32_t rt;
113 char *box_str;
114 char *ival;
115
116 cdata = data;
117 if (data_size < sizeof(struct GNUNET_GNSRECORD_BoxRecord))
118 return NULL; /* malformed */
119 GNUNET_memcpy (&box, data, sizeof(box));
120 rt = ntohl (box.record_type);
121 ival = GNUNET_GNSRECORD_value_to_string (rt,
122 &cdata[sizeof(box)],
123 data_size - sizeof(box));
124 if (NULL == ival)
125 return NULL; /* malformed */
126 GNUNET_asprintf (&box_str,
127 "%u %u %u %s",
128 (unsigned int) ntohs (box.protocol),
129 (unsigned int) ntohs (box.service),
130 (unsigned int) rt,
131 ival);
132 GNUNET_free (ival);
133 return box_str;
134 }
135 case GNUNET_GNSRECORD_TYPE_SBOX: {
136 struct GNUNET_GNSRECORD_SBoxRecord box;
137 uint32_t rt;
138 char *box_str;
139 char *ival;
140 char *prefix;
141
142 cdata = data;
143 if (data_size < sizeof(struct GNUNET_GNSRECORD_SBoxRecord))
144 return NULL; /* malformed */
145 GNUNET_memcpy (&box, data, sizeof(box));
146 rt = ntohl (box.record_type);
147
148 prefix = GNUNET_strdup (&cdata[sizeof(box)]);
149 ival = GNUNET_GNSRECORD_value_to_string (rt, &cdata[sizeof(box)
150 + strlen (prefix)
151 + 1],
152 data_size - sizeof(box)
153 - strlen (prefix) - 1);
154 if (NULL == ival)
155 return NULL; /* malformed */
156 GNUNET_asprintf (&box_str,
157 "%s %u %s",
158 prefix,
159 (unsigned int) rt,
160 ival);
161 GNUNET_free (prefix);
162 GNUNET_free (ival);
163 return box_str;
164 }
165 case GNUNET_GNSRECORD_TYPE_TOMBSTONE: {
166 return GNUNET_strdup (_ (
167 "This is a memento of an older block for internal maintenance."));
168 }
169 default:
170 return NULL;
171 }
172}
173
174
175/**
176 * Convert human-readable version of a 'value' of a record to the binary
177 * representation.
178 *
179 * @param cls closure, unused
180 * @param type type of the record
181 * @param s human-readable string
182 * @param data set to value in binary encoding (will be allocated)
183 * @param data_size set to number of bytes in @a data
184 * @return #GNUNET_OK on success
185 */
186static int
187gns_string_to_value (void *cls,
188 uint32_t type,
189 const char *s,
190 void **data,
191 size_t *data_size)
192{
193 struct GNUNET_CRYPTO_PublicKey pk;
194 uint32_t record_type;
195
196 if (NULL == s)
197 return GNUNET_SYSERR;
198 switch (type)
199 {
200 case GNUNET_GNSRECORD_TYPE_PKEY:
201 case GNUNET_GNSRECORD_TYPE_EDKEY:
202 if (GNUNET_OK !=
203 GNUNET_CRYPTO_public_key_from_string (s, &pk))
204 {
205 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
206 _ ("Unable to parse zone key record `%s'\n"),
207 s);
208 return GNUNET_SYSERR;
209 }
210 *data_size = GNUNET_CRYPTO_public_key_get_length (&pk);
211 if (GNUNET_OK !=
212 GNUNET_GNSRECORD_data_from_identity (&pk,
213 (char **) data,
214 data_size,
215 &record_type))
216 return GNUNET_SYSERR;
217 if (record_type != type)
218 {
219 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
220 _ ("Record type does not match parsed record type\n"));
221 return GNUNET_SYSERR;
222 }
223 return GNUNET_OK;
224
225 case GNUNET_GNSRECORD_TYPE_NICK:
226 case GNUNET_GNSRECORD_TYPE_REDIRECT:
227 case GNUNET_GNSRECORD_TYPE_LEHO:
228 *data = GNUNET_strdup (s);
229 *data_size = strlen (s);
230 return GNUNET_OK;
231
232 case GNUNET_GNSRECORD_TYPE_GNS2DNS: {
233 char nsbuf[514];
234 char *cpy;
235 char *at;
236 size_t off;
237
238 cpy = GNUNET_strdup (s);
239 at = strchr (cpy, '@');
240 if (NULL == at)
241 {
242 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
243 _ ("Unable to parse GNS2DNS record `%s'\n"),
244 s);
245 GNUNET_free (cpy);
246 return GNUNET_SYSERR;
247 }
248 *at = '\0';
249 at++;
250
251 off = 0;
252 if (GNUNET_OK !=
253 GNUNET_DNSPARSER_builder_add_name (nsbuf,
254 sizeof(nsbuf),
255 &off,
256 cpy))
257 {
258 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
259 _ (
260 "Failed to serialize GNS2DNS record with value `%s': Not a DNS name.\n"),
261 s);
262 GNUNET_free (cpy);
263 return GNUNET_SYSERR;
264 }
265 /* The DNS server location/name is in UTF-8 */
266 GNUNET_memcpy (&nsbuf[off], at, strlen (at) + 1);
267 off += strlen (at) + 1;
268 GNUNET_free (cpy);
269 *data_size = off;
270 *data = GNUNET_malloc (off);
271 GNUNET_memcpy (*data, nsbuf, off);
272 return GNUNET_OK;
273 }
274
275 case GNUNET_GNSRECORD_TYPE_VPN: {
276 struct GNUNET_TUN_GnsVpnRecord *vpn;
277 char s_peer[103 + 1];
278 char s_serv[253 + 1];
279 unsigned int proto;
280
281 if (3 != sscanf (s, "%u %103s %253s", &proto, s_peer, s_serv))
282 {
283 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
284 _ ("Unable to parse VPN record string `%s'\n"),
285 s);
286 return GNUNET_SYSERR;
287 }
288 *data_size = sizeof(struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1;
289 *data = vpn = GNUNET_malloc (*data_size);
290 if (GNUNET_OK !=
291 GNUNET_CRYPTO_eddsa_public_key_from_string ((char *) s_peer,
292 strlen (s_peer),
293 &vpn->peer.public_key))
294 {
295 GNUNET_free (vpn);
296 *data_size = 0;
297 return GNUNET_SYSERR;
298 }
299 vpn->proto = htons ((uint16_t) proto);
300 strcpy ((char *) &vpn[1], s_serv);
301 return GNUNET_OK;
302 }
303
304 case GNUNET_GNSRECORD_TYPE_BOX: {
305 struct GNUNET_GNSRECORD_BoxRecord *box;
306 size_t rest;
307 unsigned int protocol;
308 unsigned int service;
309 unsigned int record_type;
310 void *bval;
311 size_t bval_size;
312
313 if (3 != sscanf (s, "%u %u %u ", &protocol, &service, &record_type))
314 {
315 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
316 _ ("Unable to parse BOX record string `%s'\n"),
317 s);
318 return GNUNET_SYSERR;
319 }
320 rest = snprintf (NULL, 0, "%u %u %u ", protocol, service, record_type);
321 if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record_type,
322 &s[rest],
323 &bval,
324 &bval_size))
325 return GNUNET_SYSERR;
326 *data_size = sizeof(struct GNUNET_GNSRECORD_BoxRecord) + bval_size;
327 *data = box = GNUNET_malloc (*data_size);
328 box->protocol = htons (protocol);
329 box->service = htons (service);
330 box->record_type = htonl (record_type);
331 GNUNET_memcpy (&box[1], bval, bval_size);
332 GNUNET_free (bval);
333 return GNUNET_OK;
334 }
335 case GNUNET_GNSRECORD_TYPE_SBOX: {
336 struct GNUNET_GNSRECORD_SBoxRecord *box;
337 size_t rest;
338 char *prefix;
339 char *underscore_prefix;
340 unsigned int record_type;
341 void *bval;
342 size_t bval_size;
343 prefix = GNUNET_malloc (strlen (s));
344 size_t prefix_size;
345 if (2 != sscanf (s, "%s %u ", prefix, &record_type))
346 {
347 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
348 _ ("Unable to parse SBOX record string `%s'\n"),
349 s);
350 return GNUNET_SYSERR;
351 }
352 underscore_prefix = strrchr (prefix, '.');
353 if (underscore_prefix == NULL)
354 {
355 underscore_prefix = prefix;
356 }
357 else
358 {
359 underscore_prefix++;
360 }
361 if ('_' != underscore_prefix[0])
362 {
363 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
364 _ (
365 "Unable to parse SBOX record string `%s', the rightmost label `%s' does not start with an underscore\n"),
366 prefix, underscore_prefix);
367 return GNUNET_SYSERR;
368 }
369 rest = snprintf (NULL, 0, "%s %u ", prefix, record_type);
370 if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record_type,
371 &s[rest],
372 &bval,
373 &bval_size))
374 return GNUNET_SYSERR;
375 prefix_size = strlen (prefix) + 1;
376 *data_size = sizeof(struct GNUNET_GNSRECORD_SBoxRecord) + prefix_size
377 + bval_size;
378 void *p = *data = box = GNUNET_malloc (*data_size);
379 box->record_type = htonl (record_type);
380 p += sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
381 GNUNET_memcpy (p, prefix, prefix_size);
382 p += prefix_size;
383 GNUNET_memcpy (p, bval, bval_size);
384 GNUNET_free (bval);
385 GNUNET_free (prefix);
386 return GNUNET_OK;
387 }
388 case GNUNET_GNSRECORD_TYPE_TOMBSTONE: {
389 *data_size = 0;
390 *data = NULL;
391 return GNUNET_OK;
392 }
393
394 default:
395 return GNUNET_SYSERR;
396 }
397}
398
399
400/**
401 * Mapping of record type numbers to human-readable
402 * record type names.
403 */
404static struct
405{
406 const char *name;
407 uint32_t number;
408} gns_name_map[] = {
409 { "PKEY", GNUNET_GNSRECORD_TYPE_PKEY },
410 { "EDKEY", GNUNET_GNSRECORD_TYPE_EDKEY },
411 { "NICK", GNUNET_GNSRECORD_TYPE_NICK },
412 { "LEHO", GNUNET_GNSRECORD_TYPE_LEHO },
413 { "VPN", GNUNET_GNSRECORD_TYPE_VPN },
414 { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
415 { "BOX", GNUNET_GNSRECORD_TYPE_BOX },
416 { "SBOX", GNUNET_GNSRECORD_TYPE_SBOX },
417 { "REDIRECT", GNUNET_GNSRECORD_TYPE_REDIRECT },
418 /* Tombstones should never be added manually
419 * so this makes sense, kind of */
420 { "\u271E", GNUNET_GNSRECORD_TYPE_TOMBSTONE },
421 { NULL, UINT32_MAX }
422};
423
424
425/**
426 * Convert a type name (e.g. "AAAA") to the corresponding number.
427 *
428 * @param cls closure, unused
429 * @param gns_typename name to convert
430 * @return corresponding number, UINT32_MAX on error
431 */
432static uint32_t
433gns_typename_to_number (void *cls,
434 const char *gns_typename)
435{
436 unsigned int i;
437
438 i = 0;
439 while ((NULL != gns_name_map[i].name) &&
440 (0 != strcasecmp (gns_typename, gns_name_map[i].name)))
441 i++;
442 return gns_name_map[i].number;
443}
444
445
446/**
447 * Convert a type number to the corresponding type string (e.g. 1 to "A")
448 *
449 * @param cls closure, unused
450 * @param type number of a type to convert
451 * @return corresponding typestring, NULL on error
452 */
453static const char *
454gns_number_to_typename (void *cls,
455 uint32_t type)
456{
457 unsigned int i;
458
459 i = 0;
460 while ( (NULL != gns_name_map[i].name) &&
461 (type != gns_name_map[i].number) )
462 i++;
463 return gns_name_map[i].name;
464}
465
466
467static enum GNUNET_GenericReturnValue
468gns_is_critical (void *cls, uint32_t type)
469{
470 return ((type == GNUNET_GNSRECORD_TYPE_PKEY) ||
471 (type == GNUNET_GNSRECORD_TYPE_EDKEY) ||
472 (type == GNUNET_GNSRECORD_TYPE_GNS2DNS) ||
473 (type == GNUNET_GNSRECORD_TYPE_REDIRECT) ?
474 GNUNET_YES : GNUNET_NO);
475}
476
477
478/**
479 * Entry point for the plugin.
480 *
481 * @param cls NULL
482 * @return the exported block API
483 */
484void *
485libgnunet_plugin_gnsrecord_gns_init (void *cls)
486{
487 struct GNUNET_GNSRECORD_PluginFunctions *api;
488
489 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
490 api->value_to_string = &gns_value_to_string;
491 api->string_to_value = &gns_string_to_value;
492 api->typename_to_number = &gns_typename_to_number;
493 api->number_to_typename = &gns_number_to_typename;
494 api->is_critical = &gns_is_critical;
495 return api;
496}
497
498
499/**
500 * Exit point from the plugin.
501 *
502 * @param cls the return value from #libgnunet_plugin_block_test_init()
503 * @return NULL
504 */
505void *
506libgnunet_plugin_gnsrecord_gns_done (void *cls)
507{
508 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
509
510 GNUNET_free (api);
511 return NULL;
512}
513
514
515/* end of plugin_gnsrecord_gns.c */