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_conversation_service.h"
34 #include "gnunet_namestore_service.h"
35 #include "gnunet_dnsparser_lib.h"
36 #include "gnunet_tun_lib.h"
37 #include "namestore.h"
40 #define LOG(kind,...) GNUNET_log_from (kind, "namestore-api",__VA_ARGS__)
42 GNUNET_NETWORK_STRUCT_BEGIN
46 * Internal format of a record in the serialized form.
52 * Expiration time for the DNS record; relative or absolute depends
53 * on 'flags', network byte order.
55 uint64_t expiration_time GNUNET_PACKED;
58 * Number of bytes in 'data', network byte order.
60 uint32_t data_size GNUNET_PACKED;
63 * Type of the GNS/DNS record, network byte order.
65 uint32_t record_type GNUNET_PACKED;
68 * Flags for the record, network byte order.
70 uint32_t flags GNUNET_PACKED;
74 GNUNET_NETWORK_STRUCT_END
77 * Convert a UTF-8 string to UTF-8 lowercase
78 * @param src source string
79 * @return converted result
82 GNUNET_NAMESTORE_normalize_string (const char *src)
84 GNUNET_assert (NULL != src);
85 char *res = strdup (src);
87 GNUNET_STRINGS_utf8_tolower(src, &res);
93 * Convert a zone key to a string (for printing debug messages).
94 * This is one of the very few calls in the entire API that is
97 * @param z the zone key
98 * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s
101 GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EccPublicSignKey *z)
103 static char buf[sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) * 8];
106 end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z,
107 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey),
120 * Calculate how many bytes we will need to serialize the given
123 * @param rd_count number of records in the rd array
124 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
125 * @return the required size to serialize
128 GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
129 const struct GNUNET_NAMESTORE_RecordData *rd)
134 ret = sizeof (struct NetworkRecord) * rd_count;
135 for (i=0;i<rd_count;i++)
137 GNUNET_assert ((ret + rd[i].data_size) >= ret);
138 ret += rd[i].data_size;
145 * Serialize the given records to the given destination buffer.
147 * @param rd_count number of records in the rd array
148 * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
149 * @param dest_size size of the destination array
150 * @param dest where to write the result
151 * @return the size of serialized records, -1 if records do not fit
154 GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
155 const struct GNUNET_NAMESTORE_RecordData *rd,
159 struct NetworkRecord rec;
164 for (i=0;i<rd_count;i++)
166 LOG (GNUNET_ERROR_TYPE_DEBUG,
167 "Serializing record %u with flags %d and expiration time %llu\n",
170 (unsigned long long) rd[i].expiration_time);
171 rec.expiration_time = GNUNET_htonll (rd[i].expiration_time);
172 rec.data_size = htonl ((uint32_t) rd[i].data_size);
173 rec.record_type = htonl (rd[i].record_type);
174 rec.flags = htonl (rd[i].flags);
175 if (off + sizeof (rec) > dest_size)
177 memcpy (&dest[off], &rec, sizeof (rec));
179 if (off + rd[i].data_size > dest_size)
181 memcpy (&dest[off], rd[i].data, rd[i].data_size);
182 off += rd[i].data_size;
189 * Compares if two records are equal (ignoring flags such
190 * as authority, private and pending, but not relative vs.
191 * absolute expiration time).
195 * @return #GNUNET_YES if the records are equal or #GNUNET_NO if they are not
198 GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
199 const struct GNUNET_NAMESTORE_RecordData *b)
201 LOG (GNUNET_ERROR_TYPE_DEBUG,
202 "Comparing records\n");
203 if (a->record_type != b->record_type)
205 LOG (GNUNET_ERROR_TYPE_DEBUG,
206 "Record type %lu != %lu\n", a->record_type, b->record_type);
209 if ((a->expiration_time != b->expiration_time) &&
210 ((a->expiration_time != 0) && (b->expiration_time != 0)))
212 LOG (GNUNET_ERROR_TYPE_DEBUG,
213 "Expiration time %llu != %llu\n",
218 if ((a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS)
219 != (b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS))
221 LOG (GNUNET_ERROR_TYPE_DEBUG,
222 "Flags %lu (%lu) != %lu (%lu)\n", a->flags,
223 a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS, b->flags,
224 b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS);
227 if (a->data_size != b->data_size)
229 LOG (GNUNET_ERROR_TYPE_DEBUG,
230 "Data size %lu != %lu\n",
235 if (0 != memcmp (a->data, b->data, a->data_size))
237 LOG (GNUNET_ERROR_TYPE_DEBUG,
238 "Data contents do not match\n");
241 LOG (GNUNET_ERROR_TYPE_DEBUG,
242 "Records are equal\n");
248 * Deserialize the given records to the given destination.
250 * @param len size of the serialized record data
251 * @param src the serialized record data
252 * @param rd_count number of records in the rd array
253 * @param dest where to put the data
254 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
257 GNUNET_NAMESTORE_records_deserialize (size_t len,
259 unsigned int rd_count,
260 struct GNUNET_NAMESTORE_RecordData *dest)
262 struct NetworkRecord rec;
267 for (i=0;i<rd_count;i++)
269 if (off + sizeof (rec) > len)
270 return GNUNET_SYSERR;
271 memcpy (&rec, &src[off], sizeof (rec));
272 dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time);
273 dest[i].data_size = ntohl ((uint32_t) rec.data_size);
274 dest[i].record_type = ntohl (rec.record_type);
275 dest[i].flags = ntohl (rec.flags);
277 if (off + dest[i].data_size > len)
278 return GNUNET_SYSERR;
279 dest[i].data = &src[off];
280 off += dest[i].data_size;
281 LOG (GNUNET_ERROR_TYPE_DEBUG,
282 "Deserialized record %u with flags %d and expiration time %llu\n",
285 (unsigned long long) dest[i].expiration_time);
292 * Returns the expiration time of the given block of records. The block
293 * expiration time is the expiration time of the record with smallest
296 * @param rd_count number of records given in @a rd
297 * @param rd array of records
298 * @return absolute expiration time
300 struct GNUNET_TIME_Absolute
301 GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count,
302 const struct GNUNET_NAMESTORE_RecordData *rd)
305 struct GNUNET_TIME_Absolute expire;
306 struct GNUNET_TIME_Absolute at;
307 struct GNUNET_TIME_Relative rt;
310 return GNUNET_TIME_UNIT_ZERO_ABS;
311 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
312 for (c = 0; c < rd_count; c++)
314 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
316 rt.rel_value_us = rd[c].expiration_time;
317 at = GNUNET_TIME_relative_to_absolute (rt);
321 at.abs_value_us = rd[c].expiration_time;
323 expire = GNUNET_TIME_absolute_min (at, expire);
325 LOG (GNUNET_ERROR_TYPE_DEBUG,
326 "Determined expiration time for block with %u records to be %s\n",
328 GNUNET_STRINGS_absolute_time_to_string (expire));
334 * Derive session key and iv from label and public key.
336 * @param iv initialization vector to initialize
337 * @param skey session key to initialize
338 * @param label label to use for KDF
339 * @param pub public key to use for KDF
342 derive_block_aes_key (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
343 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
345 const struct GNUNET_CRYPTO_EccPublicSignKey *pub)
347 static const char ctx_key[] = "gns-aes-ctx-key";
348 static const char ctx_iv[] = "gns-aes-ctx-iv";
350 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
351 pub, sizeof (struct GNUNET_CRYPTO_EccPublicSignKey),
352 label, strlen (label),
353 ctx_key, strlen (ctx_key),
355 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
356 pub, sizeof (struct GNUNET_CRYPTO_EccPublicSignKey),
357 label, strlen (label),
358 ctx_iv, strlen (ctx_iv),
364 * Sign name and records
366 * @param key the private key
367 * @param expire block expiration
368 * @param label the name for the records
369 * @param rd record data
370 * @param rd_count number of records
371 * @return NULL on error (block too large)
373 struct GNUNET_NAMESTORE_Block *
374 GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EccPrivateKey *key,
375 struct GNUNET_TIME_Absolute expire,
377 const struct GNUNET_NAMESTORE_RecordData *rd,
378 unsigned int rd_count)
380 size_t payload_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
381 char payload[sizeof (uint32_t) + payload_len];
382 struct GNUNET_NAMESTORE_Block *block;
383 struct GNUNET_CRYPTO_EccPublicSignKey pkey;
384 struct GNUNET_CRYPTO_EccPrivateKey *dkey;
385 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
386 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
387 uint32_t rd_count_nbo;
389 if (payload_len > GNUNET_NAMESTORE_MAX_VALUE_SIZE)
391 rd_count_nbo = htonl (rd_count);
392 memcpy (payload, &rd_count_nbo, sizeof (uint32_t));
393 GNUNET_assert (payload_len ==
394 GNUNET_NAMESTORE_records_serialize (rd_count, rd,
395 payload_len, &payload[sizeof (uint32_t)]));
396 block = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Block) +
397 sizeof (uint32_t) + payload_len);
398 block->purpose.size = htonl (sizeof (uint32_t) + payload_len +
399 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
400 sizeof (struct GNUNET_TIME_AbsoluteNBO));
401 block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
402 block->expiration_time = GNUNET_TIME_absolute_hton (expire);
403 dkey = GNUNET_CRYPTO_ecc_key_derive (key,
406 GNUNET_CRYPTO_ecc_key_get_public_for_signature (dkey,
407 &block->derived_key);
408 GNUNET_CRYPTO_ecc_key_get_public_for_signature (key,
410 derive_block_aes_key (&iv, &skey, label, &pkey);
411 GNUNET_break (payload_len + sizeof (uint32_t) ==
412 GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len + sizeof (uint32_t),
416 GNUNET_CRYPTO_ecc_sign (dkey,
431 * Check if a signature is valid. This API is used by the GNS Block
432 * to validate signatures received from the network.
434 * @param block block to verify
435 * @return #GNUNET_OK if the signature is valid
438 GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block)
440 return GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN,
443 &block->derived_key);
450 * @param block block to decrypt
451 * @param zone_key public key of the zone
452 * @param label the name for the records
453 * @param proc function to call with the result
454 * @param proc_cls closure for proc
455 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was
459 GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
460 const struct GNUNET_CRYPTO_EccPublicSignKey *zone_key,
462 GNUNET_NAMESTORE_RecordCallback proc,
465 size_t payload_len = ntohl (block->purpose.size) -
466 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) -
467 sizeof (struct GNUNET_TIME_AbsoluteNBO);
468 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
469 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
471 if (ntohl (block->purpose.size) <
472 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
473 sizeof (struct GNUNET_TIME_AbsoluteNBO))
476 return GNUNET_SYSERR;
478 derive_block_aes_key (&iv, &skey, label, zone_key);
480 char payload[payload_len];
483 GNUNET_break (payload_len ==
484 GNUNET_CRYPTO_symmetric_decrypt (&block[1], payload_len,
490 rd_count = ntohl (rd_count);
493 /* limit to sane value */
495 return GNUNET_SYSERR;
498 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
501 GNUNET_NAMESTORE_records_deserialize (payload_len - sizeof (uint32_t),
502 &payload[sizeof (uint32_t)],
507 return GNUNET_SYSERR;
510 proc (proc_cls, rd_count, (0 != rd_count) ? rd : NULL);
518 * Convert the 'value' of a record to a string.
520 * @param type type of the record
521 * @param data value in binary encoding
522 * @param data_size number of bytes in @a data
523 * @return NULL on error, otherwise human-readable representation of the value
526 GNUNET_NAMESTORE_value_to_string (uint32_t type,
532 char tmp[INET6_ADDRSTRLEN];
538 case GNUNET_DNSPARSER_TYPE_A:
539 if (data_size != sizeof (struct in_addr))
541 if (NULL == inet_ntop (AF_INET, data, tmp, sizeof (tmp)))
543 return GNUNET_strdup (tmp);
544 case GNUNET_DNSPARSER_TYPE_NS:
550 ns = GNUNET_DNSPARSER_parse_name (data,
561 case GNUNET_DNSPARSER_TYPE_CNAME:
567 cname = GNUNET_DNSPARSER_parse_name (data,
570 if ( (NULL == cname) ||
578 case GNUNET_DNSPARSER_TYPE_SOA:
580 struct GNUNET_DNSPARSER_SoaRecord *soa;
584 soa = GNUNET_DNSPARSER_parse_soa (data,
587 if ( (NULL == soa) ||
593 GNUNET_asprintf (&result,
594 "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu",
602 GNUNET_DNSPARSER_free_soa (soa);
605 case GNUNET_DNSPARSER_TYPE_PTR:
611 ptr = GNUNET_DNSPARSER_parse_name (data,
614 if ( (NULL == ptr) ||
622 case GNUNET_DNSPARSER_TYPE_MX:
624 struct GNUNET_DNSPARSER_MxRecord *mx;
628 mx = GNUNET_DNSPARSER_parse_mx (data,
637 GNUNET_asprintf (&result,
641 GNUNET_DNSPARSER_free_mx (mx);
644 case GNUNET_DNSPARSER_TYPE_TXT:
645 return GNUNET_strndup (data, data_size);
646 case GNUNET_DNSPARSER_TYPE_AAAA:
647 if (data_size != sizeof (struct in6_addr))
649 if (NULL == inet_ntop (AF_INET6, data, tmp, sizeof (tmp)))
651 return GNUNET_strdup (tmp);
652 case GNUNET_NAMESTORE_TYPE_PKEY:
653 if (data_size != sizeof (struct GNUNET_CRYPTO_EccPublicSignKey))
655 return GNUNET_CRYPTO_ecc_public_sign_key_to_string (data);
656 case GNUNET_NAMESTORE_TYPE_PHONE:
658 const struct GNUNET_CONVERSATION_PhoneRecord *pr;
662 if (data_size != sizeof (struct GNUNET_CONVERSATION_PhoneRecord))
665 if (0 != ntohl (pr->version))
667 pkey = GNUNET_CRYPTO_ecc_public_sign_key_to_string (&pr->peer.public_key);
668 GNUNET_asprintf (&ret,
675 case GNUNET_NAMESTORE_TYPE_PSEU:
676 return GNUNET_strndup (data, data_size);
677 case GNUNET_NAMESTORE_TYPE_LEHO:
678 return GNUNET_strndup (data, data_size);
679 case GNUNET_NAMESTORE_TYPE_VPN:
681 const struct GNUNET_TUN_GnsVpnRecord *vpn;
685 if ( (data_size <= sizeof (struct GNUNET_TUN_GnsVpnRecord)) ||
686 ('\0' != cdata[data_size - 1]) )
687 return NULL; /* malformed */
689 if (0 == GNUNET_asprintf (&vpn_str, "%u %s %s",
690 (unsigned int) ntohs (vpn->proto),
691 (const char*) GNUNET_i2s_full (&vpn->peer),
692 (const char*) &vpn[1]))
694 GNUNET_free (vpn_str);
699 case GNUNET_NAMESTORE_TYPE_GNS2DNS:
705 ns = GNUNET_DNSPARSER_parse_name (data,
716 case GNUNET_DNSPARSER_TYPE_SRV:
718 struct GNUNET_DNSPARSER_SrvRecord *srv;
722 srv = GNUNET_DNSPARSER_parse_srv ("+", /* FIXME: is this OK? */
726 if ( (NULL == srv) ||
732 GNUNET_asprintf (&result,
733 "%d %d %d _%s._%s.%s",
740 GNUNET_DNSPARSER_free_srv (srv);
743 case GNUNET_DNSPARSER_TYPE_TLSA:
745 const struct GNUNET_TUN_DnsTlsaRecord *tlsa;
749 if ( (data_size <= sizeof (struct GNUNET_TUN_DnsTlsaRecord)) ||
750 ('\0' != cdata[data_size - 1]) )
751 return NULL; /* malformed */
753 if (0 == GNUNET_asprintf (&tlsa_str,
758 (const char *) &tlsa[1]))
760 GNUNET_free (tlsa_str);
768 GNUNET_break (0); // not implemented
774 * Convert human-readable version of a 'value' of a record to the binary
777 * @param type type of the record
778 * @param s human-readable string
779 * @param data set to value in binary encoding (will be allocated)
780 * @param data_size set to number of bytes in @a data
781 * @return #GNUNET_OK on success
784 GNUNET_NAMESTORE_string_to_value (uint32_t type,
789 struct in_addr value_a;
790 struct in6_addr value_aaaa;
791 struct GNUNET_CRYPTO_EccPublicSignKey pkey;
792 struct GNUNET_TUN_GnsVpnRecord *vpn;
793 struct GNUNET_TUN_DnsTlsaRecord *tlsa;
794 char s_peer[103 + 1];
795 char s_serv[253 + 1];
799 return GNUNET_SYSERR;
803 LOG (GNUNET_ERROR_TYPE_ERROR,
804 _("Unsupported record type %d\n"),
806 return GNUNET_SYSERR;
807 case GNUNET_DNSPARSER_TYPE_A:
808 if (1 != inet_pton (AF_INET, s, &value_a))
810 LOG (GNUNET_ERROR_TYPE_ERROR,
811 _("Unable to parse IPv4 address `%s'\n"),
813 return GNUNET_SYSERR;
815 *data = GNUNET_malloc (sizeof (struct in_addr));
816 memcpy (*data, &value_a, sizeof (value_a));
817 *data_size = sizeof (value_a);
819 case GNUNET_DNSPARSER_TYPE_NS:
826 GNUNET_DNSPARSER_builder_add_name (nsbuf,
831 LOG (GNUNET_ERROR_TYPE_ERROR,
832 _("Failed to serialize NS record with value `%s'\n"),
834 return GNUNET_SYSERR;
837 *data = GNUNET_malloc (off);
838 memcpy (*data, nsbuf, off);
841 case GNUNET_DNSPARSER_TYPE_CNAME:
848 GNUNET_DNSPARSER_builder_add_name (cnamebuf,
853 LOG (GNUNET_ERROR_TYPE_ERROR,
854 _("Failed to serialize CNAME record with value `%s'\n"),
856 return GNUNET_SYSERR;
859 *data = GNUNET_malloc (off);
860 memcpy (*data, cnamebuf, off);
863 case GNUNET_DNSPARSER_TYPE_SOA:
865 struct GNUNET_DNSPARSER_SoaRecord soa;
867 char soa_rname[253 + 1];
868 char soa_mname[253 + 1];
869 unsigned int soa_serial;
870 unsigned int soa_refresh;
871 unsigned int soa_retry;
872 unsigned int soa_expire;
873 unsigned int soa_min;
877 "rname=%253s mname=%253s %u,%u,%u,%u,%u",
878 soa_rname, soa_mname,
879 &soa_serial, &soa_refresh, &soa_retry, &soa_expire, &soa_min))
881 LOG (GNUNET_ERROR_TYPE_ERROR,
882 _("Unable to parse SOA record `%s'\n"),
884 return GNUNET_SYSERR;
886 soa.mname = soa_mname;
887 soa.rname = soa_rname;
888 soa.serial = (uint32_t) soa_serial;
889 soa.refresh =(uint32_t) soa_refresh;
890 soa.retry = (uint32_t) soa_retry;
891 soa.expire = (uint32_t) soa_expire;
892 soa.minimum_ttl = (uint32_t) soa_min;
895 GNUNET_DNSPARSER_builder_add_soa (soabuf,
900 LOG (GNUNET_ERROR_TYPE_ERROR,
901 _("Failed to serialize SOA record with mname `%s' and rname `%s'\n"),
904 return GNUNET_SYSERR;
907 *data = GNUNET_malloc (off);
908 memcpy (*data, soabuf, off);
911 case GNUNET_DNSPARSER_TYPE_PTR:
918 GNUNET_DNSPARSER_builder_add_name (ptrbuf,
923 LOG (GNUNET_ERROR_TYPE_ERROR,
924 _("Failed to serialize PTR record with value `%s'\n"),
926 return GNUNET_SYSERR;
929 *data = GNUNET_malloc (off);
930 memcpy (*data, ptrbuf, off);
933 case GNUNET_DNSPARSER_TYPE_MX:
935 struct GNUNET_DNSPARSER_MxRecord mx;
937 char mxhost[253 + 1];
941 if (2 != SSCANF(s, "%hu,%253s", &mx_pref, mxhost))
943 LOG (GNUNET_ERROR_TYPE_ERROR,
944 _("Unable to parse MX record `%s'\n"),
946 return GNUNET_SYSERR;
948 mx.preference = mx_pref;
953 GNUNET_DNSPARSER_builder_add_mx (mxbuf,
958 LOG (GNUNET_ERROR_TYPE_ERROR,
959 _("Failed to serialize MX record with hostname `%s'\n"),
961 return GNUNET_SYSERR;
964 *data = GNUNET_malloc (off);
965 memcpy (*data, mxbuf, off);
968 case GNUNET_DNSPARSER_TYPE_TXT:
969 *data = GNUNET_strdup (s);
970 *data_size = strlen (s);
972 case GNUNET_DNSPARSER_TYPE_AAAA:
973 if (1 != inet_pton (AF_INET6, s, &value_aaaa))
975 LOG (GNUNET_ERROR_TYPE_ERROR,
976 _("Unable to parse IPv6 address `%s'\n"),
978 return GNUNET_SYSERR;
980 *data = GNUNET_malloc (sizeof (struct in6_addr));
981 *data_size = sizeof (struct in6_addr);
982 memcpy (*data, &value_aaaa, sizeof (value_aaaa));
984 case GNUNET_NAMESTORE_TYPE_PKEY:
986 GNUNET_CRYPTO_ecc_public_sign_key_from_string (s, strlen (s), &pkey))
988 LOG (GNUNET_ERROR_TYPE_ERROR,
989 _("Unable to parse PKEY record `%s'\n"),
991 return GNUNET_SYSERR;
993 *data = GNUNET_new (struct GNUNET_CRYPTO_EccPublicSignKey);
994 memcpy (*data, &pkey, sizeof (pkey));
995 *data_size = sizeof (struct GNUNET_CRYPTO_EccPublicSignKey);
997 case GNUNET_NAMESTORE_TYPE_PHONE:
999 struct GNUNET_CONVERSATION_PhoneRecord *pr;
1002 struct GNUNET_PeerIdentity peer;
1004 if ( (NULL == (dash = strchr (s, '-'))) ||
1005 (1 != sscanf (s, "%u-", &line)) ||
1007 GNUNET_CRYPTO_ecc_public_sign_key_from_string (dash + 1,
1009 &peer.public_key)) )
1011 LOG (GNUNET_ERROR_TYPE_ERROR,
1012 _("Unable to parse PHONE record `%s'\n"),
1014 return GNUNET_SYSERR;
1016 pr = GNUNET_new (struct GNUNET_CONVERSATION_PhoneRecord);
1017 pr->version = htonl (0);
1018 pr->line = htonl ((uint32_t) line);
1021 *data_size = sizeof (struct GNUNET_CONVERSATION_PhoneRecord);
1024 case GNUNET_NAMESTORE_TYPE_PSEU:
1025 *data = GNUNET_strdup (s);
1026 *data_size = strlen (s);
1028 case GNUNET_NAMESTORE_TYPE_LEHO:
1029 *data = GNUNET_strdup (s);
1030 *data_size = strlen (s);
1032 case GNUNET_NAMESTORE_TYPE_VPN:
1033 if (3 != SSCANF (s,"%u %103s %253s",
1034 &proto, s_peer, s_serv))
1036 LOG (GNUNET_ERROR_TYPE_ERROR,
1037 _("Unable to parse VPN record string `%s'\n"),
1039 return GNUNET_SYSERR;
1041 *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1;
1042 *data = vpn = GNUNET_malloc (*data_size);
1043 if (GNUNET_OK != GNUNET_CRYPTO_ecc_public_sign_key_from_string ((char*) s_peer,
1045 &vpn->peer.public_key))
1049 return GNUNET_SYSERR;
1051 vpn->proto = htons ((uint16_t) proto);
1052 strcpy ((char*)&vpn[1], s_serv);
1054 case GNUNET_NAMESTORE_TYPE_GNS2DNS:
1061 GNUNET_DNSPARSER_builder_add_name (nsbuf,
1066 LOG (GNUNET_ERROR_TYPE_ERROR,
1067 _("Failed to serialize GNS2DNS record with value `%s'\n"),
1069 return GNUNET_SYSERR;
1072 *data = GNUNET_malloc (off);
1073 memcpy (*data, nsbuf, off);
1076 case GNUNET_DNSPARSER_TYPE_TLSA:
1077 *data_size = sizeof (struct GNUNET_TUN_DnsTlsaRecord) + strlen (s) - 6;
1078 *data = tlsa = GNUNET_malloc (*data_size);
1079 if (4 != SSCANF (s, "%c %c %c %s",
1082 &tlsa->matching_type,
1085 LOG (GNUNET_ERROR_TYPE_ERROR,
1086 _("Unable to parse TLSA record string `%s'\n"),
1090 return GNUNET_SYSERR;
1094 LOG (GNUNET_ERROR_TYPE_ERROR,
1095 _("Unsupported record type %d\n"),
1097 return GNUNET_SYSERR;
1103 * Mapping of record type numbers to human-readable
1104 * record type names.
1110 { "A", GNUNET_DNSPARSER_TYPE_A },
1111 { "NS", GNUNET_DNSPARSER_TYPE_NS },
1112 { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME },
1113 { "SOA", GNUNET_DNSPARSER_TYPE_SOA },
1114 { "PTR", GNUNET_DNSPARSER_TYPE_PTR },
1115 { "MX", GNUNET_DNSPARSER_TYPE_MX },
1116 { "TXT", GNUNET_DNSPARSER_TYPE_TXT },
1117 { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA },
1118 { "PKEY", GNUNET_NAMESTORE_TYPE_PKEY },
1119 { "PSEU", GNUNET_NAMESTORE_TYPE_PSEU },
1120 { "LEHO", GNUNET_NAMESTORE_TYPE_LEHO },
1121 { "VPN", GNUNET_NAMESTORE_TYPE_VPN },
1122 { "GNS2DNS", GNUNET_NAMESTORE_TYPE_GNS2DNS },
1123 { "PHONE", GNUNET_NAMESTORE_TYPE_PHONE },
1124 { "TLSA", GNUNET_DNSPARSER_TYPE_TLSA },
1125 { NULL, UINT32_MAX }
1130 * Convert a type name (i.e. "AAAA") to the corresponding number.
1132 * @param dns_typename name to convert
1133 * @return corresponding number, UINT32_MAX on error
1136 GNUNET_NAMESTORE_typename_to_number (const char *dns_typename)
1141 while ( (name_map[i].name != NULL) &&
1142 (0 != strcasecmp (dns_typename, name_map[i].name)) )
1144 return name_map[i].number;
1149 * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
1151 * @param type number of a type to convert
1152 * @return corresponding typestring, NULL on error
1155 GNUNET_NAMESTORE_number_to_typename (uint32_t type)
1160 while ( (name_map[i].name != NULL) &&
1161 (type != name_map[i].number) )
1163 return name_map[i].name;
1168 * Test if a given record is expired.
1170 * @return #GNUNET_YES if the record is expired,
1174 GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd)
1176 struct GNUNET_TIME_Absolute at;
1178 if (0 != (rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
1180 at.abs_value_us = rd->expiration_time;
1181 return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ? GNUNET_YES : GNUNET_NO;
1186 * Calculate the DHT query for a given @a label in a given @a zone.
1188 * @param zone private key of the zone
1189 * @param label label of the record
1190 * @param query hash to use for the query
1193 GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EccPrivateKey *zone,
1195 struct GNUNET_HashCode *query)
1197 struct GNUNET_CRYPTO_EccPublicSignKey pub;
1199 GNUNET_CRYPTO_ecc_key_get_public_for_signature (zone, &pub);
1200 GNUNET_NAMESTORE_query_from_public_key (&pub, label, query);
1205 * Calculate the DHT query for a given @a label in a given @a zone.
1207 * @param pub public key of the zone
1208 * @param label label of the record
1209 * @param query hash to use for the query
1212 GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EccPublicSignKey *pub,
1214 struct GNUNET_HashCode *query)
1216 struct GNUNET_CRYPTO_EccPublicSignKey pd;
1218 GNUNET_CRYPTO_ecc_public_key_derive (pub, label, "gns", &pd);
1219 GNUNET_CRYPTO_hash (&pd, sizeof (pd), query);
1224 * Convert public key to the respective absolute domain name in the
1226 * This is one of the very few calls in the entire API that is
1229 * @param pkey a public key with a point on the eliptic curve
1230 * @return string "X.zkey" where X is the public
1231 * key in an encoding suitable for DNS labels.
1234 GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EccPublicSignKey *pkey)
1236 static char ret[128];
1239 pkeys = GNUNET_CRYPTO_ecc_public_sign_key_to_string (pkey);
1240 GNUNET_snprintf (ret,
1244 GNUNET_free (pkeys);
1250 * Convert an absolute domain name in the ".zkey" pTLD to the
1251 * respective public key.
1253 * @param zkey string "X.zkey" where X is the coordinates of the public
1254 * key in an encoding suitable for DNS labels.
1255 * @param pkey set to a public key on the eliptic curve
1256 * @return #GNUNET_SYSERR if @a zkey has the wrong syntax
1259 GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey,
1260 struct GNUNET_CRYPTO_EccPublicSignKey *pkey)
1266 cpy = GNUNET_strdup (zkey);
1268 if (NULL == (dot = strchr (x, (int) '.')))
1271 if (0 != strcasecmp (dot + 1,
1276 GNUNET_CRYPTO_ecc_public_sign_key_from_string (x,
1284 return GNUNET_SYSERR;
1288 /* end of namestore_common.c */