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