1f78b40f6beccf4f7cdaab2dff62884ca4f41702
[oweals/gnunet.git] / src / include / gnunet_namestore_service.h
1
2 /*
3      This file is part of GNUnet
4      (C) 2012, 2013 Christian Grothoff (and other contributing authors)
5
6      GNUnet is free software; you can redistribute it and/or modify
7      it under the terms of the GNU General Public License as published
8      by the Free Software Foundation; either version 3, or (at your
9      option) any later version.
10
11      GNUnet is distributed in the hope that it will be useful, but
12      WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14      General Public License for more details.
15
16      You should have received a copy of the GNU General Public License
17      along with GNUnet; see the file COPYING.  If not, write to the
18      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19      Boston, MA 02111-1307, USA.
20 */
21
22 /**
23  * @file include/gnunet_namestore_service.h
24  * @brief API that can be used to store naming information on a GNUnet node;
25  *        Naming information can either be records for which this peer/user
26  *        is authoritative, or blocks which are cached, encrypted naming
27  *        data from other peers.
28  * @author Christian Grothoff
29  */
30 #ifndef GNUNET_NAMESTORE_SERVICE_H
31 #define GNUNET_NAMESTORE_SERVICE_H
32
33 #include "gnunet_util_lib.h"
34 #include "gnunet_block_lib.h"
35
36 #ifdef __cplusplus
37 extern "C"
38 {
39 #if 0                           /* keep Emacsens' auto-indent happy */
40 }
41 #endif
42 #endif
43
44 /**
45  * Record type indicating any record/'*'
46  */
47 #define GNUNET_NAMESTORE_TYPE_ANY 0
48
49 /**
50  * Record type for GNS zone transfer ("PKEY").
51  */
52 #define GNUNET_NAMESTORE_TYPE_PKEY 65536
53
54 /**
55  * Record type for GNS zone transfer ("PSEU").
56  */
57 #define GNUNET_NAMESTORE_TYPE_PSEU 65537
58
59 /**
60  * Record type for GNS legacy hostnames ("LEHO").
61  */
62 #define GNUNET_NAMESTORE_TYPE_LEHO 65538
63
64 /**
65  * Record type for VPN resolution
66  */
67 #define GNUNET_NAMESTORE_TYPE_VPN 65539
68
69 /**
70  * Record type for a social place.
71  */
72 #define GNUNET_NAMESTORE_TYPE_PLACE 65541
73
74 /**
75  * Entry in the queue.
76  */
77 struct GNUNET_NAMESTORE_QueueEntry;
78
79 /**
80  * Handle to the namestore service.
81  */
82 struct GNUNET_NAMESTORE_Handle;
83
84 /**
85  * Handle to the namestore zone iterator.
86  */
87 struct GNUNET_NAMESTORE_ZoneIterator;
88
89 /**
90  * Maximum size of a value that can be stored in the namestore.
91  */
92 #define GNUNET_NAMESTORE_MAX_VALUE_SIZE (63 * 1024)
93
94
95 /**
96  * Connect to the namestore service.
97  *
98  * @param cfg configuration to use
99  * @return handle to use to access the service
100  */
101 struct GNUNET_NAMESTORE_Handle *
102 GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
103
104
105 /**
106  * Disconnect from the namestore service (and free associated
107  * resources).  Must not be called from within operation callbacks of
108  * the API.
109  *
110  * @param h handle to the namestore
111  */
112 void
113 GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h);
114
115
116 /**
117  * Continuation called to notify client about result of the
118  * operation.
119  *
120  * @param cls closure
121  * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
122  *                #GNUNET_NO if content was already there or not found
123  *                #GNUNET_YES (or other positive value) on success
124  * @param emsg NULL on success, otherwise an error message
125  */
126 typedef void (*GNUNET_NAMESTORE_ContinuationWithStatus) (void *cls,
127                                                          int32_t success,
128                                                          const char *emsg);
129
130
131 /**
132  * Flags that can be set for a record.
133  */
134 enum GNUNET_NAMESTORE_RecordFlags
135 {
136   
137   /**
138    * No special options.
139    */
140   GNUNET_NAMESTORE_RF_NONE = 0,
141
142   /**
143    * This is a private record of this peer and it should
144    * thus not be handed out to other peers.
145    */
146   GNUNET_NAMESTORE_RF_PRIVATE = 2,
147
148   /**
149    * This record was added automatically by the system
150    * and is pending user confimation.
151    */
152   GNUNET_NAMESTORE_RF_PENDING = 4,
153
154   /**
155    * This expiration time of the record is a relative
156    * time (not an absolute time).
157    */
158   GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION = 8,
159
160   /**
161    * This record should not be used unless all (other) records with an absolute
162    * expiration time have expired.
163    */
164   GNUNET_NAMESTORE_RF_SHADOW_RECORD = 16
165
166   /**
167    * When comparing flags for record equality for removal,
168    * which flags should must match (in addition to the type,
169    * name, expiration value and data of the record)?  All flags
170    * that are not listed here will be ignored for this purpose.
171    * (for example, we don't expect that users will remember to
172    * pass the '--private' option when removing a record from
173    * the namestore, hence we don't require this particular option
174    * to match upon removal).  See also
175    * #GNUNET_NAMESTORE_records_cmp.
176    */
177 #define GNUNET_NAMESTORE_RF_RCMP_FLAGS (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
178 };
179
180
181 /**
182  * A GNS record.
183  */
184 struct GNUNET_NAMESTORE_RecordData
185 {
186
187   /**
188    * Binary value stored in the DNS record.  Note: "data" must never
189    * be individually 'malloc'ed, but instead always points into some
190    * existing data area.
191    */
192   const void *data;
193
194   /**
195    * Expiration time for the DNS record.  Can be relative
196    * or absolute, depending on 'flags'.  Measured in the same
197    * unit as GNUnet time (microseconds).
198    */
199   uint64_t expiration_time;
200
201   /**
202    * Number of bytes in 'data'.
203    */
204   size_t data_size;
205
206   /**
207    * Type of the GNS/DNS record.
208    */
209   uint32_t record_type;
210
211   /**
212    * Flags for the record.
213    */
214   enum GNUNET_NAMESTORE_RecordFlags flags;
215 };
216
217
218
219 GNUNET_NETWORK_STRUCT_BEGIN
220
221
222 /**
223  * Information we have in an encrypted block with record data (i.e. in the DHT).
224  */
225 struct GNUNET_NAMESTORE_Block
226 {
227
228   /**
229    * Signature of the block.
230    */
231   struct GNUNET_CRYPTO_EccSignature signature;
232
233   /**
234    * Derived key used for signing; hash of this is the query.
235    */
236   struct GNUNET_CRYPTO_EccPublicSignKey derived_key;
237
238   /**
239    * Number of bytes signed; also specifies the number of bytes
240    * of encrypted data that follow.
241    */
242   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
243   
244   /**
245    * Expiration time of the block.
246    */
247   struct GNUNET_TIME_AbsoluteNBO expiration_time;
248
249   /* followed by encrypted data */
250 };
251
252 GNUNET_NETWORK_STRUCT_END
253
254 /**
255  * Store an item in the namestore.  If the item is already present,
256  * it is replaced with the new record.  
257  *
258  * @param h handle to the namestore
259  * @param block block to store
260  * @param cont continuation to call when done
261  * @param cont_cls closure for @a cont
262  * @return handle to abort the request
263  */
264 struct GNUNET_NAMESTORE_QueueEntry *
265 GNUNET_NAMESTORE_block_cache (struct GNUNET_NAMESTORE_Handle *h,
266                               const struct GNUNET_NAMESTORE_Block *block,
267                               GNUNET_NAMESTORE_ContinuationWithStatus cont,
268                               void *cont_cls);
269
270
271 /**
272  * Store an item in the namestore.  If the item is already present,
273  * it is replaced with the new record.  Use an empty array to
274  * remove all records under the given name.
275  *
276  * @param h handle to the namestore
277  * @param pkey private key of the zone
278  * @param label name that is being mapped (at most 255 characters long)
279  * @param rd_count number of records in the 'rd' array
280  * @param rd array of records with data to store
281  * @param cont continuation to call when done
282  * @param cont_cls closure for @a cont
283  * @return handle to abort the request
284  */
285 struct GNUNET_NAMESTORE_QueueEntry *
286 GNUNET_NAMESTORE_records_store (struct GNUNET_NAMESTORE_Handle *h,
287                                 const struct GNUNET_CRYPTO_EccPrivateKey *pkey,
288                                 const char *label,
289                                 unsigned int rd_count,
290                                 const struct GNUNET_NAMESTORE_RecordData *rd,
291                                 GNUNET_NAMESTORE_ContinuationWithStatus cont,
292                                 void *cont_cls);
293
294
295 /**
296  * Process a record that was stored in the namestore.
297  *
298  * @param cls closure
299  * @param block block that was stored in the namestore
300  */
301 typedef void (*GNUNET_NAMESTORE_BlockProcessor) (void *cls,
302                                                  const struct GNUNET_NAMESTORE_Block *block);
303
304
305 /**
306  * Get a result for a particular key from the namestore.  The processor
307  * will only be called once.  
308  *
309  * @param h handle to the namestore
310  * @param derived_hash hash of zone key combined with name to lookup
311  * @param proc function to call on the matching block, or with
312  *        NULL if there is no matching block
313  * @param proc_cls closure for @a proc
314  * @return a handle that can be used to cancel
315  */
316 struct GNUNET_NAMESTORE_QueueEntry *
317 GNUNET_NAMESTORE_lookup_block (struct GNUNET_NAMESTORE_Handle *h, 
318                                const struct GNUNET_HashCode *derived_hash,
319                                GNUNET_NAMESTORE_BlockProcessor proc, void *proc_cls);
320
321
322 /**
323  * Process a record that was stored in the namestore.
324  *
325  * @param cls closure
326  * @param zone private key of the zone; NULL on disconnect
327  * @param label label of the records; NULL on disconnect
328  * @param rd_count number of entries in @a rd array, 0 if label was deleted
329  * @param rd array of records with data to store
330  */
331 typedef void (*GNUNET_NAMESTORE_RecordMonitor) (void *cls,
332                                                 const struct GNUNET_CRYPTO_EccPrivateKey *zone,
333                                                 const char *label,
334                                                 unsigned int rd_count,
335                                                 const struct GNUNET_NAMESTORE_RecordData *rd);
336
337
338 /**
339  * Look for an existing PKEY delegation record for a given public key.
340  * Returns at most one result to the processor.
341  *
342  * @param h handle to the namestore
343  * @param zone public key of the zone to look up in, never NULL
344  * @param value_zone public key of the target zone (value), never NULL
345  * @param proc function to call on the matching records, or with
346  *        NULL (rd_count == 0) if there are no matching records
347  * @param proc_cls closure for @a proc
348  * @return a handle that can be used to
349  *         cancel
350  */
351 struct GNUNET_NAMESTORE_QueueEntry *
352 GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h, 
353                                const struct GNUNET_CRYPTO_EccPrivateKey *zone,
354                                const struct GNUNET_CRYPTO_EccPublicSignKey *value_zone,
355                                GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls);
356
357
358 /**
359  * Process a records that were decrypted from a block.
360  *
361  * @param cls closure
362  * @param rd_count number of entries in @a rd array
363  * @param rd array of records with data to store
364  */
365 typedef void (*GNUNET_NAMESTORE_RecordCallback) (void *cls,
366                                                  unsigned int rd_count,
367                                                  const struct GNUNET_NAMESTORE_RecordData *rd);
368
369
370 /**
371  * Cancel a namestore operation.  The final callback from the
372  * operation must not have been done yet.  Must be called on any
373  * namestore operation that has not yet completed prior to calling
374  * #GNUNET_NAMESTORE_disconnect.
375  *
376  * @param qe operation to cancel
377  */
378 void
379 GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe);
380
381
382 /**
383  * Starts a new zone iteration (used to periodically PUT all of our
384  * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle
385  * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and
386  * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once
387  * immediately, and then again after
388  * #GNUNET_NAMESTORE_zone_iterator_next is invoked.
389  *
390  * @param h handle to the namestore
391  * @param zone zone to access, NULL for all zones
392  * @param proc function to call on each name from the zone; it
393  *        will be called repeatedly with a value (if available)
394  *        and always once at the end with a name of NULL.
395  * @param proc_cls closure for @a proc
396  * @return an iterator handle to use for iteration
397  */
398 struct GNUNET_NAMESTORE_ZoneIterator *
399 GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h,
400                                        const struct GNUNET_CRYPTO_EccPrivateKey *zone,
401                                        GNUNET_NAMESTORE_RecordMonitor proc,
402                                        void *proc_cls);
403
404
405 /**
406  * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start
407  * for the next record.
408  *
409  * @param it the iterator
410  */
411 void
412 GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it);
413
414
415 /**
416  * Stops iteration and releases the namestore handle for further calls.  Must
417  * be called on any iteration that has not yet completed prior to calling
418  * #GNUNET_NAMESTORE_disconnect.
419  *
420  * @param it the iterator
421  */
422 void
423 GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it);
424
425
426 /**
427  * Handle for a monitoring activity.
428  */
429 struct GNUNET_NAMESTORE_ZoneMonitor;
430
431
432 /**
433  * Function called once the monitor has caught up with the current 
434  * state of the database.  Will be called AGAIN after each disconnect
435  * (record monitor called with 'NULL' for zone_key) once we're again
436  * in sync.
437  *
438  * @param cls closure
439  */
440 typedef void (*GNUNET_NAMESTORE_RecordsSynchronizedCallback)(void *cls);
441
442
443 /**
444  * Begin monitoring a zone for changes.  Will first call the @a monitor function
445  * on all existing records in the selected zone(s), then calls @a sync_cb,
446  * and then calls the @a monitor whenever a record changes.  If the namestore
447  * disconnects, the @a monitor function is called with a disconnect event; if
448  * the connection is re-established, the process begins from the start (all
449  * existing records, sync, then updates).
450  *
451  * @param cfg configuration to use to connect to namestore
452  * @param zone zone to monitor
453  * @param monitor function to call on zone changes
454  * @param sync_cb function called when we're in sync with the namestore
455  * @param cls closure for @a monitor and @a sync_cb
456  * @return handle to stop monitoring
457  */
458 struct GNUNET_NAMESTORE_ZoneMonitor *
459 GNUNET_NAMESTORE_zone_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
460                                      const struct GNUNET_CRYPTO_EccPrivateKey *zone,
461                                      GNUNET_NAMESTORE_RecordMonitor monitor,
462                                      GNUNET_NAMESTORE_RecordsSynchronizedCallback sync_cb,
463                                      void *cls);
464
465
466 /**
467  * Stop monitoring a zone for changes.
468  *
469  * @param zm handle to the monitor activity to stop
470  */
471 void
472 GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm);
473
474
475 /* convenience APIs for serializing / deserializing GNS records */
476
477 /**
478  * Calculate how many bytes we will need to serialize the given
479  * records.
480  *
481  * @param rd_count number of records in the @a rd array
482  * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
483  * @return the required size to serialize
484  */
485 size_t
486 GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
487                                    const struct GNUNET_NAMESTORE_RecordData *rd);
488
489
490 /**
491  * Serialize the given records to the given destination buffer.
492  *
493  * @param rd_count number of records in the @a rd array
494  * @param rd array of #GNUNET_NAMESTORE_RecordData with @a rd_count elements
495  * @param dest_size size of the destination array @a dst
496  * @param dest where to write the result
497  * @return the size of serialized records, -1 if records do not fit
498  */
499 ssize_t
500 GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
501                                     const struct GNUNET_NAMESTORE_RecordData *rd,
502                                     size_t dest_size,
503                                     char *dest);
504
505
506 /**
507  * Deserialize the given records to the given destination.
508  *
509  * @param len size of the serialized record data
510  * @param src the serialized record data
511  * @param rd_count number of records in the @a dest array
512  * @param dest where to put the data
513  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
514  */
515 int
516 GNUNET_NAMESTORE_records_deserialize (size_t len,
517                                       const char *src,
518                                       unsigned int rd_count,
519                                       struct GNUNET_NAMESTORE_RecordData *dest);
520
521
522 /**
523  * Convert the binary value @a data of a record of 
524  * type @a type to a human-readable string.
525  *
526  * @param type type of the record
527  * @param data value in binary encoding
528  * @param data_size number of bytes in @a data
529  * @return NULL on error, otherwise human-readable representation of the value
530  */
531 char *
532 GNUNET_NAMESTORE_value_to_string (uint32_t type,
533                                   const void *data,
534                                   size_t data_size);
535
536
537 /**
538  * Convert human-readable version of the value @a s of a record
539  * of type @a type to the respective binary representation.
540  *
541  * @param type type of the record
542  * @param s human-readable string
543  * @param data set to value in binary encoding (will be allocated)
544  * @param data_size set to number of bytes in @a data
545  * @return #GNUNET_OK on success
546  */
547 int
548 GNUNET_NAMESTORE_string_to_value (uint32_t type,
549                                   const char *s,
550                                   void **data,
551                                   size_t *data_size);
552
553
554 /**
555  * Convert a type name (i.e. "AAAA") to the corresponding number.
556  *
557  * @param typename name to convert
558  * @return corresponding number, UINT32_MAX on error
559  */
560 uint32_t
561 GNUNET_NAMESTORE_typename_to_number (const char *typename);
562
563
564 /**
565  * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
566  *
567  * @param type number of a type to convert
568  * @return corresponding typestring, NULL on error
569  */
570 const char *
571 GNUNET_NAMESTORE_number_to_typename (uint32_t type);
572
573
574 /**
575  * Test if a given record is expired.
576  * 
577  * @param rd record to test
578  * @return #GNUNET_YES if the record is expired,
579  *         #GNUNET_NO if not
580  */
581 int
582 GNUNET_NAMESTORE_is_expired (const struct GNUNET_NAMESTORE_RecordData *rd);
583
584
585 /**
586  * Convert a UTF-8 string to UTF-8 lowercase
587  * @param src source string
588  * @return converted result
589  */
590 char *
591 GNUNET_NAMESTORE_normalize_string (const char *src);
592
593
594 /**
595  * Convert a zone to a string (for printing debug messages).
596  * This is one of the very few calls in the entire API that is
597  * NOT reentrant!
598  *
599  * @param z public key of a zone
600  * @return string form; will be overwritten by next call to #GNUNET_NAMESTORE_z2s.
601  */
602 const char *
603 GNUNET_NAMESTORE_z2s (const struct GNUNET_CRYPTO_EccPublicSignKey *z);
604
605
606 /**
607  * Convert public key to the respective absolute domain name in the
608  * ".zkey" pTLD. 
609  * This is one of the very few calls in the entire API that is
610  * NOT reentrant!
611  * 
612  * @param pkey a public key with a point on the eliptic curve 
613  * @return string "X.zkey" where X is the coordinates of the public
614  *         key in an encoding suitable for DNS labels.
615  */
616 const char *
617 GNUNET_NAMESTORE_pkey_to_zkey (const struct GNUNET_CRYPTO_EccPublicSignKey *pkey);
618
619
620 /**
621  * Convert an absolute domain name in the ".zkey" pTLD to the
622  * respective public key.
623  * 
624  * @param zkey string "X.zkey" where X is the public
625  *         key in an encoding suitable for DNS labels.
626  * @param pkey set to a public key on the eliptic curve 
627  * @return #GNUNET_SYSERR if @a zkey has the wrong syntax
628  */
629 int
630 GNUNET_NAMESTORE_zkey_to_pkey (const char *zkey,
631                                struct GNUNET_CRYPTO_EccPublicSignKey *pkey);
632
633
634 /**
635  * Calculate the DHT query for a given @a label in a given @a zone.
636  * 
637  * @param zone private key of the zone
638  * @param label label of the record
639  * @param query hash to use for the query
640  */
641 void
642 GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EccPrivateKey *zone,
643                                          const char *label,
644                                          struct GNUNET_HashCode *query);
645
646
647 /**
648  * Calculate the DHT query for a given @a label in a given @a zone.
649  * 
650  * @param pub public key of the zone
651  * @param label label of the record
652  * @param query hash to use for the query
653  */
654 void
655 GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EccPublicSignKey *pub,
656                                         const char *label,
657                                         struct GNUNET_HashCode *query);
658
659
660 /**
661  * Sign name and records
662  *
663  * @param key the private key
664  * @param expire block expiration
665  * @param label the name for the records
666  * @param rd record data
667  * @param rd_count number of records in @a rd
668  */
669 struct GNUNET_NAMESTORE_Block *
670 GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EccPrivateKey *key,
671                                struct GNUNET_TIME_Absolute expire,
672                                const char *label,
673                                const struct GNUNET_NAMESTORE_RecordData *rd,
674                                unsigned int rd_count);
675
676
677 /**
678  * Check if a signature is valid.  This API is used by the GNS Block
679  * to validate signatures received from the network.
680  *
681  * @param block block to verify
682  * @return #GNUNET_OK if the signature is valid
683  */
684 int
685 GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block);
686
687
688 /**
689  * Decrypt block.
690  *
691  * @param block block to decrypt
692  * @param zone_key public key of the zone
693  * @param label the name for the records
694  * @param proc function to call with the result
695  * @param proc_cls closure for @a proc
696  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was 
697  *        not well-formed
698  */
699 int
700 GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
701                                 const struct GNUNET_CRYPTO_EccPublicSignKey *zone_key,
702                                 const char *label,
703                                 GNUNET_NAMESTORE_RecordCallback proc,
704                                 void *proc_cls);
705
706
707 /**
708  * Compares if two records are equal
709  *
710  * @param a a record
711  * @param b another record 
712  * @return #GNUNET_YES if the records are equal, or #GNUNET_NO if not.
713  */
714 int
715 GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
716                               const struct GNUNET_NAMESTORE_RecordData *b);
717
718
719 /**
720  * Returns the expiration time of the given block of records. The block
721  * expiration time is the expiration time of the block with smallest
722  * expiration time.
723  *
724  * @param rd_count number of records given in @a rd
725  * @param rd array of records 
726  * @return absolute expiration time
727  */
728 struct GNUNET_TIME_Absolute
729 GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count, 
730                                              const struct GNUNET_NAMESTORE_RecordData *rd);
731
732
733 #if 0                           /* keep Emacsens' auto-indent happy */
734 {
735 #endif
736 #ifdef __cplusplus
737 }
738 #endif
739
740 /* end of gnunet_namestore_service.h */
741 #endif