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