- distribute peers equally among island nodes on SuperMUC
[oweals/gnunet.git] / src / namestore / namestore_common.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010, 2012 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_common.c
23  * @brief API to access the NAMESTORE service
24  * @author Martin Schanzenbach
25  * @author Matthias Wachs
26  */
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 "gns_protocol.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  * Internal format of a record in the serialized form.
45  */
46 struct NetworkRecord
47 {
48
49   /**
50    * Expiration time for the DNS record; relative or absolute depends
51    * on 'flags', network byte order.
52    */
53   uint64_t expiration_time GNUNET_PACKED;
54
55   /**
56    * Number of bytes in 'data', network byte order.
57    */
58   uint32_t data_size GNUNET_PACKED;
59
60   /**
61    * Type of the GNS/DNS record, network byte order.
62    */
63   uint32_t record_type GNUNET_PACKED;
64
65   /**
66    * Flags for the record, network byte order.
67    */
68   uint32_t flags GNUNET_PACKED;
69   
70 };
71
72 GNUNET_NETWORK_STRUCT_END
73
74 /**
75  * Convert a UTF-8 string to UTF-8 lowercase
76  * @param src source string
77  * @return converted result
78  */
79 char *
80 GNUNET_NAMESTORE_normalize_string (const char *src)
81 {
82   GNUNET_assert (NULL != src);
83   char *res = strdup (src);
84   /* normalize */
85   GNUNET_STRINGS_utf8_tolower(src, &res);
86   return res;
87 }
88
89
90 /**
91  * Convert a short hash to a string (for printing debug messages).
92  * This is one of the very few calls in the entire API that is
93  * NOT reentrant!
94  *
95  * @param hc the short hash code
96  * @return string form; will be overwritten by next call to GNUNET_h2s.
97  */
98 const char *
99 GNUNET_short_h2s (const struct GNUNET_CRYPTO_ShortHashCode * hc)
100 {
101   static struct GNUNET_CRYPTO_ShortHashAsciiEncoded ret;
102
103   GNUNET_CRYPTO_short_hash_to_enc (hc, &ret);
104   return (const char *) &ret;
105 }
106
107
108 /**
109  * Calculate how many bytes we will need to serialize the given
110  * records.
111  *
112  * @param rd_count number of records in the rd array
113  * @param rd array of GNUNET_NAMESTORE_RecordData with rd_count elements
114  *
115  * @return the required size to serialize
116  *
117  */
118 size_t
119 GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
120                                    const struct GNUNET_NAMESTORE_RecordData *rd)
121 {
122   unsigned int i;
123   size_t ret;
124
125   ret = sizeof (struct NetworkRecord) * rd_count;
126   for (i=0;i<rd_count;i++)
127   {
128     GNUNET_assert ((ret + rd[i].data_size) >= ret);
129     ret += rd[i].data_size;
130   }
131   return ret;  
132 }
133
134
135 /**
136  * Serialize the given records to the given destination buffer.
137  *
138  * @param rd_count number of records in the rd array
139  * @param rd array of GNUNET_NAMESTORE_RecordData with rd_count elements
140  * @param dest_size size of the destination array
141  * @param dest where to write the result
142  *
143  * @return the size of serialized records, -1 if records do not fit
144  */
145 ssize_t
146 GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
147                                     const struct GNUNET_NAMESTORE_RecordData *rd,
148                                     size_t dest_size,
149                                     char *dest)
150 {
151   struct NetworkRecord rec;
152   unsigned int i;
153   size_t off;
154   
155   off = 0;
156   for (i=0;i<rd_count;i++)
157   {
158     rec.expiration_time = GNUNET_htonll (rd[i].expiration_time);
159     rec.data_size = htonl ((uint32_t) rd[i].data_size);
160     rec.record_type = htonl (rd[i].record_type);
161     rec.flags = htonl (rd[i].flags);
162     if (off + sizeof (rec) > dest_size)
163       return -1;
164     memcpy (&dest[off], &rec, sizeof (rec));
165     off += sizeof (rec);
166     if (off + rd[i].data_size > dest_size)
167       return -1;
168     memcpy (&dest[off], rd[i].data, rd[i].data_size);
169     off += rd[i].data_size;
170   }
171   return off;
172 }
173
174
175 /**
176  * Compares if two records are equal (ignoring flags such
177  * as authority, private and pending, but not relative vs.
178  * absolute expiration time).
179  *
180  * @param a record
181  * @param b record
182  * @return GNUNET_YES if the records are equal or GNUNET_NO if they are not
183  */
184 int
185 GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
186                               const struct GNUNET_NAMESTORE_RecordData *b)
187 {
188   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
189       "Comparing records\n");
190   if (a->record_type != b->record_type)
191   {
192     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
193         "Record type %lu != %lu\n", a->record_type, b->record_type);
194     return GNUNET_NO;
195   }
196   if ((a->expiration_time != b->expiration_time) &&
197       ((a->expiration_time != 0) && (b->expiration_time != 0)))
198   {
199     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
200         "Expiration time %llu != %llu\n", a->expiration_time, b->expiration_time);
201     return GNUNET_NO;
202   }
203   if ((a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS) 
204        != (b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS))
205   {
206     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
207         "Flags %lu (%lu) != %lu (%lu)\n", a->flags,
208         a->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS, b->flags,
209         b->flags & GNUNET_NAMESTORE_RF_RCMP_FLAGS);
210     return GNUNET_NO;
211   }
212   if (a->data_size != b->data_size)
213   {
214     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
215         "Data size %lu != %lu\n", a->data_size, b->data_size);
216     return GNUNET_NO;
217   }
218   if (0 != memcmp (a->data, b->data, a->data_size))
219   {
220     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
221         "Data contents do not match\n");
222     return GNUNET_NO;
223   }
224   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
225       "Records are equal\n");
226   return GNUNET_YES;
227 }
228
229
230 /**
231  * Deserialize the given records to the given destination.
232  *
233  * @param len size of the serialized record data
234  * @param src the serialized record data
235  * @param rd_count number of records in the rd array
236  * @param dest where to put the data
237  *
238  * @return GNUNET_OK on success, GNUNET_SYSERR on error
239  */
240 int
241 GNUNET_NAMESTORE_records_deserialize (size_t len,
242                                       const char *src,
243                                       unsigned int rd_count,
244                                       struct GNUNET_NAMESTORE_RecordData *dest)
245 {
246   struct NetworkRecord rec;
247   unsigned int i;
248   size_t off;
249   
250   off = 0;
251   for (i=0;i<rd_count;i++)
252   {
253     if (off + sizeof (rec) > len)
254       return GNUNET_SYSERR;
255     memcpy (&rec, &src[off], sizeof (rec));
256     dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time);
257     dest[i].data_size = ntohl ((uint32_t) rec.data_size);
258     dest[i].record_type = ntohl (rec.record_type);
259     dest[i].flags = ntohl (rec.flags);
260     off += sizeof (rec);
261
262     if (off + dest[i].data_size > len)
263       return GNUNET_SYSERR;
264     dest[i].data = &src[off];
265     off += dest[i].data_size;
266   }
267   return GNUNET_OK; 
268 }
269
270
271 /**
272  * Sign name and records
273  *
274  * @param key the private key
275  * @param expire block expiration
276  * @param name the name
277  * @param rd record data
278  * @param rd_count number of records
279  *
280  * @return the signature
281  */
282 struct GNUNET_CRYPTO_RsaSignature *
283 GNUNET_NAMESTORE_create_signature (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
284                                    struct GNUNET_TIME_Absolute expire,
285                                    const char *name,
286                                    const struct GNUNET_NAMESTORE_RecordData *rd,
287                                    unsigned int rd_count)
288 {
289   struct GNUNET_CRYPTO_RsaSignature *sig;
290   struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose;
291   struct GNUNET_TIME_AbsoluteNBO expire_nbo;
292   size_t rd_ser_len;
293   size_t name_len;
294   struct GNUNET_TIME_AbsoluteNBO *expire_tmp;
295   char * name_tmp;
296   char * rd_tmp;
297   int res;
298   uint32_t sig_len;
299
300   if (NULL == name)
301   {
302     GNUNET_break (0);
303     return NULL;
304   }
305   sig = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaSignature));
306   name_len = strlen (name) + 1;
307   expire_nbo = GNUNET_TIME_absolute_hton (expire);
308   rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
309   {
310     char rd_ser[rd_ser_len];
311
312     GNUNET_assert (rd_ser_len ==
313                    GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_ser));
314     sig_len = sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + rd_ser_len + name_len;
315     sig_purpose = GNUNET_malloc (sig_len);
316     sig_purpose->size = htonl (sig_len);
317     sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
318     expire_tmp = (struct GNUNET_TIME_AbsoluteNBO *) &sig_purpose[1];
319     memcpy (expire_tmp, &expire_nbo, sizeof (struct GNUNET_TIME_AbsoluteNBO));
320     name_tmp = (char *) &expire_tmp[1];
321     memcpy (name_tmp, name, name_len);
322     rd_tmp = &name_tmp[name_len];
323     memcpy (rd_tmp, rd_ser, rd_ser_len);
324     res = GNUNET_CRYPTO_rsa_sign (key, sig_purpose, sig);
325     GNUNET_free (sig_purpose);
326   }
327   if (GNUNET_OK != res)
328   {
329     GNUNET_break (0);
330     GNUNET_free (sig);
331     return NULL;
332   }
333   return sig;
334 }
335
336
337 /**
338  * Convert the 'value' of a record to a string.
339  *
340  * @param type type of the record
341  * @param data value in binary encoding
342  * @param data_size number of bytes in data
343  * @return NULL on error, otherwise human-readable representation of the value
344  */
345 char *
346 GNUNET_NAMESTORE_value_to_string (uint32_t type,
347                                   const void *data,
348                                   size_t data_size)
349 {
350   uint16_t mx_pref;
351   const struct soa_data *soa;
352   const struct vpn_data *vpn;
353   const struct srv_data *srv;
354   const struct tlsa_data *tlsa;
355   struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
356   struct GNUNET_CRYPTO_HashAsciiEncoded s_peer;
357   const char *cdata;
358   char* vpn_str;
359   char* srv_str;
360   char* tlsa_str;
361   char* result;
362   const char* soa_rname;
363   const char* soa_mname;
364   char tmp[INET6_ADDRSTRLEN];
365
366   switch (type)
367   {
368   case 0:
369     return NULL;
370   case GNUNET_DNSPARSER_TYPE_A:
371     if (data_size != sizeof (struct in_addr))
372       return NULL;
373     if (NULL == inet_ntop (AF_INET, data, tmp, sizeof (tmp)))
374       return NULL;
375     return GNUNET_strdup (tmp);
376   case GNUNET_DNSPARSER_TYPE_NS:
377     return GNUNET_strndup (data, data_size);
378   case GNUNET_DNSPARSER_TYPE_CNAME:
379     return GNUNET_strndup (data, data_size);
380   case GNUNET_DNSPARSER_TYPE_SOA:
381     if (data_size <= sizeof (struct soa_data))
382       return NULL;
383     soa = data;
384     soa_rname = (const char*) &soa[1];
385     soa_mname = memchr (soa_rname, 0, data_size - sizeof (struct soa_data) - 1);
386     if (NULL == soa_mname)
387       return NULL;
388     soa_mname++;
389     if (NULL == memchr (soa_mname, 0, 
390                         data_size - (sizeof (struct soa_data) + strlen (soa_rname) + 1)))
391       return NULL;
392     GNUNET_asprintf (&result, 
393                      "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu",
394                      soa_rname, soa_mname,
395                      ntohl (soa->serial), 
396                      ntohl (soa->refresh),
397                      ntohl (soa->retry), 
398                      ntohl (soa->expire),
399                      ntohl (soa->minimum));
400     return result;
401   case GNUNET_DNSPARSER_TYPE_PTR:
402     return GNUNET_strndup (data, data_size);
403   case GNUNET_DNSPARSER_TYPE_MX:
404     mx_pref = ntohs(*((uint16_t*)data));
405     if (GNUNET_asprintf(&result, "%hu,%s", mx_pref, data+sizeof(uint16_t))
406         != 0)
407       return result;
408     else
409     {
410       GNUNET_free (result);
411       return NULL;
412     }
413   case GNUNET_DNSPARSER_TYPE_TXT:
414     return GNUNET_strndup (data, data_size);
415   case GNUNET_DNSPARSER_TYPE_AAAA:
416     if (data_size != sizeof (struct in6_addr))
417       return NULL;
418     if (NULL == inet_ntop (AF_INET6, data, tmp, sizeof (tmp)))
419       return NULL;
420     return GNUNET_strdup (tmp);
421   case GNUNET_NAMESTORE_TYPE_PKEY:
422     if (data_size != sizeof (struct GNUNET_CRYPTO_ShortHashCode))
423       return NULL;
424     GNUNET_CRYPTO_short_hash_to_enc (data,
425                                      &enc);
426     return GNUNET_strdup ((const char*) enc.short_encoding);
427   case GNUNET_NAMESTORE_TYPE_PSEU:
428     return GNUNET_strndup (data, data_size);
429   case GNUNET_NAMESTORE_TYPE_LEHO:
430     return GNUNET_strndup (data, data_size);
431   case GNUNET_NAMESTORE_TYPE_VPN:
432     cdata = data;
433     if ( (data_size <= sizeof (struct vpn_data)) ||
434          ('\0' != cdata[data_size - 1]) )
435       return NULL; /* malformed */
436     vpn = data;
437     GNUNET_CRYPTO_hash_to_enc (&vpn->peer, &s_peer);
438     if (0 == GNUNET_asprintf (&vpn_str, "%u %s %s",
439                               (unsigned int) ntohs (vpn->proto),
440                               (const char*) &s_peer,
441                               (const char*) &vpn[1]))
442     {
443       GNUNET_free (vpn_str);
444       return NULL;
445     }
446     return vpn_str;
447   case GNUNET_DNSPARSER_TYPE_SRV:
448     cdata = data;
449     if ( (data_size <= sizeof (struct srv_data)) ||
450          ('\0' != cdata[data_size - 1]) )
451       return NULL; /* malformed */
452     srv = data;
453
454     if (0 == GNUNET_asprintf (&srv_str, 
455                               "%d %d %d %s",
456                               ntohs (srv->prio),
457                               ntohs (srv->weight),
458                               ntohs (srv->port),
459                               (const char *)&srv[1]))
460     {
461       GNUNET_free (srv_str);
462       return NULL;
463     }
464     return srv_str;
465   case GNUNET_DNSPARSER_TYPE_TLSA:
466     cdata = data;
467     if ( (data_size <= sizeof (struct tlsa_data)) ||
468          ('\0' != cdata[data_size - 1]) )
469       return NULL; /* malformed */
470     tlsa = data;
471     if (0 == GNUNET_asprintf (&tlsa_str, 
472                               "%c %c %c %s",
473                               tlsa->usage,
474                               tlsa->selector,
475                               tlsa->matching_type,
476                               (const char *) &tlsa[1]))
477     {
478       GNUNET_free (tlsa_str);
479       return NULL;
480     }
481     return tlsa_str;
482   default:
483     GNUNET_break (0);
484   }
485   GNUNET_break (0); // not implemented
486   return NULL;
487 }
488
489
490 /**
491  * Convert human-readable version of a 'value' of a record to the binary
492  * representation.
493  *
494  * @param type type of the record
495  * @param s human-readable string
496  * @param data set to value in binary encoding (will be allocated)
497  * @param data_size set to number of bytes in data
498  * @return GNUNET_OK on success
499  */
500 int
501 GNUNET_NAMESTORE_string_to_value (uint32_t type,
502                                   const char *s,
503                                   void **data,
504                                   size_t *data_size)
505 {
506   struct in_addr value_a;
507   struct in6_addr value_aaaa;
508   struct GNUNET_CRYPTO_ShortHashCode pkey;
509   struct soa_data *soa;
510   struct vpn_data *vpn;
511   struct tlsa_data *tlsa;
512   char result[253 + 1];
513   char soa_rname[253 + 1];
514   char soa_mname[253 + 1];
515   char s_peer[103 + 1];
516   char s_serv[253 + 1];
517   unsigned int soa_serial;
518   unsigned int soa_refresh;
519   unsigned int soa_retry;
520   unsigned int soa_expire;
521   unsigned int soa_min;
522   uint16_t mx_pref;
523   uint16_t mx_pref_n;
524   unsigned int proto;
525   
526   if (NULL == s)
527     return GNUNET_SYSERR;
528   switch (type)
529   {
530   case 0:
531     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
532                 _("Unsupported record type %d\n"),
533                 (int) type);
534     return GNUNET_SYSERR;
535   case GNUNET_DNSPARSER_TYPE_A:
536     if (1 != inet_pton (AF_INET, s, &value_a))
537     {
538       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
539                   _("Unable to parse IPv4 address `%s'\n"),
540                   s);
541       return GNUNET_SYSERR;
542     }
543     *data = GNUNET_malloc (sizeof (struct in_addr));
544     memcpy (*data, &value_a, sizeof (value_a));
545     *data_size = sizeof (value_a);
546     return GNUNET_OK;
547   case GNUNET_DNSPARSER_TYPE_NS:
548     *data = GNUNET_strdup (s);
549     *data_size = strlen (s) + 1;
550     return GNUNET_OK;
551   case GNUNET_DNSPARSER_TYPE_CNAME:
552     *data = GNUNET_strdup (s);
553     *data_size = strlen (s) + 1;
554     return GNUNET_OK;
555   case GNUNET_DNSPARSER_TYPE_SOA:
556     if (7 != SSCANF (s, 
557                      "rname=%253s mname=%253s %u,%u,%u,%u,%u",
558                      soa_rname, soa_mname,
559                      &soa_serial, &soa_refresh, &soa_retry, &soa_expire, &soa_min))
560     {
561       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
562                   _("Unable to parse SOA record `%s'\n"),
563                   s);
564       return GNUNET_SYSERR;
565     }
566     *data_size = sizeof (struct soa_data)+strlen(soa_rname)+strlen(soa_mname)+2;
567     *data = GNUNET_malloc (*data_size);
568     soa = (struct soa_data*)*data;
569     soa->serial = htonl(soa_serial);
570     soa->refresh = htonl(soa_refresh);
571     soa->retry = htonl(soa_retry);
572     soa->expire = htonl(soa_expire);
573     soa->minimum = htonl(soa_min);
574     strcpy((char*)&soa[1], soa_rname);
575     strcpy((char*)&soa[1]+strlen(*data)+1, soa_mname);
576     return GNUNET_OK;
577   case GNUNET_DNSPARSER_TYPE_PTR:
578     *data = GNUNET_strdup (s);
579     *data_size = strlen (s);
580     return GNUNET_OK;
581   case GNUNET_DNSPARSER_TYPE_MX:
582     if (2 != SSCANF(s, "%hu,%253s", &mx_pref, result))
583     {
584       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
585                   _("Unable to parse MX record `%s'\n"),
586                   s);
587       return GNUNET_SYSERR;
588     }
589     *data_size = sizeof (uint16_t)+strlen(result)+1;
590     *data = GNUNET_malloc (*data_size);
591     mx_pref_n = htons(mx_pref);
592     memcpy(*data, &mx_pref_n, sizeof (uint16_t));
593     strcpy((*data)+sizeof (uint16_t), result);
594     return GNUNET_OK;
595   case GNUNET_DNSPARSER_TYPE_TXT:
596     *data = GNUNET_strdup (s);
597     *data_size = strlen (s);
598     return GNUNET_OK;
599   case GNUNET_DNSPARSER_TYPE_AAAA:
600     if (1 != inet_pton (AF_INET6, s, &value_aaaa))    
601     {
602       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
603                   _("Unable to parse IPv6 address `%s'\n"),
604                   s);
605       return GNUNET_SYSERR;
606     }
607     *data = GNUNET_malloc (sizeof (struct in6_addr));
608     *data_size = sizeof (struct in6_addr);
609     memcpy (*data, &value_aaaa, sizeof (value_aaaa));
610     return GNUNET_OK;
611   case GNUNET_NAMESTORE_TYPE_PKEY:
612     if (GNUNET_OK !=
613         GNUNET_CRYPTO_short_hash_from_string (s, &pkey))
614     {
615       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
616                   _("Unable to parse PKEY record `%s'\n"),
617                   s);
618       return GNUNET_SYSERR;
619     }
620     *data = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode));
621     memcpy (*data, &pkey, sizeof (pkey));
622     *data_size = sizeof (struct GNUNET_CRYPTO_ShortHashCode);
623     return GNUNET_OK;
624   case GNUNET_NAMESTORE_TYPE_PSEU:
625     *data = GNUNET_strdup (s);
626     *data_size = strlen (s);
627     return GNUNET_OK;
628   case GNUNET_NAMESTORE_TYPE_LEHO:
629     *data = GNUNET_strdup (s);
630     *data_size = strlen (s);
631     return GNUNET_OK;
632   case GNUNET_NAMESTORE_TYPE_VPN:
633     if (3 != SSCANF (s,"%u %103s %253s",
634                      &proto, s_peer, s_serv))
635     {
636       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
637                   _("Unable to parse VPN record string `%s'\n"),
638                   s);
639       return GNUNET_SYSERR;
640     }
641     *data_size = sizeof (struct vpn_data) + strlen (s_serv) + 1;
642     *data = vpn = GNUNET_malloc (*data_size);
643     if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char*)&s_peer,
644                                                      &vpn->peer))
645     {
646       GNUNET_free (vpn);
647       *data_size = 0;
648       return GNUNET_SYSERR;
649     }
650     vpn->proto = htons ((uint16_t) proto);
651     strcpy ((char*)&vpn[1], s_serv);
652     return GNUNET_OK;
653   case GNUNET_DNSPARSER_TYPE_TLSA:
654     *data_size = sizeof (struct tlsa_data) + strlen (s) - 6;
655     *data = tlsa = GNUNET_malloc (*data_size);
656     if (4 != SSCANF (s, "%c %c %c %s",
657                      &tlsa->usage,
658                      &tlsa->selector,
659                      &tlsa->matching_type,
660                      (char*)&tlsa[1]))
661     {
662       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
663                   _("Unable to parse TLSA record string `%s'\n"), 
664                   s);
665       *data_size = 0;
666       GNUNET_free (tlsa);
667       return GNUNET_SYSERR;
668     }
669     return GNUNET_OK;
670   default:
671     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
672                 _("Unsupported record type %d\n"),
673                 (int) type);
674     return GNUNET_SYSERR;
675   }
676 }
677
678
679 static struct { 
680   const char *name; 
681   uint32_t number; 
682 } name_map[] = {
683   { "A", GNUNET_DNSPARSER_TYPE_A },
684   { "NS", GNUNET_DNSPARSER_TYPE_NS },
685   { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME },
686   { "SOA", GNUNET_DNSPARSER_TYPE_SOA },
687   { "PTR", GNUNET_DNSPARSER_TYPE_PTR },
688   { "MX", GNUNET_DNSPARSER_TYPE_MX },
689   { "TXT", GNUNET_DNSPARSER_TYPE_TXT },
690   { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA },
691   { "PKEY",  GNUNET_NAMESTORE_TYPE_PKEY },
692   { "PSEU",  GNUNET_NAMESTORE_TYPE_PSEU },
693   { "LEHO",  GNUNET_NAMESTORE_TYPE_LEHO },
694   { "VPN", GNUNET_NAMESTORE_TYPE_VPN },
695   { "TLSA", GNUNET_DNSPARSER_TYPE_TLSA },
696   { NULL, UINT32_MAX }
697 };
698
699
700 /**
701  * Convert a type name (i.e. "AAAA") to the corresponding number.
702  *
703  * @param typename name to convert
704  * @return corresponding number, UINT32_MAX on error
705  */
706 uint32_t
707 GNUNET_NAMESTORE_typename_to_number (const char *typename)
708 {
709   unsigned int i;
710
711   i=0;
712   while ( (name_map[i].name != NULL) &&
713           (0 != strcasecmp (typename, name_map[i].name)) )
714     i++;
715   return name_map[i].number;  
716 }
717
718
719 /**
720  * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
721  *
722  * @param type number of a type to convert
723  * @return corresponding typestring, NULL on error
724  */
725 const char *
726 GNUNET_NAMESTORE_number_to_typename (uint32_t type)
727 {
728   unsigned int i;
729
730   i=0;
731   while ( (name_map[i].name != NULL) &&
732           (type != name_map[i].number) )
733     i++;
734   return name_map[i].name;  
735 }
736
737 /**
738  * Test if a given record is expired.
739  * 
740  * @return GNUNET_YES if the record is expired,
741  *         GNUNET_NO if not
742  */
743 int
744 GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd)
745 {
746   struct GNUNET_TIME_Absolute at;
747
748   if (0 != (rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
749     return GNUNET_NO;
750   at.abs_value = rd->expiration_time;
751   return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value) ? GNUNET_YES : GNUNET_NO;
752 }
753
754
755 /* end of namestore_common.c */