2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file namestore/namestore_api_common.c
23 * @brief API to access the NAMESTORE service
24 * @author Martin Schanzenbach
25 * @author Matthias Wachs
26 * @author Christian Grothoff
29 #include "gnunet_util_lib.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_signatures.h"
32 #include "gnunet_arm_service.h"
33 #include "gnunet_namestore_service.h"
34 #include "gnunet_dnsparser_lib.h"
35 #include "gnunet_tun_lib.h"
36 #include "namestore.h"
39 #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__)
41 GNUNET_NETWORK_STRUCT_BEGIN
45 * Internal format of a record in the serialized form.
51 * Expiration time for the DNS record; relative or absolute depends
52 * on 'flags', network byte order.
54 uint64_t expiration_time GNUNET_PACKED;
57 * Number of bytes in 'data', network byte order.
59 uint32_t data_size GNUNET_PACKED;
62 * Type of the GNS/DNS record, network byte order.
64 uint32_t record_type GNUNET_PACKED;
67 * Flags for the record, network byte order.
69 uint32_t flags GNUNET_PACKED;
73 GNUNET_NETWORK_STRUCT_END
76 * Convert a UTF-8 string to UTF-8 lowercase
77 * @param src source string
78 * @return converted result
81 GNUNET_NAMESTORE_normalize_string (const char *src)
83 GNUNET_assert (NULL != src);
84 char *res = strdup (src);
86 GNUNET_STRINGS_utf8_tolower(src, &res);
92 * Convert a zone key to a string (for printing debug messages).
93 * This is one of the very few calls in the entire API that is
96 * @param z the zone key
97 * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s
100 GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EccPublicSignKey *z)
102 static char buf[sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) * 8];
105 end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z,
106 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey),
119 * Calculate how many bytes we will need to serialize the given
122 * @param rd_count number of records in the rd array
123 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
124 * @return the required size to serialize
127 GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
128 const struct GNUNET_NAMESTORE_RecordData *rd)
133 ret = sizeof (struct NetworkRecord) * rd_count;
134 for (i=0;i<rd_count;i++)
136 GNUNET_assert ((ret + rd[i].data_size) >= ret);
137 ret += rd[i].data_size;
144 * Serialize the given records to the given destination buffer.
146 * @param rd_count number of records in the rd array
147 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
148 * @param dest_size size of the destination array
149 * @param dest where to write the result
150 * @return the size of serialized records, -1 if records do not fit
153 GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
154 const struct GNUNET_NAMESTORE_RecordData *rd,
158 struct NetworkRecord rec;
163 for (i=0;i<rd_count;i++)
165 rec.expiration_time = GNUNET_htonll (rd[i].expiration_time);
166 rec.data_size = htonl ((uint32_t) rd[i].data_size);
167 rec.record_type = htonl (rd[i].record_type);
168 rec.flags = htonl (rd[i].flags);
169 if (off + sizeof (rec) > dest_size)
171 memcpy (&dest[off], &rec, sizeof (rec));
173 if (off + rd[i].data_size > dest_size)
175 memcpy (&dest[off], rd[i].data, rd[i].data_size);
176 off += rd[i].data_size;
183 * Compares if two records are equal (ignoring flags such
184 * as authority, private and pending, but not relative vs.
185 * absolute expiration time).
189 * @return #GNUNET_YES if the records are equal or #GNUNET_NO if they are not
192 GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
193 const struct GNUNET_NAMESTORE_RecordData *b)
195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
196 "Comparing records\n");
197 if (a->record_type != b->record_type)
199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
200 "Record type %lu != %lu\n", a->record_type, b->record_type);
203 if ((a->expiration_time != b->expiration_time) &&
204 ((a->expiration_time != 0) && (b->expiration_time != 0)))
206 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
207 "Expiration time %llu != %llu\n", a->expiration_time, b->expiration_time);
210 if ((a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS)
211 != (b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS))
213 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
214 "Flags %lu (%lu) != %lu (%lu)\n", a->flags,
215 a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS, b->flags,
216 b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS);
219 if (a->data_size != b->data_size)
221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
222 "Data size %lu != %lu\n", a->data_size, b->data_size);
225 if (0 != memcmp (a->data, b->data, a->data_size))
227 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
228 "Data contents do not match\n");
231 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
232 "Records are equal\n");
238 * Deserialize the given records to the given destination.
240 * @param len size of the serialized record data
241 * @param src the serialized record data
242 * @param rd_count number of records in the rd array
243 * @param dest where to put the data
244 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
247 GNUNET_NAMESTORE_records_deserialize (size_t len,
249 unsigned int rd_count,
250 struct GNUNET_NAMESTORE_RecordData *dest)
252 struct NetworkRecord rec;
257 for (i=0;i<rd_count;i++)
259 if (off + sizeof (rec) > len)
260 return GNUNET_SYSERR;
261 memcpy (&rec, &src[off], sizeof (rec));
262 dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time);
263 dest[i].data_size = ntohl ((uint32_t) rec.data_size);
264 dest[i].record_type = ntohl (rec.record_type);
265 dest[i].flags = ntohl (rec.flags);
268 if (off + dest[i].data_size > len)
269 return GNUNET_SYSERR;
270 dest[i].data = &src[off];
271 off += dest[i].data_size;
278 * Returns the expiration time of the given block of records. The block
279 * expiration time is the expiration time of the block with smallest
282 * @param rd_count number of records given in @a rd
283 * @param rd array of records
284 * @return absolute expiration time
286 struct GNUNET_TIME_Absolute
287 GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count,
288 const struct GNUNET_NAMESTORE_RecordData *rd)
291 struct GNUNET_TIME_Absolute expire;
292 struct GNUNET_TIME_Absolute at;
293 struct GNUNET_TIME_Relative rt;
296 return GNUNET_TIME_UNIT_ZERO_ABS;
297 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
298 for (c = 0; c < rd_count; c++)
300 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
302 rt.rel_value_us = rd[c].expiration_time;
303 at = GNUNET_TIME_relative_to_absolute (rt);
307 at.abs_value_us = rd[c].expiration_time;
309 expire = GNUNET_TIME_absolute_min (at, expire);
316 * Derive session key and iv from label and public key.
318 * @param iv initialization vector to initialize
319 * @param skey session key to initialize
320 * @param label label to use for KDF
321 * @param pub public key to use for KDF
324 derive_block_aes_key (struct GNUNET_CRYPTO_AesInitializationVector *iv,
325 struct GNUNET_CRYPTO_AesSessionKey *skey,
327 const struct GNUNET_CRYPTO_EccPublicSignKey *pub)
329 static const char ctx_key[] = "gns-aes-ctx-key";
330 static const char ctx_iv[] = "gns-aes-ctx-iv";
332 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_AesSessionKey),
333 pub, sizeof (struct GNUNET_CRYPTO_EccPublicSignKey),
334 label, strlen (label),
335 ctx_key, strlen (ctx_key),
337 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_AesInitializationVector),
338 pub, sizeof (struct GNUNET_CRYPTO_EccPublicSignKey),
339 label, strlen (label),
340 ctx_iv, strlen (ctx_iv),
346 * Sign name and records
348 * @param key the private key
349 * @param expire block expiration
350 * @param label the name for the records
351 * @param rd record data
352 * @param rd_count number of records
353 * @return NULL on error (block too large)
355 struct GNUNET_NAMESTORE_Block *
356 GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EccPrivateKey *key,
357 struct GNUNET_TIME_Absolute expire,
359 const struct GNUNET_NAMESTORE_RecordData *rd,
360 unsigned int rd_count)
362 size_t payload_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
363 char payload[sizeof (uint32_t) + payload_len];
364 struct GNUNET_NAMESTORE_Block *block;
365 struct GNUNET_CRYPTO_EccPublicSignKey pkey;
366 struct GNUNET_CRYPTO_EccPrivateKey *dkey;
367 struct GNUNET_CRYPTO_AesInitializationVector iv;
368 struct GNUNET_CRYPTO_AesSessionKey skey;
369 uint32_t rd_count_nbo;
371 if (payload_len > GNUNET_NAMESTORE_MAX_VALUE_SIZE)
373 rd_count_nbo = htonl (rd_count);
374 memcpy (payload, &rd_count_nbo, sizeof (uint32_t));
375 GNUNET_assert (payload_len ==
376 GNUNET_NAMESTORE_records_serialize (rd_count, rd,
377 payload_len, &payload[sizeof (uint32_t)]));
378 block = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Block) +
379 sizeof (uint32_t) + payload_len);
380 block->purpose.size = htonl (sizeof (uint32_t) + payload_len +
381 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
382 sizeof (struct GNUNET_TIME_AbsoluteNBO));
383 block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
384 block->expiration_time = GNUNET_TIME_absolute_hton (expire);
385 dkey = GNUNET_CRYPTO_ecc_key_derive (key,
388 GNUNET_CRYPTO_ecc_key_get_public_for_signature (dkey,
389 &block->derived_key);
390 GNUNET_CRYPTO_ecc_key_get_public_for_signature (key,
392 derive_block_aes_key (&iv, &skey, label, &pkey);
393 GNUNET_break (payload_len + sizeof (uint32_t) ==
394 GNUNET_CRYPTO_aes_encrypt (payload, payload_len + sizeof (uint32_t),
398 GNUNET_CRYPTO_ecc_sign (dkey,
413 * Check if a signature is valid. This API is used by the GNS Block
414 * to validate signatures received from the network.
416 * @param block block to verify
417 * @return #GNUNET_OK if the signature is valid
420 GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block)
422 return GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN,
425 &block->derived_key);
432 * @param block block to decrypt
433 * @param zone_key public key of the zone
434 * @param label the name for the records
435 * @param proc function to call with the result
436 * @param proc_cls closure for proc
437 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was
441 GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
442 const struct GNUNET_CRYPTO_EccPublicSignKey *zone_key,
444 GNUNET_NAMESTORE_RecordCallback proc,
447 size_t payload_len = ntohl (block->purpose.size) -
448 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) -
449 sizeof (struct GNUNET_TIME_AbsoluteNBO);
450 struct GNUNET_CRYPTO_AesInitializationVector iv;
451 struct GNUNET_CRYPTO_AesSessionKey skey;
453 if (ntohl (block->purpose.size) <
454 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
455 sizeof (struct GNUNET_TIME_AbsoluteNBO))
458 return GNUNET_SYSERR;
460 derive_block_aes_key (&iv, &skey, label, zone_key);
462 char payload[payload_len];
465 GNUNET_break (payload_len ==
466 GNUNET_CRYPTO_aes_decrypt (&block[1], payload_len,
472 rd_count = ntohl (rd_count);
475 /* limit to sane value */
477 return GNUNET_SYSERR;
480 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
483 GNUNET_NAMESTORE_records_deserialize (payload_len - sizeof (uint32_t),
484 &payload[sizeof (uint32_t)],
489 return GNUNET_SYSERR;
492 proc (proc_cls, rd_count, (0 != rd_count) ? rd : NULL);
500 * Convert the 'value' of a record to a string.
502 * @param type type of the record
503 * @param data value in binary encoding
504 * @param data_size number of bytes in @a data
505 * @return NULL on error, otherwise human-readable representation of the value
508 GNUNET_NAMESTORE_value_to_string (uint32_t type,
512 struct GNUNET_CRYPTO_HashAsciiEncoded s_peer;
515 char tmp[INET6_ADDRSTRLEN];
521 case GNUNET_DNSPARSER_TYPE_A:
522 if (data_size != sizeof (struct in_addr))
524 if (NULL == inet_ntop (AF_INET, data, tmp, sizeof (tmp)))
526 return GNUNET_strdup (tmp);
527 case GNUNET_DNSPARSER_TYPE_NS:
533 ns = GNUNET_DNSPARSER_parse_name (data,
544 case GNUNET_DNSPARSER_TYPE_CNAME:
550 cname = GNUNET_DNSPARSER_parse_name (data,
553 if ( (NULL == cname) ||
561 case GNUNET_DNSPARSER_TYPE_SOA:
563 struct GNUNET_DNSPARSER_SoaRecord *soa;
567 soa = GNUNET_DNSPARSER_parse_soa (data,
570 if ( (NULL == soa) ||
576 GNUNET_asprintf (&result,
577 "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu",
585 GNUNET_DNSPARSER_free_soa (soa);
588 case GNUNET_DNSPARSER_TYPE_PTR:
594 ptr = GNUNET_DNSPARSER_parse_name (data,
597 if ( (NULL == ptr) ||
605 case GNUNET_DNSPARSER_TYPE_MX:
607 struct GNUNET_DNSPARSER_MxRecord *mx;
611 mx = GNUNET_DNSPARSER_parse_mx (data,
620 GNUNET_asprintf (&result,
624 GNUNET_DNSPARSER_free_mx (mx);
627 case GNUNET_DNSPARSER_TYPE_TXT:
628 return GNUNET_strndup (data, data_size);
629 case GNUNET_DNSPARSER_TYPE_AAAA:
630 if (data_size != sizeof (struct in6_addr))
632 if (NULL == inet_ntop (AF_INET6, data, tmp, sizeof (tmp)))
634 return GNUNET_strdup (tmp);
635 case GNUNET_NAMESTORE_TYPE_PKEY:
636 if (data_size != sizeof (struct GNUNET_CRYPTO_EccPublicSignKey))
638 return GNUNET_CRYPTO_ecc_public_sign_key_to_string (data);
639 case GNUNET_NAMESTORE_TYPE_PSEU:
640 return GNUNET_strndup (data, data_size);
641 case GNUNET_NAMESTORE_TYPE_LEHO:
642 return GNUNET_strndup (data, data_size);
643 case GNUNET_NAMESTORE_TYPE_VPN:
645 const struct GNUNET_TUN_GnsVpnRecord *vpn;
649 if ( (data_size <= sizeof (struct GNUNET_TUN_GnsVpnRecord)) ||
650 ('\0' != cdata[data_size - 1]) )
651 return NULL; /* malformed */
653 GNUNET_CRYPTO_hash_to_enc (&vpn->peer.hashPubKey, &s_peer);
654 if (0 == GNUNET_asprintf (&vpn_str, "%u %s %s",
655 (unsigned int) ntohs (vpn->proto),
656 (const char*) &s_peer,
657 (const char*) &vpn[1]))
659 GNUNET_free (vpn_str);
664 case GNUNET_NAMESTORE_TYPE_GNS2DNS:
670 ns = GNUNET_DNSPARSER_parse_name (data,
681 case GNUNET_DNSPARSER_TYPE_SRV:
683 struct GNUNET_DNSPARSER_SrvRecord *srv;
687 srv = GNUNET_DNSPARSER_parse_srv ("+", /* FIXME: is this OK? */
691 if ( (NULL == srv) ||
697 GNUNET_asprintf (&result,
698 "%d %d %d _%s._%s.%s",
705 GNUNET_DNSPARSER_free_srv (srv);
708 case GNUNET_DNSPARSER_TYPE_TLSA:
710 const struct GNUNET_TUN_DnsTlsaRecord *tlsa;
714 if ( (data_size <= sizeof (struct GNUNET_TUN_DnsTlsaRecord)) ||
715 ('\0' != cdata[data_size - 1]) )
716 return NULL; /* malformed */
718 if (0 == GNUNET_asprintf (&tlsa_str,
723 (const char *) &tlsa[1]))
725 GNUNET_free (tlsa_str);
733 GNUNET_break (0); // not implemented
739 * Convert human-readable version of a 'value' of a record to the binary
742 * @param type type of the record
743 * @param s human-readable string
744 * @param data set to value in binary encoding (will be allocated)
745 * @param data_size set to number of bytes in @a data
746 * @return #GNUNET_OK on success
749 GNUNET_NAMESTORE_string_to_value (uint32_t type,
754 struct in_addr value_a;
755 struct in6_addr value_aaaa;
756 struct GNUNET_CRYPTO_EccPublicSignKey pkey;
757 struct GNUNET_TUN_GnsVpnRecord *vpn;
758 struct GNUNET_TUN_DnsTlsaRecord *tlsa;
759 char s_peer[103 + 1];
760 char s_serv[253 + 1];
764 return GNUNET_SYSERR;
768 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
769 _("Unsupported record type %d\n"),
771 return GNUNET_SYSERR;
772 case GNUNET_DNSPARSER_TYPE_A:
773 if (1 != inet_pton (AF_INET, s, &value_a))
775 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
776 _("Unable to parse IPv4 address `%s'\n"),
778 return GNUNET_SYSERR;
780 *data = GNUNET_malloc (sizeof (struct in_addr));
781 memcpy (*data, &value_a, sizeof (value_a));
782 *data_size = sizeof (value_a);
784 case GNUNET_DNSPARSER_TYPE_NS:
791 GNUNET_DNSPARSER_builder_add_name (nsbuf,
796 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
797 _("Failed to serialize NS record with value `%s'\n"),
799 return GNUNET_SYSERR;
802 *data = GNUNET_malloc (off);
803 memcpy (*data, nsbuf, off);
806 case GNUNET_DNSPARSER_TYPE_CNAME:
813 GNUNET_DNSPARSER_builder_add_name (cnamebuf,
818 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
819 _("Failed to serialize CNAME record with value `%s'\n"),
821 return GNUNET_SYSERR;
824 *data = GNUNET_malloc (off);
825 memcpy (*data, cnamebuf, off);
828 case GNUNET_DNSPARSER_TYPE_SOA:
830 struct GNUNET_DNSPARSER_SoaRecord soa;
832 char soa_rname[253 + 1];
833 char soa_mname[253 + 1];
834 unsigned int soa_serial;
835 unsigned int soa_refresh;
836 unsigned int soa_retry;
837 unsigned int soa_expire;
838 unsigned int soa_min;
842 "rname=%253s mname=%253s %u,%u,%u,%u,%u",
843 soa_rname, soa_mname,
844 &soa_serial, &soa_refresh, &soa_retry, &soa_expire, &soa_min))
846 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
847 _("Unable to parse SOA record `%s'\n"),
849 return GNUNET_SYSERR;
851 soa.mname = soa_mname;
852 soa.rname = soa_rname;
853 soa.serial = (uint32_t) soa_serial;
854 soa.refresh =(uint32_t) soa_refresh;
855 soa.retry = (uint32_t) soa_retry;
856 soa.expire = (uint32_t) soa_expire;
857 soa.minimum_ttl = (uint32_t) soa_min;
860 GNUNET_DNSPARSER_builder_add_soa (soabuf,
865 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
866 _("Failed to serialize SOA record with mname `%s' and rname `%s'\n"),
869 return GNUNET_SYSERR;
872 *data = GNUNET_malloc (off);
873 memcpy (*data, soabuf, off);
876 case GNUNET_DNSPARSER_TYPE_PTR:
883 GNUNET_DNSPARSER_builder_add_name (ptrbuf,
888 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
889 _("Failed to serialize PTR record with value `%s'\n"),
891 return GNUNET_SYSERR;
894 *data = GNUNET_malloc (off);
895 memcpy (*data, ptrbuf, off);
898 case GNUNET_DNSPARSER_TYPE_MX:
900 struct GNUNET_DNSPARSER_MxRecord mx;
902 char mxhost[253 + 1];
906 if (2 != SSCANF(s, "%hu,%253s", &mx_pref, mxhost))
908 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
909 _("Unable to parse MX record `%s'\n"),
911 return GNUNET_SYSERR;
913 mx.preference = mx_pref;
918 GNUNET_DNSPARSER_builder_add_mx (mxbuf,
923 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
924 _("Failed to serialize MX record with hostname `%s'\n"),
926 return GNUNET_SYSERR;
929 *data = GNUNET_malloc (off);
930 memcpy (*data, mxbuf, off);
933 case GNUNET_DNSPARSER_TYPE_TXT:
934 *data = GNUNET_strdup (s);
935 *data_size = strlen (s);
937 case GNUNET_DNSPARSER_TYPE_AAAA:
938 if (1 != inet_pton (AF_INET6, s, &value_aaaa))
940 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
941 _("Unable to parse IPv6 address `%s'\n"),
943 return GNUNET_SYSERR;
945 *data = GNUNET_malloc (sizeof (struct in6_addr));
946 *data_size = sizeof (struct in6_addr);
947 memcpy (*data, &value_aaaa, sizeof (value_aaaa));
949 case GNUNET_NAMESTORE_TYPE_PKEY:
951 GNUNET_CRYPTO_ecc_public_sign_key_from_string (s, strlen (s), &pkey))
953 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
954 _("Unable to parse PKEY record `%s'\n"),
956 return GNUNET_SYSERR;
958 *data = GNUNET_new (struct GNUNET_CRYPTO_EccPublicSignKey);
959 memcpy (*data, &pkey, sizeof (pkey));
960 *data_size = sizeof (struct GNUNET_CRYPTO_EccPublicSignKey);
962 case GNUNET_NAMESTORE_TYPE_PSEU:
963 *data = GNUNET_strdup (s);
964 *data_size = strlen (s);
966 case GNUNET_NAMESTORE_TYPE_LEHO:
967 *data = GNUNET_strdup (s);
968 *data_size = strlen (s);
970 case GNUNET_NAMESTORE_TYPE_VPN:
971 if (3 != SSCANF (s,"%u %103s %253s",
972 &proto, s_peer, s_serv))
974 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
975 _("Unable to parse VPN record string `%s'\n"),
977 return GNUNET_SYSERR;
979 *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1;
980 *data = vpn = GNUNET_malloc (*data_size);
981 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char*)&s_peer,
982 &vpn->peer.hashPubKey))
986 return GNUNET_SYSERR;
988 vpn->proto = htons ((uint16_t) proto);
989 strcpy ((char*)&vpn[1], s_serv);
991 case GNUNET_NAMESTORE_TYPE_GNS2DNS:
998 GNUNET_DNSPARSER_builder_add_name (nsbuf,
1003 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1004 _("Failed to serialize GNS2DNS record with value `%s'\n"),
1006 return GNUNET_SYSERR;
1009 *data = GNUNET_malloc (off);
1010 memcpy (*data, nsbuf, off);
1013 case GNUNET_DNSPARSER_TYPE_TLSA:
1014 *data_size = sizeof (struct GNUNET_TUN_DnsTlsaRecord) + strlen (s) - 6;
1015 *data = tlsa = GNUNET_malloc (*data_size);
1016 if (4 != SSCANF (s, "%c %c %c %s",
1019 &tlsa->matching_type,
1022 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1023 _("Unable to parse TLSA record string `%s'\n"),
1027 return GNUNET_SYSERR;
1031 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1032 _("Unsupported record type %d\n"),
1034 return GNUNET_SYSERR;
1040 * Mapping of record type numbers to human-readable
1041 * record type names.
1047 { "A", GNUNET_DNSPARSER_TYPE_A },
1048 { "NS", GNUNET_DNSPARSER_TYPE_NS },
1049 { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME },
1050 { "SOA", GNUNET_DNSPARSER_TYPE_SOA },
1051 { "PTR", GNUNET_DNSPARSER_TYPE_PTR },
1052 { "MX", GNUNET_DNSPARSER_TYPE_MX },
1053 { "TXT", GNUNET_DNSPARSER_TYPE_TXT },
1054 { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA },
1055 { "PKEY", GNUNET_NAMESTORE_TYPE_PKEY },
1056 { "PSEU", GNUNET_NAMESTORE_TYPE_PSEU },
1057 { "LEHO", GNUNET_NAMESTORE_TYPE_LEHO },
1058 { "VPN", GNUNET_NAMESTORE_TYPE_VPN },
1059 { "GNS2DNS", GNUNET_NAMESTORE_TYPE_GNS2DNS },
1060 { "TLSA", GNUNET_DNSPARSER_TYPE_TLSA },
1061 { NULL, UINT32_MAX }
1066 * Convert a type name (i.e. "AAAA") to the corresponding number.
1068 * @param typename name to convert
1069 * @return corresponding number, UINT32_MAX on error
1072 GNUNET_NAMESTORE_typename_to_number (const char *typename)
1077 while ( (name_map[i].name != NULL) &&
1078 (0 != strcasecmp (typename, name_map[i].name)) )
1080 return name_map[i].number;
1085 * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
1087 * @param type number of a type to convert
1088 * @return corresponding typestring, NULL on error
1091 GNUNET_NAMESTORE_number_to_typename (uint32_t type)
1096 while ( (name_map[i].name != NULL) &&
1097 (type != name_map[i].number) )
1099 return name_map[i].name;
1104 * Test if a given record is expired.
1106 * @return #GNUNET_YES if the record is expired,
1110 GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd)
1112 struct GNUNET_TIME_Absolute at;
1114 if (0 != (rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
1116 at.abs_value_us = rd->expiration_time;
1117 return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ? GNUNET_YES : GNUNET_NO;
1122 * Calculate the DHT query for a given @a label in a given @a zone.
1124 * @param zone private key of the zone
1125 * @param label label of the record
1126 * @param query hash to use for the query
1129 GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EccPrivateKey *zone,
1131 struct GNUNET_HashCode *query)
1133 struct GNUNET_CRYPTO_EccPublicSignKey pub;
1135 GNUNET_CRYPTO_ecc_key_get_public_for_signature (zone, &pub);
1136 GNUNET_NAMESTORE_query_from_public_key (&pub, label, query);
1141 * Calculate the DHT query for a given @a label in a given @a zone.
1143 * @param pub public key of the zone
1144 * @param label label of the record
1145 * @param query hash to use for the query
1148 GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EccPublicSignKey *pub,
1150 struct GNUNET_HashCode *query)
1152 struct GNUNET_CRYPTO_EccPublicSignKey pd;
1154 GNUNET_CRYPTO_ecc_public_key_derive (pub, label, "gns", &pd);
1155 GNUNET_CRYPTO_hash (&pd, sizeof (pd), query);
1160 * Convert public key to the respective absolute domain name in the
1162 * This is one of the very few calls in the entire API that is
1165 * @param pkey a public key with a point on the eliptic curve
1166 * @return string "X.zkey" where X is the public
1167 * key in an encoding suitable for DNS labels.
1170 GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EccPublicSignKey *pkey)
1172 static char ret[128];
1175 pkeys = GNUNET_CRYPTO_ecc_public_sign_key_to_string (pkey);
1176 GNUNET_snprintf (ret,
1180 GNUNET_free (pkeys);
1186 * Convert an absolute domain name in the ".zkey" pTLD to the
1187 * respective public key.
1189 * @param zkey string "X.zkey" where X is the coordinates of the public
1190 * key in an encoding suitable for DNS labels.
1191 * @param pkey set to a public key on the eliptic curve
1192 * @return #GNUNET_SYSERR if @a zkey has the wrong syntax
1195 GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey,
1196 struct GNUNET_CRYPTO_EccPublicSignKey *pkey)
1202 cpy = GNUNET_strdup (zkey);
1204 if (NULL == (dot = strchr (x, (int) '.')))
1207 if (0 != strcasecmp (dot + 1,
1212 GNUNET_CRYPTO_ecc_public_sign_key_from_string (x,
1220 return GNUNET_SYSERR;
1224 /* end of namestore_common.c */