GNUnet 0.21.1
plugin_gnsrecord_gns.c
Go to the documentation of this file.
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
29#include "platform.h"
30#include "gnunet_util_lib.h"
33#include <inttypes.h>
34
35
45static char *
47 uint32_t type,
48 const void *data,
49 size_t data_size)
50{
51 const char *cdata;
53
54 switch (type)
55 {
58 if (GNUNET_OK !=
61 type,
62 &pk))
63 return NULL;
65
70
72 char *ns;
73 char *ip;
74 size_t off;
75 char *nstr;
76
77 off = 0;
79 if (NULL == ns)
80 {
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);
89 GNUNET_free (ip);
90 return nstr;
91 }
92
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
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);
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 }
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);
162 GNUNET_free (ival);
163 return box_str;
164 }
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
186static int
188 uint32_t type,
189 const char *s,
190 void **data,
191 size_t *data_size)
192{
194 uint32_t record_type;
195
196 if (NULL == s)
197 return GNUNET_SYSERR;
198 switch (type)
199 {
202 if (GNUNET_OK !=
204 {
206 _ ("Unable to parse zone key record `%s'\n"),
207 s);
208 return GNUNET_SYSERR;
209 }
211 if (GNUNET_OK !=
213 (char **) data,
214 data_size,
215 &record_type))
216 return GNUNET_SYSERR;
217 if (record_type != type)
218 {
220 _ ("Record type does not match parsed record type\n"));
221 return GNUNET_SYSERR;
222 }
223 return GNUNET_OK;
224
228 *data = GNUNET_strdup (s);
229 *data_size = strlen (s);
230 return GNUNET_OK;
231
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 {
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 !=
254 sizeof(nsbuf),
255 &off,
256 cpy))
257 {
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
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 {
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 !=
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
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 {
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);
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 }
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 {
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 {
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);
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);
386 return GNUNET_OK;
387 }
389 *data_size = 0;
390 *data = NULL;
391 return GNUNET_OK;
392 }
393
394 default:
395 return GNUNET_SYSERR;
396 }
397}
398
399
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 */
421 { NULL, UINT32_MAX }
423
424
432static uint32_t
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
453static const char *
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
468gns_is_critical (void *cls, uint32_t type)
469{
470 return ((type == GNUNET_GNSRECORD_TYPE_PKEY) ||
475}
476
477
484void *
486{
488
495 return api;
496}
497
498
505void *
507{
509
510 GNUNET_free (api);
511 return NULL;
512}
513
514
515/* end of plugin_gnsrecord_gns.c */
static int prefix
If printing the value of PREFIX has been requested.
Definition: gnunet-config.c:59
static char * data
The data to insert into the dht.
struct GNUNET_CRYPTO_PrivateKey pk
Private key from command line option, or NULL.
static struct GNUNET_NAMECACHE_Handle * ns
Handle to the namecache.
static uint32_t type
Type string converted to DNS type value.
static size_t data_size
Number of bytes in data.
static uint8_t proto
Protocol to use.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
API that can be used to manipulate GNS record data.
Plugin API for GNS record types.
int GNUNET_DNSPARSER_builder_add_name(char *dst, size_t dst_len, size_t *off, const char *name)
Add a DNS name to the UDP packet at the given location, converting the name to IDNA notation as neces...
Definition: dnsparser.c:982
char * GNUNET_DNSPARSER_parse_name(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse name inside of a DNS query or record.
Definition: dnsparser.c:353
int GNUNET_GNSRECORD_string_to_value(uint32_t type, const char *s, void **data, size_t *data_size)
Convert human-readable version of the value s of a record of type type to the respective binary repre...
Definition: gnsrecord.c:177
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_data_from_identity(const struct GNUNET_CRYPTO_PublicKey *key, char **data, size_t *data_size, uint32_t *type)
Create record data and size from an identity key.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_CRYPTO_PublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
char * GNUNET_GNSRECORD_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the binary value data of a record of type type to a human-readable string.
Definition: gnsrecord.c:155
ssize_t GNUNET_CRYPTO_public_key_get_length(const struct GNUNET_CRYPTO_PublicKey *key)
Get the compacted length of a GNUNET_CRYPTO_PublicKey.
Definition: crypto_pkey.c:68
#define GNUNET_log(kind,...)
char * GNUNET_CRYPTO_public_key_to_string(const struct GNUNET_CRYPTO_PublicKey *key)
Creates a (Base32) string representation of the public key.
Definition: crypto_pkey.c:551
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_public_key_from_string(const char *enc, size_t enclen, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Convert a string representing a public key to a public key.
Definition: crypto_ecc.c:358
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_public_key_from_string(const char *str, struct GNUNET_CRYPTO_PublicKey *key)
Parses a (Base32) string representation of the public key.
Definition: crypto_pkey.c:571
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_ERROR
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
void * libgnunet_plugin_gnsrecord_gns_init(void *cls)
Entry point for the plugin.
static char * gns_value_to_string(void *cls, uint32_t type, const void *data, size_t data_size)
Convert the 'value' of a record to a string.
static int gns_string_to_value(void *cls, uint32_t type, const char *s, void **data, size_t *data_size)
Convert human-readable version of a 'value' of a record to the binary representation.
static const char * gns_number_to_typename(void *cls, uint32_t type)
Convert a type number to the corresponding type string (e.g.
static struct @37 gns_name_map[]
Mapping of record type numbers to human-readable record type names.
const char * name
uint32_t number
static uint32_t gns_typename_to_number(void *cls, const char *gns_typename)
Convert a type name (e.g.
void * libgnunet_plugin_gnsrecord_gns_done(void *cls)
Exit point from the plugin.
static enum GNUNET_GenericReturnValue gns_is_critical(void *cls, uint32_t type)
#define GNUNET_GNSRECORD_TYPE_BOX
Box record.
#define GNUNET_GNSRECORD_TYPE_NICK
GNS zone nickname.
#define GNUNET_GNSRECORD_TYPE_TOMBSTONE
Record type to indicate a previously delete record (PRIVATE only)
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Delegation to DNS.
#define GNUNET_GNSRECORD_TYPE_REDIRECT
Redirection record.
#define GNUNET_GNSRECORD_TYPE_VPN
VPN resolution.
#define GNUNET_GNSRECORD_TYPE_LEHO
GNS legacy hostname.
#define GNUNET_GNSRECORD_TYPE_SBOX
SBox record.
#define GNUNET_GNSRECORD_TYPE_PKEY
WARNING: This header is generated! In order to add GNS record types, you must register them in GANA,...
#define GNUNET_GNSRECORD_TYPE_EDKEY
GNS zone delegation (EDKEY)
An identity key as per LSD0001.
Record type used to box up SRV and TLSA records.
uint32_t record_type
GNS record type of the boxed record.
uint16_t service
Service of the boxed record (aka port number), in NBO.
uint16_t protocol
Protocol of the boxed record (6 = TCP, 17 = UDP, etc.).
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
GNUNET_GNSRECORD_IsCriticalFunction is_critical
Is critical.
GNUNET_GNSRECORD_TypenameToNumberFunction typename_to_number
Typename to number.
GNUNET_GNSRECORD_NumberToTypenameFunction number_to_typename
Number to typename.
GNUNET_GNSRECORD_ValueToStringFunction value_to_string
Conversion to string.
void * cls
Closure for all of the callbacks.
GNUNET_GNSRECORD_StringToValueFunction string_to_value
Conversion to binary.
Record type used to box up SMIMEA records.
uint32_t record_type
GNS record type of the boxed record.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Payload of GNS VPN record.
struct GNUNET_PeerIdentity peer
The peer to contact.
uint16_t proto
The protocol to use.