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
30 #include "gnunet_util_lib.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_signatures.h"
33 #include "gnunet_arm_service.h"
34 #include "gnunet_namestore_service.h"
35 #include "gnunet_dnsparser_lib.h"
36 #include "gns_protocol.h"
37 #include "namestore.h"
40 #define LOG(kind,...) GNUNET_log_from (kind, "gns-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_EccPublicKey *z)
103 static char buf[sizeof (struct GNUNET_CRYPTO_EccPublicKey) * 8];
106 end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z,
107 sizeof (struct GNUNET_CRYPTO_EccPublicKey),
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 rec.expiration_time = GNUNET_htonll (rd[i].expiration_time);
167 rec.data_size = htonl ((uint32_t) rd[i].data_size);
168 rec.record_type = htonl (rd[i].record_type);
169 rec.flags = htonl (rd[i].flags);
170 if (off + sizeof (rec) > dest_size)
172 memcpy (&dest[off], &rec, sizeof (rec));
174 if (off + rd[i].data_size > dest_size)
176 memcpy (&dest[off], rd[i].data, rd[i].data_size);
177 off += rd[i].data_size;
184 * Compares if two records are equal (ignoring flags such
185 * as authority, private and pending, but not relative vs.
186 * absolute expiration time).
190 * @return #GNUNET_YES if the records are equal or #GNUNET_NO if they are not
193 GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
194 const struct GNUNET_NAMESTORE_RecordData *b)
196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
197 "Comparing records\n");
198 if (a->record_type != b->record_type)
200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
201 "Record type %lu != %lu\n", a->record_type, b->record_type);
204 if ((a->expiration_time != b->expiration_time) &&
205 ((a->expiration_time != 0) && (b->expiration_time != 0)))
207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
208 "Expiration time %llu != %llu\n", a->expiration_time, b->expiration_time);
211 if ((a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS)
212 != (b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS))
214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
215 "Flags %lu (%lu) != %lu (%lu)\n", a->flags,
216 a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS, b->flags,
217 b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS);
220 if (a->data_size != b->data_size)
222 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
223 "Data size %lu != %lu\n", a->data_size, b->data_size);
226 if (0 != memcmp (a->data, b->data, a->data_size))
228 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
229 "Data contents do not match\n");
232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
233 "Records are equal\n");
239 * Deserialize the given records to the given destination.
241 * @param len size of the serialized record data
242 * @param src the serialized record data
243 * @param rd_count number of records in the rd array
244 * @param dest where to put the data
245 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
248 GNUNET_NAMESTORE_records_deserialize (size_t len,
250 unsigned int rd_count,
251 struct GNUNET_NAMESTORE_RecordData *dest)
253 struct NetworkRecord rec;
258 for (i=0;i<rd_count;i++)
260 if (off + sizeof (rec) > len)
261 return GNUNET_SYSERR;
262 memcpy (&rec, &src[off], sizeof (rec));
263 dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time);
264 dest[i].data_size = ntohl ((uint32_t) rec.data_size);
265 dest[i].record_type = ntohl (rec.record_type);
266 dest[i].flags = ntohl (rec.flags);
269 if (off + dest[i].data_size > len)
270 return GNUNET_SYSERR;
271 dest[i].data = &src[off];
272 off += dest[i].data_size;
279 * Returns the expiration time of the given block of records. The block
280 * expiration time is the expiration time of the block with smallest
283 * @param rd_count number of records given in @a rd
284 * @param rd array of records
285 * @return absolute expiration time
287 struct GNUNET_TIME_Absolute
288 GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count,
289 const struct GNUNET_NAMESTORE_RecordData *rd)
292 struct GNUNET_TIME_Absolute expire;
293 struct GNUNET_TIME_Absolute at;
294 struct GNUNET_TIME_Relative rt;
297 return GNUNET_TIME_UNIT_ZERO_ABS;
298 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
299 for (c = 0; c < rd_count; c++)
301 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
303 rt.rel_value_us = rd[c].expiration_time;
304 at = GNUNET_TIME_relative_to_absolute (rt);
308 at.abs_value_us = rd[c].expiration_time;
310 expire = GNUNET_TIME_absolute_min (at, expire);
317 * Derive session key and iv from label and public key.
319 * @param iv initialization vector to initialize
320 * @param skey session key to initialize
321 * @param label label to use for KDF
322 * @param pub public key to use for KDF
325 derive_block_aes_key (struct GNUNET_CRYPTO_AesInitializationVector *iv,
326 struct GNUNET_CRYPTO_AesSessionKey *skey,
328 const struct GNUNET_CRYPTO_EccPublicKey *pub)
330 static const char ctx_key[] = "gns-aes-ctx-key";
331 static const char ctx_iv[] = "gns-aes-ctx-iv";
333 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_AesSessionKey),
334 pub, sizeof (struct GNUNET_CRYPTO_EccPublicKey),
335 label, strlen (label),
336 ctx_key, strlen (ctx_key),
338 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_AesInitializationVector),
339 pub, sizeof (struct GNUNET_CRYPTO_EccPublicKey),
340 label, strlen (label),
341 ctx_iv, strlen (ctx_iv),
347 * Sign name and records
349 * @param key the private key
350 * @param expire block expiration
351 * @param label the name for the records
352 * @param rd record data
353 * @param rd_count number of records
354 * @return NULL on error (block too large)
356 struct GNUNET_NAMESTORE_Block *
357 GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EccPrivateKey *key,
358 struct GNUNET_TIME_Absolute expire,
360 const struct GNUNET_NAMESTORE_RecordData *rd,
361 unsigned int rd_count)
363 size_t payload_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
364 char payload[sizeof (uint32_t) + payload_len];
365 struct GNUNET_NAMESTORE_Block *block;
366 struct GNUNET_CRYPTO_EccPublicKey pkey;
367 struct GNUNET_CRYPTO_EccPrivateKey *dkey;
368 struct GNUNET_CRYPTO_AesInitializationVector iv;
369 struct GNUNET_CRYPTO_AesSessionKey skey;
370 uint32_t rd_count_nbo;
372 if (payload_len > GNUNET_NAMESTORE_MAX_VALUE_SIZE)
374 rd_count_nbo = htonl (rd_count);
375 memcpy (payload, &rd_count_nbo, sizeof (uint32_t));
376 GNUNET_assert (payload_len ==
377 GNUNET_NAMESTORE_records_serialize (rd_count, rd,
378 payload_len, &payload[sizeof (uint32_t)]));
379 block = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Block) +
380 sizeof (uint32_t) + payload_len);
381 block->purpose.size = htonl (sizeof (uint32_t) + payload_len +
382 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
383 sizeof (struct GNUNET_TIME_AbsoluteNBO));
384 block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
385 block->expiration_time = GNUNET_TIME_absolute_hton (expire);
386 dkey = GNUNET_CRYPTO_ecc_key_derive (key,
389 GNUNET_CRYPTO_ecc_key_get_public (dkey,
390 &block->derived_key);
391 GNUNET_CRYPTO_ecc_key_get_public (key,
393 derive_block_aes_key (&iv, &skey, label, &pkey);
394 GNUNET_break (payload_len + sizeof (uint32_t) ==
395 GNUNET_CRYPTO_aes_encrypt (payload, payload_len + sizeof (uint32_t),
399 GNUNET_CRYPTO_ecc_sign (dkey,
412 * Check if a signature is valid. This API is used by the GNS Block
413 * to validate signatures received from the network.
415 * @param block block to verify
416 * @return #GNUNET_OK if the signature is valid
419 GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block)
421 return GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN,
424 &block->derived_key);
431 * @param block block to decrypt
432 * @param zone_key public key of the zone
433 * @param label the name for the records
434 * @param proc function to call with the result
435 * @param proc_cls closure for proc
436 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was
440 GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
441 const struct GNUNET_CRYPTO_EccPublicKey *zone_key,
443 GNUNET_NAMESTORE_RecordCallback proc,
446 size_t payload_len = ntohl (block->purpose.size) -
447 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) -
448 sizeof (struct GNUNET_TIME_AbsoluteNBO);
449 struct GNUNET_CRYPTO_AesInitializationVector iv;
450 struct GNUNET_CRYPTO_AesSessionKey skey;
452 if (ntohl (block->purpose.size) <
453 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) -
454 sizeof (struct GNUNET_TIME_AbsoluteNBO))
457 return GNUNET_SYSERR;
459 derive_block_aes_key (&iv, &skey, label, zone_key);
461 char payload[payload_len];
464 GNUNET_break (payload_len ==
465 GNUNET_CRYPTO_aes_decrypt (&block[1], payload_len,
471 rd_count = ntohl (rd_count);
474 /* limit to sane value */
476 return GNUNET_SYSERR;
479 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
482 GNUNET_NAMESTORE_records_deserialize (payload_len - sizeof (uint32_t),
483 &payload[sizeof (uint32_t)],
488 return GNUNET_SYSERR;
490 proc (proc_cls, rd_count, rd);
498 * Convert the 'value' of a record to a string.
500 * @param type type of the record
501 * @param data value in binary encoding
502 * @param data_size number of bytes in data
503 * @return NULL on error, otherwise human-readable representation of the value
506 GNUNET_NAMESTORE_value_to_string (uint32_t type,
511 const struct soa_data *soa;
512 const struct vpn_data *vpn;
513 const struct srv_data *srv;
514 const struct tlsa_data *tlsa;
515 struct GNUNET_CRYPTO_HashAsciiEncoded s_peer;
521 const char* soa_rname;
522 const char* soa_mname;
523 char tmp[INET6_ADDRSTRLEN];
529 case GNUNET_DNSPARSER_TYPE_A:
530 if (data_size != sizeof (struct in_addr))
532 if (NULL == inet_ntop (AF_INET, data, tmp, sizeof (tmp)))
534 return GNUNET_strdup (tmp);
535 case GNUNET_DNSPARSER_TYPE_NS:
536 return GNUNET_strndup (data, data_size);
537 case GNUNET_DNSPARSER_TYPE_CNAME:
538 return GNUNET_strndup (data, data_size);
539 case GNUNET_DNSPARSER_TYPE_SOA:
540 if (data_size <= sizeof (struct soa_data))
543 soa_rname = (const char*) &soa[1];
544 soa_mname = memchr (soa_rname, 0, data_size - sizeof (struct soa_data) - 1);
545 if (NULL == soa_mname)
548 if (NULL == memchr (soa_mname, 0,
549 data_size - (sizeof (struct soa_data) + strlen (soa_rname) + 1)))
551 GNUNET_asprintf (&result,
552 "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu",
553 soa_rname, soa_mname,
555 ntohl (soa->refresh),
558 ntohl (soa->minimum));
560 case GNUNET_DNSPARSER_TYPE_PTR:
561 return GNUNET_strndup (data, data_size);
562 case GNUNET_DNSPARSER_TYPE_MX:
563 mx_pref = ntohs(*((uint16_t*)data));
564 if (GNUNET_asprintf(&result, "%hu,%s", mx_pref, data+sizeof(uint16_t))
569 GNUNET_free (result);
572 case GNUNET_DNSPARSER_TYPE_TXT:
573 return GNUNET_strndup (data, data_size);
574 case GNUNET_DNSPARSER_TYPE_AAAA:
575 if (data_size != sizeof (struct in6_addr))
577 if (NULL == inet_ntop (AF_INET6, data, tmp, sizeof (tmp)))
579 return GNUNET_strdup (tmp);
580 case GNUNET_NAMESTORE_TYPE_PKEY:
581 if (data_size != sizeof (struct GNUNET_CRYPTO_EccPublicKey))
583 return GNUNET_CRYPTO_ecc_public_key_to_string (data);
584 case GNUNET_NAMESTORE_TYPE_PSEU:
585 return GNUNET_strndup (data, data_size);
586 case GNUNET_NAMESTORE_TYPE_LEHO:
587 return GNUNET_strndup (data, data_size);
588 case GNUNET_NAMESTORE_TYPE_VPN:
590 if ( (data_size <= sizeof (struct vpn_data)) ||
591 ('\0' != cdata[data_size - 1]) )
592 return NULL; /* malformed */
594 GNUNET_CRYPTO_hash_to_enc (&vpn->peer, &s_peer);
595 if (0 == GNUNET_asprintf (&vpn_str, "%u %s %s",
596 (unsigned int) ntohs (vpn->proto),
597 (const char*) &s_peer,
598 (const char*) &vpn[1]))
600 GNUNET_free (vpn_str);
604 case GNUNET_DNSPARSER_TYPE_SRV:
606 if ( (data_size <= sizeof (struct srv_data)) ||
607 ('\0' != cdata[data_size - 1]) )
608 return NULL; /* malformed */
611 if (0 == GNUNET_asprintf (&srv_str,
616 (const char *)&srv[1]))
618 GNUNET_free (srv_str);
622 case GNUNET_DNSPARSER_TYPE_TLSA:
624 if ( (data_size <= sizeof (struct tlsa_data)) ||
625 ('\0' != cdata[data_size - 1]) )
626 return NULL; /* malformed */
628 if (0 == GNUNET_asprintf (&tlsa_str,
633 (const char *) &tlsa[1]))
635 GNUNET_free (tlsa_str);
642 GNUNET_break (0); // not implemented
648 * Convert human-readable version of a 'value' of a record to the binary
651 * @param type type of the record
652 * @param s human-readable string
653 * @param data set to value in binary encoding (will be allocated)
654 * @param data_size set to number of bytes in data
655 * @return GNUNET_OK on success
658 GNUNET_NAMESTORE_string_to_value (uint32_t type,
663 struct in_addr value_a;
664 struct in6_addr value_aaaa;
665 struct GNUNET_CRYPTO_EccPublicKey pkey;
666 struct soa_data *soa;
667 struct vpn_data *vpn;
668 struct tlsa_data *tlsa;
669 char result[253 + 1];
670 char soa_rname[253 + 1];
671 char soa_mname[253 + 1];
672 char s_peer[103 + 1];
673 char s_serv[253 + 1];
674 unsigned int soa_serial;
675 unsigned int soa_refresh;
676 unsigned int soa_retry;
677 unsigned int soa_expire;
678 unsigned int soa_min;
684 return GNUNET_SYSERR;
688 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
689 _("Unsupported record type %d\n"),
691 return GNUNET_SYSERR;
692 case GNUNET_DNSPARSER_TYPE_A:
693 if (1 != inet_pton (AF_INET, s, &value_a))
695 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
696 _("Unable to parse IPv4 address `%s'\n"),
698 return GNUNET_SYSERR;
700 *data = GNUNET_malloc (sizeof (struct in_addr));
701 memcpy (*data, &value_a, sizeof (value_a));
702 *data_size = sizeof (value_a);
704 case GNUNET_DNSPARSER_TYPE_NS:
705 *data = GNUNET_strdup (s);
706 *data_size = strlen (s) + 1;
708 case GNUNET_DNSPARSER_TYPE_CNAME:
709 *data = GNUNET_strdup (s);
710 *data_size = strlen (s) + 1;
712 case GNUNET_DNSPARSER_TYPE_SOA:
714 "rname=%253s mname=%253s %u,%u,%u,%u,%u",
715 soa_rname, soa_mname,
716 &soa_serial, &soa_refresh, &soa_retry, &soa_expire, &soa_min))
718 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
719 _("Unable to parse SOA record `%s'\n"),
721 return GNUNET_SYSERR;
723 *data_size = sizeof (struct soa_data)+strlen(soa_rname)+strlen(soa_mname)+2;
724 *data = GNUNET_malloc (*data_size);
725 soa = (struct soa_data*)*data;
726 soa->serial = htonl(soa_serial);
727 soa->refresh = htonl(soa_refresh);
728 soa->retry = htonl(soa_retry);
729 soa->expire = htonl(soa_expire);
730 soa->minimum = htonl(soa_min);
731 strcpy((char*)&soa[1], soa_rname);
732 strcpy((char*)&soa[1]+strlen(*data)+1, soa_mname);
734 case GNUNET_DNSPARSER_TYPE_PTR:
735 *data = GNUNET_strdup (s);
736 *data_size = strlen (s);
738 case GNUNET_DNSPARSER_TYPE_MX:
739 if (2 != SSCANF(s, "%hu,%253s", &mx_pref, result))
741 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
742 _("Unable to parse MX record `%s'\n"),
744 return GNUNET_SYSERR;
746 *data_size = sizeof (uint16_t)+strlen(result)+1;
747 *data = GNUNET_malloc (*data_size);
748 mx_pref_n = htons(mx_pref);
749 memcpy(*data, &mx_pref_n, sizeof (uint16_t));
750 strcpy((*data)+sizeof (uint16_t), result);
752 case GNUNET_DNSPARSER_TYPE_TXT:
753 *data = GNUNET_strdup (s);
754 *data_size = strlen (s);
756 case GNUNET_DNSPARSER_TYPE_AAAA:
757 if (1 != inet_pton (AF_INET6, s, &value_aaaa))
759 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
760 _("Unable to parse IPv6 address `%s'\n"),
762 return GNUNET_SYSERR;
764 *data = GNUNET_malloc (sizeof (struct in6_addr));
765 *data_size = sizeof (struct in6_addr);
766 memcpy (*data, &value_aaaa, sizeof (value_aaaa));
768 case GNUNET_NAMESTORE_TYPE_PKEY:
770 GNUNET_CRYPTO_ecc_public_key_from_string (s, strlen (s), &pkey))
772 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
773 _("Unable to parse PKEY record `%s'\n"),
775 return GNUNET_SYSERR;
777 *data = GNUNET_new (struct GNUNET_CRYPTO_EccPublicKey);
778 memcpy (*data, &pkey, sizeof (pkey));
779 *data_size = sizeof (struct GNUNET_CRYPTO_EccPublicKey);
781 case GNUNET_NAMESTORE_TYPE_PSEU:
782 *data = GNUNET_strdup (s);
783 *data_size = strlen (s);
785 case GNUNET_NAMESTORE_TYPE_LEHO:
786 *data = GNUNET_strdup (s);
787 *data_size = strlen (s);
789 case GNUNET_NAMESTORE_TYPE_VPN:
790 if (3 != SSCANF (s,"%u %103s %253s",
791 &proto, s_peer, s_serv))
793 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
794 _("Unable to parse VPN record string `%s'\n"),
796 return GNUNET_SYSERR;
798 *data_size = sizeof (struct vpn_data) + strlen (s_serv) + 1;
799 *data = vpn = GNUNET_malloc (*data_size);
800 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char*)&s_peer,
805 return GNUNET_SYSERR;
807 vpn->proto = htons ((uint16_t) proto);
808 strcpy ((char*)&vpn[1], s_serv);
810 case GNUNET_DNSPARSER_TYPE_TLSA:
811 *data_size = sizeof (struct tlsa_data) + strlen (s) - 6;
812 *data = tlsa = GNUNET_malloc (*data_size);
813 if (4 != SSCANF (s, "%c %c %c %s",
816 &tlsa->matching_type,
819 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
820 _("Unable to parse TLSA record string `%s'\n"),
824 return GNUNET_SYSERR;
828 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
829 _("Unsupported record type %d\n"),
831 return GNUNET_SYSERR;
837 * Mapping of record type numbers to human-readable
844 { "A", GNUNET_DNSPARSER_TYPE_A },
845 { "NS", GNUNET_DNSPARSER_TYPE_NS },
846 { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME },
847 { "SOA", GNUNET_DNSPARSER_TYPE_SOA },
848 { "PTR", GNUNET_DNSPARSER_TYPE_PTR },
849 { "MX", GNUNET_DNSPARSER_TYPE_MX },
850 { "TXT", GNUNET_DNSPARSER_TYPE_TXT },
851 { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA },
852 { "PKEY", GNUNET_NAMESTORE_TYPE_PKEY },
853 { "PSEU", GNUNET_NAMESTORE_TYPE_PSEU },
854 { "LEHO", GNUNET_NAMESTORE_TYPE_LEHO },
855 { "VPN", GNUNET_NAMESTORE_TYPE_VPN },
856 { "TLSA", GNUNET_DNSPARSER_TYPE_TLSA },
862 * Convert a type name (i.e. "AAAA") to the corresponding number.
864 * @param typename name to convert
865 * @return corresponding number, UINT32_MAX on error
868 GNUNET_NAMESTORE_typename_to_number (const char *typename)
873 while ( (name_map[i].name != NULL) &&
874 (0 != strcasecmp (typename, name_map[i].name)) )
876 return name_map[i].number;
881 * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
883 * @param type number of a type to convert
884 * @return corresponding typestring, NULL on error
887 GNUNET_NAMESTORE_number_to_typename (uint32_t type)
892 while ( (name_map[i].name != NULL) &&
893 (type != name_map[i].number) )
895 return name_map[i].name;
900 * Test if a given record is expired.
902 * @return #GNUNET_YES if the record is expired,
906 GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd)
908 struct GNUNET_TIME_Absolute at;
910 if (0 != (rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
912 at.abs_value_us = rd->expiration_time;
913 return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ? GNUNET_YES : GNUNET_NO;
918 * Calculate the DHT query for a given @a label in a given @a zone.
920 * @param zone private key of the zone
921 * @param label label of the record
922 * @param query hash to use for the query
925 GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EccPrivateKey *zone,
927 struct GNUNET_HashCode *query)
929 struct GNUNET_CRYPTO_EccPublicKey pub;
931 GNUNET_CRYPTO_ecc_key_get_public (zone, &pub);
932 GNUNET_NAMESTORE_query_from_public_key (&pub, label, query);
937 * Calculate the DHT query for a given @a label in a given @a zone.
939 * @param pub public key of the zone
940 * @param label label of the record
941 * @param query hash to use for the query
944 GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EccPublicKey *pub,
946 struct GNUNET_HashCode *query)
948 struct GNUNET_CRYPTO_EccPublicKey pd;
950 GNUNET_CRYPTO_ecc_public_key_derive (pub, label, "gns", &pd);
951 GNUNET_CRYPTO_hash (&pd, sizeof (pd), query);
955 /* end of namestore_common.c */