- fix parallel build
[oweals/gnunet.git] / src / namestore / namestore_api_common.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009-2013 Christian Grothoff (and other contributing authors)
4
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.
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      General Public License for more details.
14
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.
19 */
20
21 /**
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
27  */
28
29 #include "platform.h"
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"
38
39
40 #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__)
41
42 GNUNET_NETWORK_STRUCT_BEGIN
43
44
45 /**
46  * Internal format of a record in the serialized form.
47  */
48 struct NetworkRecord
49 {
50
51   /**
52    * Expiration time for the DNS record; relative or absolute depends
53    * on 'flags', network byte order.
54    */
55   uint64_t expiration_time GNUNET_PACKED;
56
57   /**
58    * Number of bytes in 'data', network byte order.
59    */
60   uint32_t data_size GNUNET_PACKED;
61
62   /**
63    * Type of the GNS/DNS record, network byte order.
64    */
65   uint32_t record_type GNUNET_PACKED;
66
67   /**
68    * Flags for the record, network byte order.
69    */
70   uint32_t flags GNUNET_PACKED;
71   
72 };
73
74 GNUNET_NETWORK_STRUCT_END
75
76 /**
77  * Convert a UTF-8 string to UTF-8 lowercase
78  * @param src source string
79  * @return converted result
80  */
81 char *
82 GNUNET_NAMESTORE_normalize_string (const char *src)
83 {
84   GNUNET_assert (NULL != src);
85   char *res = strdup (src);
86   /* normalize */
87   GNUNET_STRINGS_utf8_tolower(src, &res);
88   return res;
89 }
90
91
92 /**
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
95  * NOT reentrant!
96  *
97  * @param z the zone key
98  * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s
99  */
100 const char *
101 GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EccPublicKey *z)
102 {
103   static char buf[sizeof (struct GNUNET_CRYPTO_EccPublicKey) * 8];
104   char *end;
105
106   end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z, 
107                                        sizeof (struct GNUNET_CRYPTO_EccPublicKey),
108                                        buf, sizeof (buf));
109   if (NULL == end)
110   {
111     GNUNET_break (0);
112     return NULL;
113   }
114   *end = '\0';
115   return buf;
116 }
117
118
119 /**
120  * Calculate how many bytes we will need to serialize the given
121  * records.
122  *
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
126  */
127 size_t
128 GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
129                                    const struct GNUNET_NAMESTORE_RecordData *rd)
130 {
131   unsigned int i;
132   size_t ret;
133
134   ret = sizeof (struct NetworkRecord) * rd_count;
135   for (i=0;i<rd_count;i++)
136   {
137     GNUNET_assert ((ret + rd[i].data_size) >= ret);
138     ret += rd[i].data_size;
139   }
140   return ret;  
141 }
142
143
144 /**
145  * Serialize the given records to the given destination buffer.
146  *
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
152  */
153 ssize_t
154 GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
155                                     const struct GNUNET_NAMESTORE_RecordData *rd,
156                                     size_t dest_size,
157                                     char *dest)
158 {
159   struct NetworkRecord rec;
160   unsigned int i;
161   size_t off;
162   
163   off = 0;
164   for (i=0;i<rd_count;i++)
165   {
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)
171       return -1;
172     memcpy (&dest[off], &rec, sizeof (rec));
173     off += sizeof (rec);
174     if (off + rd[i].data_size > dest_size)
175       return -1;
176     memcpy (&dest[off], rd[i].data, rd[i].data_size);
177     off += rd[i].data_size;
178   }
179   return off;
180 }
181
182
183 /**
184  * Compares if two records are equal (ignoring flags such
185  * as authority, private and pending, but not relative vs.
186  * absolute expiration time).
187  *
188  * @param a record
189  * @param b record
190  * @return #GNUNET_YES if the records are equal or #GNUNET_NO if they are not
191  */
192 int
193 GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
194                               const struct GNUNET_NAMESTORE_RecordData *b)
195 {
196   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
197       "Comparing records\n");
198   if (a->record_type != b->record_type)
199   {
200     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
201         "Record type %lu != %lu\n", a->record_type, b->record_type);
202     return GNUNET_NO;
203   }
204   if ((a->expiration_time != b->expiration_time) &&
205       ((a->expiration_time != 0) && (b->expiration_time != 0)))
206   {
207     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
208         "Expiration time %llu != %llu\n", a->expiration_time, b->expiration_time);
209     return GNUNET_NO;
210   }
211   if ((a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS) 
212        != (b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS))
213   {
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);
218     return GNUNET_NO;
219   }
220   if (a->data_size != b->data_size)
221   {
222     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
223         "Data size %lu != %lu\n", a->data_size, b->data_size);
224     return GNUNET_NO;
225   }
226   if (0 != memcmp (a->data, b->data, a->data_size))
227   {
228     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
229         "Data contents do not match\n");
230     return GNUNET_NO;
231   }
232   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
233       "Records are equal\n");
234   return GNUNET_YES;
235 }
236
237
238 /**
239  * Deserialize the given records to the given destination.
240  *
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
246  */
247 int
248 GNUNET_NAMESTORE_records_deserialize (size_t len,
249                                       const char *src,
250                                       unsigned int rd_count,
251                                       struct GNUNET_NAMESTORE_RecordData *dest)
252 {
253   struct NetworkRecord rec;
254   unsigned int i;
255   size_t off;
256   
257   off = 0;
258   for (i=0;i<rd_count;i++)
259   {
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);
267     off += sizeof (rec);
268
269     if (off + dest[i].data_size > len)
270       return GNUNET_SYSERR;
271     dest[i].data = &src[off];
272     off += dest[i].data_size;
273   }
274   return GNUNET_OK; 
275 }
276
277
278 /**
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
281  * expiration time.
282  *
283  * @param rd_count number of records given in @a rd
284  * @param rd array of records
285  * @return absolute expiration time
286  */
287 struct GNUNET_TIME_Absolute
288 GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count, 
289                                              const struct GNUNET_NAMESTORE_RecordData *rd)
290 {
291   unsigned int c;
292   struct GNUNET_TIME_Absolute expire;
293   struct GNUNET_TIME_Absolute at;
294   struct GNUNET_TIME_Relative rt;
295
296   if (NULL == rd)
297     return GNUNET_TIME_UNIT_ZERO_ABS;
298   expire = GNUNET_TIME_UNIT_FOREVER_ABS;
299   for (c = 0; c < rd_count; c++)  
300   {
301     if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
302     {
303       rt.rel_value_us = rd[c].expiration_time;
304       at = GNUNET_TIME_relative_to_absolute (rt);
305     }
306     else
307     {
308       at.abs_value_us = rd[c].expiration_time;
309     }
310     expire = GNUNET_TIME_absolute_min (at, expire);  
311   }
312   return expire;
313 }
314
315
316 /**
317  * Derive session key and iv from label and public key.
318  *
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
323  */
324 static void
325 derive_block_aes_key (struct GNUNET_CRYPTO_AesInitializationVector *iv,
326                       struct GNUNET_CRYPTO_AesSessionKey *skey,
327                       const char *label,
328                       const struct GNUNET_CRYPTO_EccPublicKey *pub)
329 {
330   static const char ctx_key[] = "gns-aes-ctx-key";
331   static const char ctx_iv[] = "gns-aes-ctx-iv";
332
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),
337                      NULL, 0);
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),
342                      NULL, 0);
343 }
344
345
346 /**
347  * Sign name and records
348  *
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)
355  */
356 struct GNUNET_NAMESTORE_Block *
357 GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EccPrivateKey *key,
358                                struct GNUNET_TIME_Absolute expire,
359                                const char *label,
360                                const struct GNUNET_NAMESTORE_RecordData *rd,
361                                unsigned int rd_count)
362 {
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;
371
372   if (payload_len > GNUNET_NAMESTORE_MAX_VALUE_SIZE)
373     return NULL;
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,
387                                        label,
388                                        "gns");
389   GNUNET_CRYPTO_ecc_key_get_public (dkey,
390                                     &block->derived_key);
391   GNUNET_CRYPTO_ecc_key_get_public (key,
392                                     &pkey);
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),
396                                            &skey, &iv,
397                                            &block[1]));
398   if (GNUNET_OK !=
399       GNUNET_CRYPTO_ecc_sign (dkey,
400                               &block->purpose,
401                               &block->signature))
402   {
403     GNUNET_break (0);
404     GNUNET_free (block);
405     return NULL;
406   }
407   return block;
408 }
409
410
411 /**
412  * Check if a signature is valid.  This API is used by the GNS Block
413  * to validate signatures received from the network.
414  *
415  * @param block block to verify
416  * @return #GNUNET_OK if the signature is valid
417  */
418 int
419 GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block)
420 {  
421   return GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, 
422                                    &block->purpose,
423                                    &block->signature,
424                                    &block->derived_key);
425 }
426
427
428 /**
429  * Decrypt block.
430  *
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 
437  *        not well-formed
438  */
439 int
440 GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
441                                 const struct GNUNET_CRYPTO_EccPublicKey *zone_key,
442                                 const char *label,
443                                 GNUNET_NAMESTORE_RecordCallback proc,
444                                 void *proc_cls)
445 {
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;
451
452   if (ntohl (block->purpose.size) <
453       sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) -
454       sizeof (struct GNUNET_TIME_AbsoluteNBO))
455   {
456     GNUNET_break_op (0);
457     return GNUNET_SYSERR;
458   }
459   derive_block_aes_key (&iv, &skey, label, zone_key);
460   {
461     char payload[payload_len];    
462     uint32_t rd_count;
463
464     GNUNET_break (payload_len ==
465                   GNUNET_CRYPTO_aes_decrypt (&block[1], payload_len,
466                                              &skey, &iv,
467                                              payload));
468     memcpy (&rd_count,
469             payload,
470             sizeof (uint32_t));
471     rd_count = ntohl (rd_count);
472     if (rd_count > 2048)
473     {
474       /* limit to sane value */
475       GNUNET_break_op (0);
476       return GNUNET_SYSERR;
477     }
478     {
479       struct GNUNET_NAMESTORE_RecordData rd[rd_count];
480       
481       if (GNUNET_OK !=
482           GNUNET_NAMESTORE_records_deserialize (payload_len - sizeof (uint32_t),
483                                                 &payload[sizeof (uint32_t)],
484                                                 rd_count,
485                                                 rd))
486       {
487         GNUNET_break_op (0);
488         return GNUNET_SYSERR;
489       }
490       proc (proc_cls, rd_count, rd);
491     }
492   }
493   return GNUNET_OK;
494 }
495
496
497 /**
498  * Convert the 'value' of a record to a string.
499  *
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
504  */
505 char *
506 GNUNET_NAMESTORE_value_to_string (uint32_t type,
507                                   const void *data,
508                                   size_t data_size)
509 {
510   uint16_t mx_pref;
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;
516   const char *cdata;
517   char* vpn_str;
518   char* srv_str;
519   char* tlsa_str;
520   char* result;
521   const char* soa_rname;
522   const char* soa_mname;
523   char tmp[INET6_ADDRSTRLEN];
524
525   switch (type)
526   {
527   case 0:
528     return NULL;
529   case GNUNET_DNSPARSER_TYPE_A:
530     if (data_size != sizeof (struct in_addr))
531       return NULL;
532     if (NULL == inet_ntop (AF_INET, data, tmp, sizeof (tmp)))
533       return NULL;
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))
541       return NULL;
542     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)
546       return NULL;
547     soa_mname++;
548     if (NULL == memchr (soa_mname, 0, 
549                         data_size - (sizeof (struct soa_data) + strlen (soa_rname) + 1)))
550       return NULL;
551     GNUNET_asprintf (&result, 
552                      "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu",
553                      soa_rname, soa_mname,
554                      ntohl (soa->serial), 
555                      ntohl (soa->refresh),
556                      ntohl (soa->retry), 
557                      ntohl (soa->expire),
558                      ntohl (soa->minimum));
559     return result;
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))
565         != 0)
566       return result;
567     else
568     {
569       GNUNET_free (result);
570       return NULL;
571     }
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))
576       return NULL;
577     if (NULL == inet_ntop (AF_INET6, data, tmp, sizeof (tmp)))
578       return NULL;
579     return GNUNET_strdup (tmp);
580   case GNUNET_NAMESTORE_TYPE_PKEY:
581     if (data_size != sizeof (struct GNUNET_CRYPTO_EccPublicKey))
582       return NULL;
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:
589     cdata = data;
590     if ( (data_size <= sizeof (struct vpn_data)) ||
591          ('\0' != cdata[data_size - 1]) )
592       return NULL; /* malformed */
593     vpn = data;
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]))
599     {
600       GNUNET_free (vpn_str);
601       return NULL;
602     }
603     return vpn_str;
604   case GNUNET_DNSPARSER_TYPE_SRV:
605     cdata = data;
606     if ( (data_size <= sizeof (struct srv_data)) ||
607          ('\0' != cdata[data_size - 1]) )
608       return NULL; /* malformed */
609     srv = data;
610
611     if (0 == GNUNET_asprintf (&srv_str, 
612                               "%d %d %d %s",
613                               ntohs (srv->prio),
614                               ntohs (srv->weight),
615                               ntohs (srv->port),
616                               (const char *)&srv[1]))
617     {
618       GNUNET_free (srv_str);
619       return NULL;
620     }
621     return srv_str;
622   case GNUNET_DNSPARSER_TYPE_TLSA:
623     cdata = data;
624     if ( (data_size <= sizeof (struct tlsa_data)) ||
625          ('\0' != cdata[data_size - 1]) )
626       return NULL; /* malformed */
627     tlsa = data;
628     if (0 == GNUNET_asprintf (&tlsa_str, 
629                               "%c %c %c %s",
630                               tlsa->usage,
631                               tlsa->selector,
632                               tlsa->matching_type,
633                               (const char *) &tlsa[1]))
634     {
635       GNUNET_free (tlsa_str);
636       return NULL;
637     }
638     return tlsa_str;
639   default:
640     GNUNET_break (0);
641   }
642   GNUNET_break (0); // not implemented
643   return NULL;
644 }
645
646
647 /**
648  * Convert human-readable version of a 'value' of a record to the binary
649  * representation.
650  *
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
656  */
657 int
658 GNUNET_NAMESTORE_string_to_value (uint32_t type,
659                                   const char *s,
660                                   void **data,
661                                   size_t *data_size)
662 {
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;
679   uint16_t mx_pref;
680   uint16_t mx_pref_n;
681   unsigned int proto;
682   
683   if (NULL == s)
684     return GNUNET_SYSERR;
685   switch (type)
686   {
687   case 0:
688     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
689                 _("Unsupported record type %d\n"),
690                 (int) type);
691     return GNUNET_SYSERR;
692   case GNUNET_DNSPARSER_TYPE_A:
693     if (1 != inet_pton (AF_INET, s, &value_a))
694     {
695       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
696                   _("Unable to parse IPv4 address `%s'\n"),
697                   s);
698       return GNUNET_SYSERR;
699     }
700     *data = GNUNET_malloc (sizeof (struct in_addr));
701     memcpy (*data, &value_a, sizeof (value_a));
702     *data_size = sizeof (value_a);
703     return GNUNET_OK;
704   case GNUNET_DNSPARSER_TYPE_NS:
705     *data = GNUNET_strdup (s);
706     *data_size = strlen (s) + 1;
707     return GNUNET_OK;
708   case GNUNET_DNSPARSER_TYPE_CNAME:
709     *data = GNUNET_strdup (s);
710     *data_size = strlen (s) + 1;
711     return GNUNET_OK;
712   case GNUNET_DNSPARSER_TYPE_SOA:
713     if (7 != SSCANF (s, 
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))
717     {
718       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
719                   _("Unable to parse SOA record `%s'\n"),
720                   s);
721       return GNUNET_SYSERR;
722     }
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);
733     return GNUNET_OK;
734   case GNUNET_DNSPARSER_TYPE_PTR:
735     *data = GNUNET_strdup (s);
736     *data_size = strlen (s);
737     return GNUNET_OK;
738   case GNUNET_DNSPARSER_TYPE_MX:
739     if (2 != SSCANF(s, "%hu,%253s", &mx_pref, result))
740     {
741       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
742                   _("Unable to parse MX record `%s'\n"),
743                   s);
744       return GNUNET_SYSERR;
745     }
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);
751     return GNUNET_OK;
752   case GNUNET_DNSPARSER_TYPE_TXT:
753     *data = GNUNET_strdup (s);
754     *data_size = strlen (s);
755     return GNUNET_OK;
756   case GNUNET_DNSPARSER_TYPE_AAAA:
757     if (1 != inet_pton (AF_INET6, s, &value_aaaa))    
758     {
759       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
760                   _("Unable to parse IPv6 address `%s'\n"),
761                   s);
762       return GNUNET_SYSERR;
763     }
764     *data = GNUNET_malloc (sizeof (struct in6_addr));
765     *data_size = sizeof (struct in6_addr);
766     memcpy (*data, &value_aaaa, sizeof (value_aaaa));
767     return GNUNET_OK;
768   case GNUNET_NAMESTORE_TYPE_PKEY:
769     if (GNUNET_OK !=
770         GNUNET_CRYPTO_ecc_public_key_from_string (s, strlen (s), &pkey))
771     {
772       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
773                   _("Unable to parse PKEY record `%s'\n"),
774                   s);
775       return GNUNET_SYSERR;
776     }
777     *data = GNUNET_new (struct GNUNET_CRYPTO_EccPublicKey);
778     memcpy (*data, &pkey, sizeof (pkey));
779     *data_size = sizeof (struct GNUNET_CRYPTO_EccPublicKey);
780     return GNUNET_OK;
781   case GNUNET_NAMESTORE_TYPE_PSEU:
782     *data = GNUNET_strdup (s);
783     *data_size = strlen (s);
784     return GNUNET_OK;
785   case GNUNET_NAMESTORE_TYPE_LEHO:
786     *data = GNUNET_strdup (s);
787     *data_size = strlen (s);
788     return GNUNET_OK;
789   case GNUNET_NAMESTORE_TYPE_VPN:
790     if (3 != SSCANF (s,"%u %103s %253s",
791                      &proto, s_peer, s_serv))
792     {
793       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
794                   _("Unable to parse VPN record string `%s'\n"),
795                   s);
796       return GNUNET_SYSERR;
797     }
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,
801                                                      &vpn->peer))
802     {
803       GNUNET_free (vpn);
804       *data_size = 0;
805       return GNUNET_SYSERR;
806     }
807     vpn->proto = htons ((uint16_t) proto);
808     strcpy ((char*)&vpn[1], s_serv);
809     return GNUNET_OK;
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",
814                      &tlsa->usage,
815                      &tlsa->selector,
816                      &tlsa->matching_type,
817                      (char*)&tlsa[1]))
818     {
819       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
820                   _("Unable to parse TLSA record string `%s'\n"), 
821                   s);
822       *data_size = 0;
823       GNUNET_free (tlsa);
824       return GNUNET_SYSERR;
825     }
826     return GNUNET_OK;
827   default:
828     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
829                 _("Unsupported record type %d\n"),
830                 (int) type);
831     return GNUNET_SYSERR;
832   }
833 }
834
835
836 /**
837  * Mapping of record type numbers to human-readable
838  * record type names.
839  */
840 static struct { 
841   const char *name; 
842   uint32_t number; 
843 } name_map[] = {
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 },
857   { NULL, UINT32_MAX }
858 };
859
860
861 /**
862  * Convert a type name (i.e. "AAAA") to the corresponding number.
863  *
864  * @param typename name to convert
865  * @return corresponding number, UINT32_MAX on error
866  */
867 uint32_t
868 GNUNET_NAMESTORE_typename_to_number (const char *typename)
869 {
870   unsigned int i;
871
872   i=0;
873   while ( (name_map[i].name != NULL) &&
874           (0 != strcasecmp (typename, name_map[i].name)) )
875     i++;
876   return name_map[i].number;  
877 }
878
879
880 /**
881  * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
882  *
883  * @param type number of a type to convert
884  * @return corresponding typestring, NULL on error
885  */
886 const char *
887 GNUNET_NAMESTORE_number_to_typename (uint32_t type)
888 {
889   unsigned int i;
890
891   i=0;
892   while ( (name_map[i].name != NULL) &&
893           (type != name_map[i].number) )
894     i++;
895   return name_map[i].name;  
896 }
897
898
899 /**
900  * Test if a given record is expired.
901  * 
902  * @return #GNUNET_YES if the record is expired,
903  *         #GNUNET_NO if not
904  */
905 int
906 GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd)
907 {
908   struct GNUNET_TIME_Absolute at;
909
910   if (0 != (rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
911     return GNUNET_NO;
912   at.abs_value_us = rd->expiration_time;
913   return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ? GNUNET_YES : GNUNET_NO;
914 }
915
916
917 /**
918  * Calculate the DHT query for a given @a label in a given @a zone.
919  * 
920  * @param zone private key of the zone
921  * @param label label of the record
922  * @param query hash to use for the query
923  */
924 void
925 GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EccPrivateKey *zone,
926                                          const char *label,
927                                          struct GNUNET_HashCode *query)
928 {
929   struct GNUNET_CRYPTO_EccPublicKey pub;
930
931   GNUNET_CRYPTO_ecc_key_get_public (zone, &pub);
932   GNUNET_NAMESTORE_query_from_public_key (&pub, label, query);
933 }
934
935
936 /**
937  * Calculate the DHT query for a given @a label in a given @a zone.
938  * 
939  * @param pub public key of the zone
940  * @param label label of the record
941  * @param query hash to use for the query
942  */
943 void
944 GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EccPublicKey *pub,
945                                         const char *label,
946                                         struct GNUNET_HashCode *query)
947 {
948   struct GNUNET_CRYPTO_EccPublicKey pd;
949
950   GNUNET_CRYPTO_ecc_public_key_derive (pub, label, "gns", &pd);
951   GNUNET_CRYPTO_hash (&pd, sizeof (pd), query);
952 }
953
954
955 /* end of namestore_common.c */