aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/namestore_api_common.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-06-30 19:21:05 +0000
committerChristian Grothoff <christian@grothoff.org>2013-06-30 19:21:05 +0000
commit17de5c9d798109f55059190c886609ba377e4eb6 (patch)
tree07f2b4241f433b18baf02d5bf189307ad2308166 /src/namestore/namestore_api_common.c
parentfd87b25438487e1215c68bdb9f1bcac2d7012bc2 (diff)
downloadgnunet-17de5c9d798109f55059190c886609ba377e4eb6.tar.gz
gnunet-17de5c9d798109f55059190c886609ba377e4eb6.zip
-towards implementing improved namestore API
Diffstat (limited to 'src/namestore/namestore_api_common.c')
-rw-r--r--src/namestore/namestore_api_common.c755
1 files changed, 755 insertions, 0 deletions
diff --git a/src/namestore/namestore_api_common.c b/src/namestore/namestore_api_common.c
new file mode 100644
index 000000000..ab2506611
--- /dev/null
+++ b/src/namestore/namestore_api_common.c
@@ -0,0 +1,755 @@
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
41GNUNET_NETWORK_STRUCT_BEGIN
42
43/**
44 * Internal format of a record in the serialized form.
45 */
46struct 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
72GNUNET_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 */
79char *
80GNUNET_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 */
98const char *
99GNUNET_NAMESTORE_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 */
118size_t
119GNUNET_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 */
145ssize_t
146GNUNET_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 */
184int
185GNUNET_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 */
240int
241GNUNET_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 */
282struct GNUNET_CRYPTO_EccSignature *
283GNUNET_NAMESTORE_create_signature (const struct GNUNET_CRYPTO_EccPrivateKey *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_EccSignature *sig;
290 struct GNUNET_CRYPTO_EccSignaturePurpose *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_EccSignature));
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_EccSignaturePurpose) + 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_ecc_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 */
345char *
346GNUNET_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 */
500int
501GNUNET_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
679static 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 */
706uint32_t
707GNUNET_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 */
725const char *
726GNUNET_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 */
743int
744GNUNET_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 */