-towards block plugin for mesh
[oweals/gnunet.git] / src / namestore / gnunet-service-namestore.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 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/gnunet-service-namestore.c
23  * @brief namestore for the GNUnet naming system
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_getopt_lib.h"
28 #include "gnunet_service_lib.h"
29 #include "gnunet_namestore_service.h"
30 #include "gnunet_namestore_plugin.h"
31 #include "gnunet_signatures.h"
32 #include "namestore.h"
33
34 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
35
36 /**
37  * A namestore operation.
38  */
39 struct GNUNET_NAMESTORE_ZoneIteration
40 {
41   struct GNUNET_NAMESTORE_ZoneIteration *next;
42   struct GNUNET_NAMESTORE_ZoneIteration *prev;
43
44   struct GNUNET_NAMESTORE_Client * client;
45
46   int has_zone;
47
48   struct GNUNET_CRYPTO_ShortHashCode zone;
49
50   uint64_t request_id;
51   uint32_t offset;
52
53   /**
54    * Which flags must be included
55    */
56   uint16_t must_have_flags;
57
58   /**
59    * Which flags must not be included
60    */
61   uint16_t must_not_have_flags;
62 };
63
64
65 /**
66  * A namestore client
67  */
68 struct GNUNET_NAMESTORE_Client
69 {
70   struct GNUNET_NAMESTORE_Client *next;
71   struct GNUNET_NAMESTORE_Client *prev;
72
73   struct GNUNET_SERVER_Client * client;
74
75   struct GNUNET_NAMESTORE_ZoneIteration *op_head;
76   struct GNUNET_NAMESTORE_ZoneIteration *op_tail;
77 };
78
79 struct GNUNET_NAMESTORE_CryptoContainer
80 {
81   char * filename;
82
83   struct GNUNET_CRYPTO_ShortHashCode zone;
84   struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
85   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
86 };
87
88
89 /**
90 * Configuration handle.
91 */
92 const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
93
94 /**
95 * Database handle
96 */
97 struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
98
99 /**
100 * Zonefile directory
101 */
102 static char *zonefile_directory;
103
104 static char *db_lib_name;
105
106
107 /**
108  * Our notification context.
109  */
110 static struct GNUNET_SERVER_NotificationContext *snc;
111
112 static struct GNUNET_NAMESTORE_Client *client_head;
113 static struct GNUNET_NAMESTORE_Client *client_tail;
114
115 struct GNUNET_CONTAINER_MultiHashMap *zonekeys;
116
117
118 /**
119  * Write zonefile to disk
120  * @param filename where to write
121  * @param c the crypto container
122  *
123  * @return GNUNET_OK on success, GNUNET_SYSERR on fail
124  */
125
126 int
127 write_key_to_file (const char *filename, struct GNUNET_NAMESTORE_CryptoContainer *c)
128 {
129   struct GNUNET_CRYPTO_RsaPrivateKey *ret = c->privkey;
130   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
131   struct GNUNET_DISK_FileHandle *fd;
132
133   if (GNUNET_YES == GNUNET_DISK_file_test (filename))
134   {
135     struct GNUNET_CRYPTO_ShortHashCode zone;
136     struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
137     struct GNUNET_CRYPTO_RsaPrivateKey * privkey;
138
139     privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename);
140     if (privkey == NULL)
141     {
142       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
143            _("File zone `%s' but corrupt content already exists, failed to write! \n"), GNUNET_short_h2s (&zone));
144       return GNUNET_SYSERR;
145     }
146
147     GNUNET_CRYPTO_rsa_key_get_public (privkey, &pubkey);
148     GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone);
149     GNUNET_CRYPTO_rsa_key_free (privkey);
150
151     if (0 == memcmp (&zone, &c->zone, sizeof(zone)))
152     {
153       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
154            _("File zone `%s' containing this key already exists\n"), GNUNET_short_h2s (&zone));
155       return GNUNET_OK;
156     }
157     else
158     {
159       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
160            _("File zone `%s' but different zone key already exists, failed to write! \n"), GNUNET_short_h2s (&zone));
161       return GNUNET_OK;
162     }
163   }
164   fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
165   if (NULL == fd)
166   {
167     if (errno == EEXIST)
168     {
169       if (GNUNET_YES != GNUNET_DISK_file_test (filename))
170       {
171         /* must exist but not be accessible, fail for good! */
172         if (0 != ACCESS (filename, R_OK))
173           LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
174         else
175           GNUNET_break (0);   /* what is going on!? */
176         return GNUNET_SYSERR;
177       }
178     }
179     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
180     return GNUNET_SYSERR;
181   }
182
183   if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES))
184   {
185     GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
186     return GNUNET_SYSERR;
187   }
188   enc = GNUNET_CRYPTO_rsa_encode_key (ret);
189   GNUNET_assert (enc != NULL);
190   GNUNET_assert (ntohs (enc->len) == GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
191   GNUNET_free (enc);
192   GNUNET_DISK_file_sync (fd);
193   if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
194     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
195   GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
196
197   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
198        _("Stored zonekey for zone `%s' in file `%s'\n"), GNUNET_short_h2s(&c->zone), c->filename);
199   return GNUNET_OK;
200 }
201
202 int zone_to_disk_it (void *cls,
203                      const struct GNUNET_HashCode *key,
204                      void *value)
205 {
206   struct GNUNET_NAMESTORE_CryptoContainer * c = value;
207   if (c->filename != NULL)
208     write_key_to_file(c->filename, c);
209   else
210   {
211     GNUNET_asprintf(&c->filename, "%s/%s.zkey", zonefile_directory, GNUNET_short_h2s (&c->zone));
212     write_key_to_file(c->filename, c);
213   }
214
215
216   GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (zonekeys, key, value));
217   GNUNET_CRYPTO_rsa_key_free (c->privkey);
218   GNUNET_free (c->pubkey);
219   GNUNET_free (c->filename);
220   GNUNET_free (c);
221
222   return GNUNET_OK;
223 }
224
225
226 struct GNUNET_TIME_Absolute
227 get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd)
228 {
229   unsigned int c;
230   struct GNUNET_TIME_Absolute expire = GNUNET_TIME_UNIT_FOREVER_ABS;
231   struct GNUNET_TIME_Absolute at;
232   struct GNUNET_TIME_Relative rt;
233
234   if (NULL == rd)
235     return GNUNET_TIME_UNIT_ZERO_ABS;
236   for (c = 0; c < rd_count; c++)  
237   {
238     if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
239     {
240       rt.rel_value = rd[c].expiration_time;
241       at = GNUNET_TIME_relative_to_absolute (rt);
242     }
243     else
244     {
245       at.abs_value = rd[c].expiration_time;
246     }
247     expire = GNUNET_TIME_absolute_min (at, expire);  
248   }
249   return expire;
250 }
251
252 /**
253  * Task run during shutdown.
254  *
255  * @param cls unused
256  * @param tc unused
257  */
258 static void
259 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
260 {
261   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
262   struct GNUNET_NAMESTORE_ZoneIteration * no;
263   struct GNUNET_NAMESTORE_ZoneIteration * tmp;
264   struct GNUNET_NAMESTORE_Client * nc;
265   struct GNUNET_NAMESTORE_Client * next;
266
267   if (NULL != snc)
268   {
269     GNUNET_SERVER_notification_context_destroy (snc);
270     snc = NULL;
271   }
272   GNUNET_CONTAINER_multihashmap_iterate(zonekeys, &zone_to_disk_it, NULL);
273   GNUNET_CONTAINER_multihashmap_destroy(zonekeys);
274
275   for (nc = client_head; nc != NULL; nc = next)
276   {
277     next = nc->next;
278     for (no = nc->op_head; no != NULL; no = tmp)
279     {
280       GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
281       tmp = no->next;
282       GNUNET_free (no);
283     }
284     GNUNET_SERVER_client_drop(nc->client);
285     GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
286     GNUNET_free (nc);
287   }
288
289   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
290   GNUNET_free (db_lib_name);
291   GNUNET_free_non_null(zonefile_directory);
292 }
293
294 static struct GNUNET_NAMESTORE_Client *
295 client_lookup (struct GNUNET_SERVER_Client *client)
296 {
297   struct GNUNET_NAMESTORE_Client * nc;
298
299   GNUNET_assert (NULL != client);
300
301   for (nc = client_head; nc != NULL; nc = nc->next)
302   {
303     if (client == nc->client)
304       break;
305   }
306   return nc;
307 }
308
309 /**
310  * Called whenever a client is disconnected.  Frees our
311  * resources associated with that client.
312  *
313  * @param cls closure
314  * @param client identification of the client
315  */
316 static void
317 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
318 {
319   struct GNUNET_NAMESTORE_ZoneIteration * no;
320   struct GNUNET_NAMESTORE_Client * nc;
321   if (NULL == client)
322     return;
323
324   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client);
325
326   nc = client_lookup (client);
327
328   if ((NULL == client) || (NULL == nc))
329     return;
330
331   no = nc->op_head;
332   while (NULL != no)
333   {
334     GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
335     GNUNET_free (no);
336     no = nc->op_head;
337   }
338
339   GNUNET_SERVER_client_drop(nc->client);
340   GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
341   GNUNET_free (nc);
342   nc = NULL;
343 }
344
345
346
347 static void handle_start (void *cls,
348                           struct GNUNET_SERVER_Client * client,
349                           const struct GNUNET_MessageHeader * message)
350 {
351   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
352
353   struct GNUNET_NAMESTORE_Client * nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
354   nc->client = client;
355   GNUNET_SERVER_notification_context_add (snc, client);
356   GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc);
357   GNUNET_SERVER_client_keep (client);
358   GNUNET_SERVER_receive_done (client, GNUNET_OK);
359 }
360
361 struct LookupNameContext
362 {
363   struct GNUNET_NAMESTORE_Client *nc;
364   uint32_t request_id;
365   uint32_t record_type;
366   struct GNUNET_CRYPTO_ShortHashCode *zone;
367   char * name;
368 };
369
370 void drop_iterator (void *cls,
371                    const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
372                    struct GNUNET_TIME_Absolute expire,
373                    const char *name,
374                    unsigned int rd_len,
375                    const struct GNUNET_NAMESTORE_RecordData *rd,
376                    const struct GNUNET_CRYPTO_RsaSignature *signature)
377 {
378   struct GNUNET_CRYPTO_ShortHashCode zone_hash;
379   int * stop = cls;
380   if (NULL != zone_key)
381   {
382     GNUNET_CRYPTO_short_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_hash);
383     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting zone `%s'\n", GNUNET_short_h2s (&zone_hash));
384     GSN_database->delete_zone (GSN_database->cls, &zone_hash);
385   }
386   else
387   {
388     (*stop) = GNUNET_YES;
389   }
390 }
391
392
393 static void
394 handle_lookup_name_it (void *cls,
395     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
396     struct GNUNET_TIME_Absolute expire,
397     const char *name,
398     unsigned int rd_count,
399     const struct GNUNET_NAMESTORE_RecordData *rd,
400     const struct GNUNET_CRYPTO_RsaSignature *signature)
401 {
402   /* send response */
403   struct LookupNameContext *lnc = cls;
404   struct LookupNameResponseMessage *lnr_msg;
405   struct GNUNET_NAMESTORE_RecordData *rd_selected = NULL;
406   struct GNUNET_NAMESTORE_CryptoContainer *cc;
407   struct GNUNET_CRYPTO_RsaSignature *signature_new = NULL;
408   struct GNUNET_TIME_Absolute e;
409   struct GNUNET_CRYPTO_ShortHashCode zone_key_hash;
410   struct GNUNET_HashCode long_hash;
411   char *rd_tmp;
412   char *name_tmp;
413   size_t rd_ser_len;
414   size_t r_size = 0;
415   size_t name_len = 0;
416
417   int copied_elements = 0;
418   int contains_signature = GNUNET_NO;
419   int authoritative = GNUNET_NO;
420   int c;
421
422   if (NULL != name)
423     name_len = strlen(name) + 1;
424
425   /* count records to copy */
426   if (rd_count != 0)
427   {
428     if (lnc->record_type != 0)
429     {
430       /* special record type needed */
431       for (c = 0; c < rd_count; c ++)
432         if (rd[c].record_type == lnc->record_type)
433           copied_elements++; /* found matching record */
434       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records with type %u for name `%s' in zone `%s'\n",
435           copied_elements, lnc->record_type, lnc->name, GNUNET_short_h2s(lnc->zone));
436       rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
437       copied_elements = 0;
438       for (c = 0; c < rd_count; c ++)
439       {
440         if (rd[c].record_type == lnc->record_type)
441         {
442           /* found matching record */
443           memcpy (&rd_selected[copied_elements], &rd[c], sizeof (struct GNUNET_NAMESTORE_RecordData));
444           copied_elements++;
445         }
446       }
447     }
448     else
449     {
450       copied_elements = rd_count;
451       rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
452     }
453   }
454   else
455   {
456     /* No results */
457     copied_elements = 0;
458     rd_selected = NULL;
459     expire = GNUNET_TIME_UNIT_ZERO_ABS;
460   }
461
462   rd_ser_len = GNUNET_NAMESTORE_records_get_size(copied_elements, rd_selected);
463   char rd_ser[rd_ser_len];
464   GNUNET_NAMESTORE_records_serialize(copied_elements, rd_selected, rd_ser_len, rd_ser);
465
466   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records for name `%s' in zone `%s'\n",
467       copied_elements, lnc->name, GNUNET_short_h2s(lnc->zone));
468
469   if ((copied_elements == rd_count) && (NULL != signature))
470     contains_signature = GNUNET_YES; /* returning all records, so include signature */
471   else
472     contains_signature = GNUNET_NO; /* returning not all records, so do not include signature */
473
474
475   if ((NULL != zone_key) && (copied_elements == rd_count))
476   {
477     GNUNET_CRYPTO_short_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_key_hash);
478     GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash);
479     if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
480     {
481       cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
482       e = get_block_expiration_time(rd_count, rd);
483       signature_new = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd, rd_count);
484       GNUNET_assert (signature_new != NULL);
485       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for name `%s' with %u records in zone `%s'\n",name, copied_elements, GNUNET_short_h2s(&zone_key_hash));
486       authoritative = GNUNET_YES;
487     }
488     else
489       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am not authoritative for name `%s' in zone `%s'\n",name, GNUNET_short_h2s(&zone_key_hash));
490   }
491
492   r_size = sizeof (struct LookupNameResponseMessage) +
493            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
494            name_len +
495            rd_ser_len;
496
497   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE");
498   lnr_msg = GNUNET_malloc (r_size);
499   lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
500   lnr_msg->gns_header.header.size = ntohs (r_size);
501   lnr_msg->gns_header.r_id = htonl (lnc->request_id);
502   lnr_msg->rd_count = htons (copied_elements);
503   lnr_msg->rd_len = htons (rd_ser_len);
504   lnr_msg->name_len = htons (name_len);
505   lnr_msg->expire = GNUNET_TIME_absolute_hton(get_block_expiration_time(copied_elements, rd_selected));
506
507   if (rd_selected != rd)
508     GNUNET_free (rd_selected);
509
510   if (zone_key != NULL)
511     lnr_msg->public_key = (*zone_key);
512   else
513     memset(&lnr_msg->public_key, '\0', sizeof (lnr_msg->public_key));
514
515   if (GNUNET_YES == authoritative)
516   { /* use new created signature */
517     lnr_msg->contains_sig = htons (GNUNET_YES);
518     GNUNET_assert (signature_new != NULL);
519     lnr_msg->signature = *signature_new;
520     GNUNET_free (signature_new);
521   }
522   else if (GNUNET_YES == contains_signature)
523   {
524     /* use existing signature */
525     lnr_msg->contains_sig = htons (GNUNET_YES);
526     GNUNET_assert (signature != NULL);
527     lnr_msg->signature = *signature;
528   }
529   else
530   {
531     /* use no signature */
532     memset (&lnr_msg->signature, '\0', sizeof (lnr_msg->signature));
533   }
534
535   name_tmp = (char *) &lnr_msg[1];
536   rd_tmp = &name_tmp[name_len];
537
538   memcpy (name_tmp, name, name_len);
539   memcpy (rd_tmp, rd_ser, rd_ser_len);
540
541   GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO);
542   GNUNET_free (lnr_msg);
543 }
544
545 static void handle_lookup_name (void *cls,
546                           struct GNUNET_SERVER_Client * client,
547                           const struct GNUNET_MessageHeader * message)
548 {
549   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME");
550   struct LookupNameContext lnc;
551   struct GNUNET_NAMESTORE_Client *nc;
552   size_t name_len;
553   char * name;
554   uint32_t rid = 0;
555   uint32_t type = 0;
556
557   if (ntohs (message->size) < sizeof (struct LookupNameMessage))
558   {
559     GNUNET_break_op (0);
560     GNUNET_SERVER_receive_done (client, GNUNET_OK);
561     return;
562   }
563
564   nc = client_lookup(client);
565   if (nc == NULL)
566   {
567     GNUNET_break_op (0);
568     GNUNET_SERVER_receive_done (client, GNUNET_OK);
569     return;
570   }
571
572   struct LookupNameMessage * ln_msg = (struct LookupNameMessage *) message;
573   rid = ntohl (ln_msg->gns_header.r_id);
574   name_len = ntohl (ln_msg->name_len);
575   type = ntohl (ln_msg->record_type);
576
577   if ((name_len == 0) || (name_len > 256))
578   {
579     GNUNET_break_op (0);
580     GNUNET_SERVER_receive_done (client, GNUNET_OK);
581     return;
582   }
583
584   name = (char *) &ln_msg[1];
585   if (name[name_len -1] != '\0')
586   {
587     GNUNET_break_op (0);
588     GNUNET_SERVER_receive_done (client, GNUNET_OK);
589     return;
590   }
591
592   if (0 == type)
593     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up all records for name `%s' in zone `%s'\n", name, GNUNET_short_h2s(&ln_msg->zone));
594   else
595     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up records with type %u for name `%s' in zone `%s'\n", type, name, GNUNET_short_h2s(&ln_msg->zone));
596
597   /* do the actual lookup */
598   lnc.request_id = rid;
599   lnc.nc = nc;
600   lnc.record_type = type;
601   lnc.name = name;
602   lnc.zone = &ln_msg->zone;
603   GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, name, 0, &handle_lookup_name_it, &lnc);
604
605   GNUNET_SERVER_receive_done (client, GNUNET_OK);
606 }
607
608 static void handle_record_put (void *cls,
609                           struct GNUNET_SERVER_Client * client,
610                           const struct GNUNET_MessageHeader * message)
611 {
612   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT");
613   struct GNUNET_NAMESTORE_Client *nc;
614   struct GNUNET_TIME_Absolute expire;
615   struct GNUNET_CRYPTO_RsaSignature *signature;
616   struct RecordPutResponseMessage rpr_msg;
617   size_t name_len;
618   size_t msg_size;
619   size_t msg_size_exp;
620   char * name;
621   char * rd_ser;
622   uint32_t rid = 0;
623   uint32_t rd_ser_len;
624   uint32_t rd_count;
625   int res = GNUNET_SYSERR;
626
627   if (ntohs (message->size) < sizeof (struct RecordPutMessage))
628   {
629     GNUNET_break_op (0);
630     GNUNET_SERVER_receive_done (client, GNUNET_OK);
631     return;
632   }
633
634   nc = client_lookup (client);
635   if (nc == NULL)
636   {
637     GNUNET_break_op (0);
638     GNUNET_SERVER_receive_done (client, GNUNET_OK);
639     return;
640   }
641
642   struct RecordPutMessage * rp_msg = (struct RecordPutMessage *) message;
643
644   rid = ntohl (rp_msg->gns_header.r_id);
645   msg_size = ntohs (rp_msg->gns_header.header.size);
646   name_len = ntohs (rp_msg->name_len);
647   rd_count = ntohs (rp_msg->rd_count);
648   rd_ser_len = ntohs(rp_msg->rd_len);
649
650   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
651   {
652     GNUNET_break_op (0);
653     GNUNET_SERVER_receive_done (client, GNUNET_OK);
654     return;
655   }
656
657   if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
658   {
659     GNUNET_break_op (0);
660     GNUNET_SERVER_receive_done (client, GNUNET_OK);
661     return;
662   }
663
664   msg_size_exp = sizeof (struct RecordPutMessage) +  name_len  + rd_ser_len;
665   if (msg_size != msg_size_exp)
666   {
667     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
668     GNUNET_break_op (0);
669     GNUNET_SERVER_receive_done (client, GNUNET_OK);
670     return;
671   }
672   if ((name_len == 0) || (name_len > 256))
673   {
674     GNUNET_break_op (0);
675     GNUNET_SERVER_receive_done (client, GNUNET_OK);
676     return;
677   }
678
679   name = (char *) &rp_msg[1];
680
681   if (name[name_len -1] != '\0')
682   {
683     GNUNET_break_op (0);
684     GNUNET_SERVER_receive_done (client, GNUNET_OK);
685     return;
686   }
687
688   expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
689   signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature;
690
691   rd_ser = &name[name_len];
692   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
693   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
694   if (res != GNUNET_OK)
695   {
696     GNUNET_break_op (0);
697     goto send;
698   }
699
700   struct GNUNET_CRYPTO_ShortHashCode zone_hash;
701   GNUNET_CRYPTO_short_hash (&rp_msg->public_key, sizeof (rp_msg->public_key), &zone_hash);
702
703   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting %u record for name `%s' in zone `%s'\n", rd_count, name, GNUNET_short_h2s(&zone_hash));
704
705   /* Database operation */
706   res = GSN_database->put_records(GSN_database->cls,
707                                 &rp_msg->public_key,
708                                 expire,
709                                 name,
710                                 rd_count, rd,
711                                 signature);
712
713   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n",
714       name, (res == GNUNET_OK) ? "OK" : "FAIL");
715
716   /* Send response */
717 send:
718   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE");
719   rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
720   rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
721   rpr_msg.gns_header.r_id = htonl (rid);
722   rpr_msg.op_result = htonl (res);
723   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO);
724
725   GNUNET_SERVER_receive_done (client, GNUNET_OK);
726 }
727
728 struct CreateRecordContext
729 {
730   struct GNUNET_NAMESTORE_RecordData *rd;
731   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
732   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
733   struct GNUNET_TIME_Absolute expire;
734   char *name;
735   int res;
736 };
737
738
739 static void
740 handle_create_record_it (void *cls,
741                          const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
742                          struct GNUNET_TIME_Absolute expire,
743                          const char *name,
744                          unsigned int rd_count,
745                          const struct GNUNET_NAMESTORE_RecordData *rd,
746                          const struct GNUNET_CRYPTO_RsaSignature *signature)
747 {
748   struct CreateRecordContext * crc = cls;
749   struct GNUNET_NAMESTORE_RecordData *rd_new = NULL;
750   struct GNUNET_CRYPTO_RsaSignature dummy_signature;
751   struct GNUNET_TIME_Absolute block_expiration;
752   int res;
753   int exist = GNUNET_SYSERR;
754   int update = GNUNET_NO;
755   int c;
756   int rd_count_new = 0;
757
758   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, crc->name);
759   for (c = 0; c < rd_count; c++)
760   {
761     if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PKEY) && 
762          (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PKEY))
763     {
764       /* Update unique PKEY */
765       exist = c;
766       update = GNUNET_YES;
767       break;
768     }
769     if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PSEU) && 
770          (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PSEU))
771     {
772       /* Update unique PSEU */
773       exist = c;
774       update = GNUNET_YES;
775       break;
776     }
777     if ((crc->rd->record_type == rd[c].record_type) &&
778         (crc->rd->data_size == rd[c].data_size) &&
779         (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
780     {
781       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
782                   "Found existing records for `%s' to update expiration date!\n",
783                   crc->name);
784       exist = c;
785       if ( (crc->rd->expiration_time != rd[c].expiration_time) &&
786            ((crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) 
787             == (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) ) )
788         update = GNUNET_YES;
789       break;
790     }
791   }
792
793   if (exist == GNUNET_SYSERR)
794   {
795     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
796                 "No existing record for name `%s'!\n", 
797                 crc->name);
798     rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
799     memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
800     rd_count_new = rd_count + 1;
801     rd_new[rd_count] = *(crc->rd);
802   }
803   else if (update == GNUNET_NO)
804   {
805     /* Exact same record already exists */
806     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
807                 "Matching record for %s' exists, no change required!\n",
808                 crc->name);
809     res = GNUNET_NO;
810     goto end;
811   }
812   else 
813   {
814     /* Update record */
815     GNUNET_assert (GNUNET_YES == update);
816     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
817                 "Updating existing records for `%s'!\n", 
818                 crc->name);
819     rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData));
820     memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
821     rd_count_new = rd_count;
822     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
823                 (0 == (crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) 
824                 ? "Updating absolute expiration from %llu to %llu!\n"
825                 : "Updating relative expiration from %llu to %llu!\n", 
826                 rd_new[exist].expiration_time, crc->rd->expiration_time);
827     rd_new[exist] = *(crc->rd);
828   }
829
830   block_expiration = GNUNET_TIME_absolute_max(crc->expire, expire);
831   if (block_expiration.abs_value != expire.abs_value)
832     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
833                 "Updated block expiration time\n");
834
835   memset (&dummy_signature, '\0', sizeof (dummy_signature));
836
837   /* Database operation */
838   GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0));
839   res = GSN_database->put_records(GSN_database->cls,
840                                 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
841                                 block_expiration,
842                                 crc->name,
843                                 rd_count_new, rd_new,
844                                 &dummy_signature);
845   GNUNET_break (GNUNET_OK == res);
846   if (res == GNUNET_OK)
847     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully put record for `%s' in database \n", crc->name);
848   else
849     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to put record for `%s' in database \n", crc->name);
850   res = GNUNET_YES;
851
852 end:
853   GNUNET_free_non_null (rd_new);
854
855   switch (res) {
856     case GNUNET_SYSERR:
857        /* failed to create the record */
858        crc->res = GNUNET_SYSERR;
859       break;
860     case GNUNET_YES:
861       /* database operations OK */
862       if (GNUNET_YES == update)
863       {
864         /* we updated an existing record */
865         crc->res = GNUNET_NO;
866       }
867       else
868       {
869         /* we created a new record */
870         crc->res = GNUNET_YES;
871       }
872       break;
873     case GNUNET_NO:
874         /* identical entry existed, so we did nothing */
875         crc->res = GNUNET_NO;
876       break;
877     default:
878       break;
879   }
880
881   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res);
882
883 }
884
885 static void handle_record_create (void *cls,
886                           struct GNUNET_SERVER_Client * client,
887                           const struct GNUNET_MessageHeader * message)
888 {
889   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
890   struct GNUNET_NAMESTORE_Client *nc;
891   struct GNUNET_NAMESTORE_CryptoContainer *cc;
892   struct CreateRecordContext crc;
893   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
894   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
895   struct RecordCreateResponseMessage rcr_msg;
896   struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
897   struct GNUNET_HashCode long_hash;
898   size_t name_len;
899   size_t msg_size;
900   size_t msg_size_exp;
901   size_t rd_ser_len;
902   size_t key_len;
903   uint32_t rid = 0;
904   char *pkey_tmp;
905   char *name_tmp;
906   char *rd_ser;
907   int rd_count;
908
909   int res = GNUNET_SYSERR;
910   crc.res = GNUNET_SYSERR;
911
912   if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
913   {
914     GNUNET_break_op (0);
915     GNUNET_SERVER_receive_done (client, GNUNET_OK);
916     return;
917   }
918
919   nc = client_lookup(client);
920   if (nc == NULL)
921   {
922     GNUNET_break_op (0);
923     GNUNET_SERVER_receive_done (client, GNUNET_OK);
924     return;
925   }
926
927   struct RecordCreateMessage * rp_msg = (struct RecordCreateMessage *) message;
928   rid = ntohl (rp_msg->gns_header.r_id);
929   name_len = ntohs (rp_msg->name_len);
930   msg_size = ntohs (message->size);
931   rd_count = ntohs (rp_msg->rd_count);
932   rd_ser_len = ntohs (rp_msg->rd_len);
933   key_len = ntohs (rp_msg->pkey_len);
934   msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
935
936   if (msg_size != msg_size_exp)
937   {
938     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
939     GNUNET_break_op (0);
940     GNUNET_SERVER_receive_done (client, GNUNET_OK);
941     return;
942   }
943
944   if ((name_len == 0) || (name_len > 256))
945   {
946     GNUNET_break_op (0);
947     GNUNET_SERVER_receive_done (client, GNUNET_OK);
948     return;
949   }
950
951   pkey_tmp = (char *) &rp_msg[1];
952   name_tmp = &pkey_tmp[key_len];
953   rd_ser = &name_tmp[name_len];
954
955   if (name_tmp[name_len -1] != '\0')
956   {
957     GNUNET_break_op (0);
958     GNUNET_SERVER_receive_done (client, GNUNET_OK);
959     return;
960   }
961
962   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
963
964   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
965   if ((res != GNUNET_OK) || (rd_count != 1))
966   {
967     GNUNET_break_op (0);
968     goto send;
969   }
970   /* Extracting and converting private key */
971   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
972   GNUNET_assert (pkey != NULL);
973   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
974   GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
975   GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
976
977   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
978   {
979     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received new private key for zone `%s'\n",GNUNET_short_h2s(&pubkey_hash));
980
981     cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
982     cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
983     cc->pubkey = GNUNET_malloc(sizeof (pub));
984     memcpy (cc->pubkey, &pub, sizeof(pub));
985     cc->zone = pubkey_hash;
986     GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
987   }
988
989   crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
990   crc.res = GNUNET_SYSERR;
991   crc.pkey = pkey;
992   crc.pubkey = &pub;
993   crc.rd = rd;
994   crc.name = name_tmp;
995
996   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
997
998   /* Get existing records for name */
999   res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
1000   if (res != GNUNET_SYSERR)
1001     res = GNUNET_OK;
1002   GNUNET_CRYPTO_rsa_key_free(pkey);
1003   pkey = NULL;
1004
1005   /* Send response */
1006 send:
1007   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
1008   rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
1009   rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
1010   rcr_msg.gns_header.r_id = htonl (rid);
1011   if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
1012     rcr_msg.op_result = htonl (GNUNET_YES);
1013   else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
1014     rcr_msg.op_result = htonl (GNUNET_NO);
1015   else
1016     rcr_msg.op_result = htonl (GNUNET_SYSERR);
1017   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
1018
1019   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1020 }
1021
1022
1023 struct RemoveRecordContext
1024 {
1025   struct GNUNET_NAMESTORE_RecordData *rd;
1026   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1027   int remove_name;
1028   uint16_t op_res;
1029 };
1030
1031 static void
1032 handle_record_remove_it (void *cls,
1033     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1034     struct GNUNET_TIME_Absolute expire,
1035     const char *name,
1036     unsigned int rd_count,
1037     const struct GNUNET_NAMESTORE_RecordData *rd,
1038     const struct GNUNET_CRYPTO_RsaSignature *signature)
1039 {
1040   struct RemoveRecordContext *rrc = cls;
1041   unsigned int c;
1042   int res;
1043   int found;
1044   unsigned int rd_count_new;
1045
1046   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
1047
1048   if (rd_count == 0)
1049   {
1050     /* Could not find record to remove */
1051     rrc->op_res = 1;
1052     return;
1053   }
1054
1055   /* Find record to remove */
1056   found = GNUNET_SYSERR;
1057   for (c = 0; c < rd_count; c++)
1058   {
1059     /*
1060     if (rd[c].flags != rrc->rd->flags)
1061        continue;*/
1062     if (rd[c].record_type != rrc->rd->record_type)
1063        continue;
1064     /*
1065     if (rd[c].data_size != rrc->rd->data_size)
1066        continue;
1067     GNUNET_break(0);
1068     if (0 != memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size))
1069         continue;
1070     GNUNET_break(0); */
1071     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1072     found = c;
1073     break;
1074   }
1075   if (GNUNET_SYSERR == found)
1076   {
1077     /* Could not find record to remove */
1078     rrc->op_res = 2;
1079     return;
1080   }
1081
1082   if (rd_count-1 == 0)
1083   {
1084     struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1085     GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1086     res = GSN_database->remove_records (GSN_database->cls,
1087                                         &pubkey_hash,
1088                                         name);
1089     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1090                 "No records left for name `%s', removing name\n",
1091                 name, res);
1092     if (GNUNET_OK != res)
1093     {
1094       /* Could put records into database */
1095       rrc->op_res = 4;
1096       return;
1097     }
1098     rrc->op_res = 0;
1099     return;
1100   }
1101
1102   rd_count_new = rd_count -1;
1103   struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
1104
1105   unsigned int c2 = 0;
1106   for (c = 0; c < rd_count; c++)
1107   {
1108     if (c != found)
1109     {
1110       GNUNET_assert (c2 < rd_count_new);
1111       rd_new[c2] = rd[c];
1112       c2++;
1113     }
1114   }
1115
1116   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
1117
1118   /* Create dummy signature */
1119   struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1120   memset (&dummy_signature, '\0', sizeof (dummy_signature));
1121
1122
1123   /* Put records */
1124   res = GSN_database->put_records(GSN_database->cls,
1125                                   zone_key,
1126                                   expire,
1127                                   name,
1128                                   rd_count_new, rd_new,
1129                                   &dummy_signature);
1130   if (GNUNET_OK != res)
1131   {
1132     /* Could put records into database */
1133     rrc->op_res = 4;
1134     return;
1135   }
1136
1137   rrc->op_res = 0;
1138 }
1139
1140
1141 static void
1142 handle_record_remove (void *cls,
1143                       struct GNUNET_SERVER_Client * client,
1144                       const struct GNUNET_MessageHeader * message)
1145 {
1146   struct GNUNET_NAMESTORE_Client *nc;
1147   const struct RecordRemoveMessage * rr_msg;
1148   struct RecordRemoveResponseMessage rrr_msg;
1149   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1150   struct GNUNET_NAMESTORE_CryptoContainer *cc;
1151   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1152   struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1153   struct GNUNET_HashCode long_hash;
1154   const char * pkey_tmp;
1155   const char * name_tmp;
1156   const char * rd_ser;
1157   size_t key_len;
1158   size_t name_len;
1159   size_t rd_ser_len;
1160   size_t msg_size;
1161   size_t msg_size_exp = 0;
1162   uint32_t rd_count;
1163   uint32_t rid;
1164
1165   int res = GNUNET_SYSERR;
1166
1167   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
1168   if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1169   {
1170     GNUNET_break_op (0);
1171     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1172     return;
1173   }
1174
1175   nc = client_lookup(client);
1176   if (nc == NULL)
1177   {
1178     GNUNET_break_op (0);
1179     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1180     return;
1181   }
1182
1183   rr_msg = (const struct RecordRemoveMessage *) message;
1184   rid = ntohl (rr_msg->gns_header.r_id);
1185   name_len = ntohs (rr_msg->name_len);
1186   rd_ser_len = ntohs (rr_msg->rd_len);
1187   rd_count = ntohs (rr_msg->rd_count);
1188   key_len = ntohs (rr_msg->pkey_len);
1189   msg_size = ntohs (message->size);
1190
1191   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1192   {
1193     GNUNET_break_op (0);
1194     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1195     return;
1196   }
1197
1198   if ((name_len >=256) || (name_len == 0))
1199   {
1200     GNUNET_break_op (0);
1201     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1202     return;
1203   }
1204
1205   msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1206   if (msg_size != msg_size_exp)
1207   {
1208     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1209     GNUNET_break_op (0);
1210     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1211     return;
1212   }
1213
1214   pkey_tmp = (const char *) &rr_msg[1];
1215   name_tmp = &pkey_tmp[key_len];
1216   rd_ser = &name_tmp[name_len];
1217
1218
1219   if ((name_len == 0) || (name_len > 256))
1220   {
1221     GNUNET_break_op (0);
1222     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1223     return;
1224   }
1225
1226   if (name_tmp[name_len -1] != '\0')
1227   {
1228     GNUNET_break_op (0);
1229     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1230     return;
1231   }
1232
1233   /* Extracting and converting private key */
1234   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1235   GNUNET_assert (pkey != NULL);
1236   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1237   GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1238   GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1239
1240   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1241   {
1242     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1243                 "Received new private key for zone `%s'\n",
1244                 GNUNET_short_h2s(&pubkey_hash));
1245     cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1246     cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1247     cc->pubkey = GNUNET_malloc(sizeof (pub));
1248     memcpy (cc->pubkey, &pub, sizeof(pub));
1249     cc->zone = pubkey_hash;
1250
1251     GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1252   }
1253
1254
1255   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1256   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1257   if ((res != GNUNET_OK) || (rd_count > 1))
1258   {
1259     GNUNET_break_op (0);
1260     goto send;
1261   }
1262
1263   if (0 == rd_count)
1264   {
1265     /* remove the whole name and all records */
1266     /* Database operation */
1267     res = GSN_database->remove_records (GSN_database->cls,
1268                                          &pubkey_hash,
1269                                          name_tmp);
1270     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing name `%s': %s\n",
1271         name_tmp, (GNUNET_OK == res) ? "OK" : "FAIL");
1272
1273     if (GNUNET_OK != res)
1274       /* Could not remove entry from database */
1275       res = 4;
1276     else
1277       res = 0;
1278   }
1279   else
1280   {
1281     /* remove a single record */
1282     struct RemoveRecordContext rrc;
1283     rrc.rd = rd;
1284     rrc.pkey = pkey;
1285
1286     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1287
1288     /* Database operation */
1289     res = GSN_database->iterate_records (GSN_database->cls,
1290                                          &pubkey_hash,
1291                                          name_tmp,
1292                                          0,
1293                                          handle_record_remove_it, &rrc);
1294
1295     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
1296         name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
1297     res = rrc.op_res;
1298   }
1299   /* Send response */
1300 send:
1301   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
1302   rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1303   rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1304   rrr_msg.gns_header.r_id = htonl (rid);
1305   rrr_msg.op_result = htonl (res);
1306   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
1307
1308   GNUNET_CRYPTO_rsa_key_free (pkey);
1309
1310   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1311 }
1312
1313
1314 struct ZoneToNameCtx
1315 {
1316   struct GNUNET_NAMESTORE_Client *nc;
1317   uint32_t rid;
1318 };
1319
1320 static void
1321 handle_zone_to_name_it (void *cls,
1322     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1323     struct GNUNET_TIME_Absolute expire,
1324     const char *name,
1325     unsigned int rd_count,
1326     const struct GNUNET_NAMESTORE_RecordData *rd,
1327     const struct GNUNET_CRYPTO_RsaSignature *signature)
1328 {
1329   struct ZoneToNameCtx * ztn_ctx = cls;
1330   struct ZoneToNameResponseMessage *ztnr_msg;
1331   int16_t res = GNUNET_SYSERR;
1332   uint16_t name_len = 0;
1333   uint16_t rd_ser_len = 0 ;
1334   int32_t contains_sig = 0;
1335   size_t msg_size = 0;
1336
1337   char *rd_ser = NULL;
1338   char *name_tmp;
1339   char *rd_tmp;
1340   char *sig_tmp;
1341
1342   if ((zone_key != NULL) && (name != NULL))
1343   {
1344     /* found result */
1345     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found results: name is `%s', has %u records\n", name, rd_count);
1346     res = GNUNET_YES;
1347     name_len = strlen (name) +1;
1348   }
1349   else
1350   {
1351     /* no result found */
1352     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no results\n");
1353     res = GNUNET_NO;
1354     name_len = 0;
1355   }
1356
1357   if (rd_count > 0)
1358   {
1359     rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1360     rd_ser = GNUNET_malloc (rd_ser_len);
1361     GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1362   }
1363   else
1364     rd_ser_len = 0;
1365
1366   if (signature != NULL)
1367     contains_sig = GNUNET_YES;
1368   else
1369     contains_sig = GNUNET_NO;
1370
1371
1372
1373   msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
1374   ztnr_msg = GNUNET_malloc (msg_size);
1375
1376   name_tmp = (char *) &ztnr_msg[1];
1377   rd_tmp = &name_tmp[name_len];
1378   sig_tmp = &rd_tmp[rd_ser_len];
1379
1380   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_TO_NAME_RESPONSE");
1381   ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1382   ztnr_msg->gns_header.header.size = htons (msg_size);
1383   ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1384   ztnr_msg->res = htons (res);
1385   ztnr_msg->rd_len = htons (rd_ser_len);
1386   ztnr_msg->rd_count = htons (rd_count);
1387   ztnr_msg->name_len = htons (name_len);
1388   ztnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
1389   if (zone_key != NULL)
1390     ztnr_msg->zone_key = *zone_key;
1391   else
1392     memset (&ztnr_msg->zone_key, '\0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1393
1394   if ((name_len > 0) && (name != NULL))
1395     memcpy (name_tmp, name, name_len);
1396
1397   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name is `%s', has %u records, rd ser len %u msg_size %u\n", name, rd_count, rd_ser_len, msg_size);
1398   if ((rd_ser_len > 0) && (rd_ser != NULL))
1399     memcpy (rd_tmp, rd_ser, rd_ser_len);
1400   if ((GNUNET_YES == contains_sig) && (signature != NULL))
1401     memcpy (sig_tmp, signature, contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature));
1402
1403   GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, (const struct GNUNET_MessageHeader *) ztnr_msg, GNUNET_NO);
1404   GNUNET_free (ztnr_msg);
1405   GNUNET_free_non_null (rd_ser);
1406 }
1407
1408
1409 static void handle_zone_to_name (void *cls,
1410                           struct GNUNET_SERVER_Client * client,
1411                           const struct GNUNET_MessageHeader * message)
1412 {
1413   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME");
1414   struct GNUNET_NAMESTORE_Client *nc;
1415   struct ZoneToNameCtx ztn_ctx;
1416   size_t msg_size = 0;
1417   uint32_t rid = 0;
1418
1419   if (ntohs (message->size) != sizeof (struct ZoneToNameMessage))
1420   {
1421     GNUNET_break_op (0);
1422     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1423     return;
1424   }
1425
1426   nc = client_lookup(client);
1427   if (nc == NULL)
1428   {
1429     GNUNET_break_op (0);
1430     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1431     return;
1432   }
1433
1434   struct ZoneToNameMessage *ztn_msg = (struct ZoneToNameMessage *) message;
1435
1436   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1437   {
1438     GNUNET_break_op (0);
1439     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1440     return;
1441   }
1442
1443   rid = ntohl (ztn_msg->gns_header.r_id);
1444
1445   ztn_ctx.rid = rid;
1446   ztn_ctx.nc = nc;
1447
1448   struct GNUNET_CRYPTO_ShortHashAsciiEncoded z_tmp;
1449   GNUNET_CRYPTO_short_hash_to_enc(&ztn_msg->zone, &z_tmp);
1450   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up name for zone `%s' in zone `%s'\n",
1451       (char *) &z_tmp,
1452       GNUNET_short_h2s (&ztn_msg->value_zone));
1453
1454   GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx);
1455
1456   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1457 }
1458
1459
1460 /**
1461  * Copy record, data has to be free separetely
1462  */
1463 void
1464 copy_record (const struct GNUNET_NAMESTORE_RecordData *src, struct GNUNET_NAMESTORE_RecordData *dest)
1465 {
1466
1467   memcpy (dest, src, sizeof (struct GNUNET_NAMESTORE_RecordData));
1468   dest->data = GNUNET_malloc (src->data_size);
1469   memcpy ((void *) dest->data, src->data, src->data_size);
1470 }
1471
1472 struct ZoneIterationProcResult
1473 {
1474   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1475
1476   int res_iteration_finished;
1477   int records_included;
1478   int has_signature;
1479
1480   char *name;
1481   struct GNUNET_CRYPTO_ShortHashCode zone_hash;
1482   struct GNUNET_NAMESTORE_RecordData *rd;
1483   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
1484   struct GNUNET_CRYPTO_RsaSignature signature;
1485   struct GNUNET_TIME_Absolute expire;
1486 };
1487
1488
1489 void zone_iteraterate_proc (void *cls,
1490                          const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1491                          struct GNUNET_TIME_Absolute expire,
1492                          const char *name,
1493                          unsigned int rd_count,
1494                          const struct GNUNET_NAMESTORE_RecordData *rd,
1495                          const struct GNUNET_CRYPTO_RsaSignature *signature)
1496 {
1497   struct ZoneIterationProcResult *proc = cls;
1498   struct GNUNET_NAMESTORE_RecordData *rd_filtered;
1499   struct GNUNET_CRYPTO_RsaSignature * new_signature;
1500   struct GNUNET_NAMESTORE_CryptoContainer *cc;
1501   struct GNUNET_CRYPTO_ShortHashCode hash;
1502   struct GNUNET_HashCode long_hash;
1503   struct GNUNET_TIME_Absolute e;
1504   unsigned int rd_count_filtered  = 0;
1505   int include;
1506   int c;
1507
1508   proc->res_iteration_finished = GNUNET_NO;
1509   proc->records_included = 0;
1510
1511   if ((zone_key == NULL) && (name == NULL))
1512   {
1513     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1514     proc->res_iteration_finished = GNUNET_YES;
1515     proc->rd = NULL;
1516     proc->name = NULL;
1517   }
1518   else if ((zone_key != NULL) && (name != NULL)) /* just a safety check */
1519   {
1520     rd_filtered = GNUNET_malloc (rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1521     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received result for zone iteration: `%s'\n", name);
1522     for (c = 0; c < rd_count; c++)
1523     {
1524       include = GNUNET_YES;
1525       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must have 0x%x \n",
1526           c, rd[c].flags, proc->zi->must_have_flags);
1527       /* Checking must have flags */
1528       if ((rd[c].flags & proc->zi->must_have_flags) == proc->zi->must_have_flags)
1529       {
1530         /* Include */
1531         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1532       }
1533       else
1534       {
1535         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1536         include = GNUNET_NO;
1537       }
1538
1539       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must not have 0x%x\n",
1540           c, rd[c].flags, proc->zi->must_not_have_flags);
1541       if ((rd[c].flags & proc->zi->must_not_have_flags) != 0)
1542       {
1543         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1544         include = GNUNET_NO;
1545       }
1546       else
1547       {
1548         /* Include */
1549         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1550       }
1551       if (GNUNET_YES == include)
1552       {
1553         copy_record (&rd[c], &rd_filtered[rd_count_filtered]);
1554         rd_count_filtered++;
1555       }
1556
1557     }
1558     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Included %i of %i records \n", rd_count_filtered, rd_count);
1559
1560     proc->records_included = rd_count_filtered;
1561     if (0 == rd_count_filtered)
1562     {
1563       GNUNET_free (rd_filtered);
1564       rd_filtered = NULL;
1565     }
1566     proc->rd = rd_filtered;
1567     proc->name = GNUNET_strdup(name);
1568     memcpy (&proc->zone_key, zone_key, sizeof (proc->zone_key));
1569
1570     /* Signature */
1571     proc->has_signature = GNUNET_NO;
1572     GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &hash);
1573     GNUNET_CRYPTO_short_hash_double(&hash, &long_hash);
1574     proc->zone_hash = hash;
1575
1576     if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1577     {
1578       cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
1579       e = get_block_expiration_time(rd_count_filtered, rd_filtered);
1580       proc->expire = e;
1581       new_signature = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd_filtered, rd_count_filtered);
1582       GNUNET_assert (signature != NULL);
1583       proc->signature = (*new_signature);
1584       GNUNET_free (new_signature);
1585       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1586           name, GNUNET_short_h2s(&hash), rd_count_filtered, e.abs_value);
1587       proc->has_signature = GNUNET_YES;
1588     }
1589     else if (rd_count_filtered == rd_count)
1590     {
1591       proc->expire = expire;
1592       if (NULL != signature)
1593       {
1594         proc->signature = (*signature);
1595         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1596             name, GNUNET_short_h2s(&hash), rd_count_filtered, expire.abs_value);
1597         proc->has_signature = GNUNET_YES;
1598       }
1599       else
1600       {
1601         memset (&proc->signature, '\0', sizeof (proc->signature));
1602         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No signature provided for `%s'\n", name);
1603       }
1604     }
1605   }
1606   else
1607   {
1608     GNUNET_break (0);
1609     return;
1610   }
1611
1612 }
1613
1614 void find_next_zone_iteration_result (struct ZoneIterationProcResult *proc)
1615 {
1616
1617   struct GNUNET_CRYPTO_ShortHashCode *zone;
1618
1619   if (GNUNET_YES == proc->zi->has_zone)
1620     zone = &proc->zi->zone;
1621   else
1622     zone = NULL;
1623
1624   do
1625   {
1626     GSN_database->iterate_records (GSN_database->cls, zone , NULL, proc->zi->offset, &zone_iteraterate_proc, proc);
1627     proc->zi->offset++;
1628   }
1629   while ((proc->records_included == 0) && (GNUNET_NO == proc->res_iteration_finished));
1630 }
1631
1632
1633 void send_zone_iteration_result (struct ZoneIterationProcResult *proc)
1634 {
1635   struct GNUNET_NAMESTORE_ZoneIteration *zi = proc->zi;
1636
1637   if (GNUNET_YES == proc->res_iteration_finished)
1638   {
1639     struct ZoneIterationResponseMessage zir_msg;
1640     if (zi->has_zone == GNUNET_YES)
1641       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for zone `%s'\n", GNUNET_short_h2s(&zi->zone));
1642     else
1643       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for all zones\n");
1644
1645     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending empty `%s' message\n", "ZONE_ITERATION_RESPONSE");
1646     zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1647     zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1648     zir_msg.gns_header.r_id = htonl(zi->request_id);
1649     zir_msg.expire = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_ZERO_ABS);
1650     zir_msg.name_len = htons (0);
1651     zir_msg.reserved = htons (0);
1652     zir_msg.rd_count = htons (0);
1653     zir_msg.rd_len = htons (0);
1654     memset (&zir_msg.public_key, '\0', sizeof (zir_msg.public_key));
1655     memset (&zir_msg.signature, '\0', sizeof (zir_msg.signature));
1656     GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO);
1657
1658     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing zone iterator\n");
1659     GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi);
1660     GNUNET_free (zi);
1661     return;
1662   }
1663   else
1664   {
1665     GNUNET_assert (proc->records_included > 0);
1666
1667     struct ZoneIterationResponseMessage *zir_msg;
1668     if (zi->has_zone == GNUNET_YES)
1669       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over zone `%s'\n",
1670           proc->name, GNUNET_short_h2s(&zi->zone));
1671     if (zi->has_zone == GNUNET_NO)
1672       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over all zones\n",
1673           proc->name);
1674
1675     size_t name_len;
1676     size_t rd_ser_len;
1677     size_t msg_size;
1678     char *name_tmp;
1679     char *rd_tmp;
1680     name_len = strlen (proc->name) +1;
1681
1682     rd_ser_len = GNUNET_NAMESTORE_records_get_size(proc->records_included, proc->rd);
1683     char rd_ser[rd_ser_len];
1684     GNUNET_NAMESTORE_records_serialize(proc->records_included, proc->rd, rd_ser_len, rd_ser);
1685     msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
1686     zir_msg = GNUNET_malloc(msg_size);
1687
1688     name_tmp = (char *) &zir_msg[1];
1689     rd_tmp = &name_tmp[name_len];
1690
1691     zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1692     zir_msg->gns_header.header.size = htons (msg_size);
1693     zir_msg->gns_header.r_id = htonl(zi->request_id);
1694     zir_msg->expire = GNUNET_TIME_absolute_hton(proc->expire);
1695     zir_msg->reserved = htons (0);
1696     zir_msg->name_len = htons (name_len);
1697     zir_msg->rd_count = htons (proc->records_included);
1698     zir_msg->rd_len = htons (rd_ser_len);
1699     zir_msg->signature = proc->signature;
1700     zir_msg->public_key = proc->zone_key;
1701     memcpy (name_tmp, proc->name, name_len);
1702     memcpy (rd_tmp, rd_ser, rd_ser_len);
1703
1704     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with size %u\n", "ZONE_ITERATION_RESPONSE", msg_size);
1705     GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) zir_msg, GNUNET_NO);
1706     GNUNET_free (zir_msg);
1707   }
1708 }
1709
1710 void clean_up_zone_iteration_result (struct ZoneIterationProcResult *proc)
1711 {
1712   int c;
1713   GNUNET_free_non_null (proc->name);
1714   for (c = 0; c < proc->records_included; c++)
1715   {
1716     GNUNET_free ((void *) proc->rd[c].data);
1717   }
1718   GNUNET_free_non_null (proc->rd);
1719   proc->name = NULL;
1720   proc->rd = NULL;
1721 }
1722
1723 static void handle_iteration_start (void *cls,
1724                           struct GNUNET_SERVER_Client * client,
1725                           const struct GNUNET_MessageHeader * message)
1726 {
1727   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
1728
1729   struct ZoneIterationStartMessage * zis_msg = (struct ZoneIterationStartMessage *) message;
1730   struct GNUNET_NAMESTORE_Client *nc;
1731   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1732
1733   nc = client_lookup(client);
1734   if (nc == NULL)
1735   {
1736     GNUNET_break_op (0);
1737     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1738     return;
1739   }
1740
1741   zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
1742   zi->request_id = ntohl (zis_msg->gns_header.r_id);
1743   zi->offset = 0;
1744   zi->client = nc;
1745   zi->must_have_flags = ntohs (zis_msg->must_have_flags);
1746   zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags);
1747
1748   struct GNUNET_CRYPTO_ShortHashCode dummy;
1749   memset (&dummy, '\0', sizeof (dummy));
1750   if (0 == memcmp (&dummy, &zis_msg->zone, sizeof (dummy)))
1751   {
1752     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
1753     zi->zone = zis_msg->zone;
1754     zi->has_zone = GNUNET_NO;
1755   }
1756   else
1757   {
1758     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over zone  `%s'\n", GNUNET_short_h2s (&zis_msg->zone));
1759     zi->zone = zis_msg->zone;
1760     zi->has_zone = GNUNET_YES;
1761   }
1762
1763   GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1764
1765   struct ZoneIterationProcResult proc;
1766   proc.zi = zi;
1767
1768   find_next_zone_iteration_result (&proc);
1769   if (GNUNET_YES == proc.res_iteration_finished)
1770   {
1771     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration done\n");
1772   }
1773   else if (proc.records_included != 0)
1774   {
1775     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration return %u records\n", proc.records_included);
1776   }
1777   send_zone_iteration_result (&proc);
1778   clean_up_zone_iteration_result (&proc);
1779
1780   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1781 }
1782
1783 static void handle_iteration_stop (void *cls,
1784                           struct GNUNET_SERVER_Client * client,
1785                           const struct GNUNET_MessageHeader * message)
1786 {
1787   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP");
1788
1789   struct GNUNET_NAMESTORE_Client *nc;
1790   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1791   struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1792   uint32_t rid;
1793
1794   nc = client_lookup(client);
1795   if (nc == NULL)
1796   {
1797     GNUNET_break_op (0);
1798     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1799     return;
1800   }
1801
1802   rid = ntohl (zis_msg->gns_header.r_id);
1803   for (zi = nc->op_head; zi != NULL; zi = zi->next)
1804   {
1805     if (zi->request_id == rid)
1806       break;
1807   }
1808   if (zi == NULL)
1809   {
1810     GNUNET_break_op (0);
1811     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1812     return;
1813   }
1814
1815   GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi);
1816   if (GNUNET_YES == zi->has_zone)
1817     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_short_h2s (&zi->zone));
1818   else
1819     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration all zones\n");
1820   GNUNET_free (zi);
1821
1822   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1823 }
1824
1825 static void handle_iteration_next (void *cls,
1826                           struct GNUNET_SERVER_Client * client,
1827                           const struct GNUNET_MessageHeader * message)
1828 {
1829   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
1830
1831   struct GNUNET_NAMESTORE_Client *nc;
1832   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1833   struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1834   uint32_t rid;
1835
1836   nc = client_lookup(client);
1837   if (nc == NULL)
1838   {
1839     GNUNET_break_op (0);
1840     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1841     return;
1842   }
1843
1844   rid = ntohl (zis_msg->gns_header.r_id);
1845   for (zi = nc->op_head; zi != NULL; zi = zi->next)
1846   {
1847     if (zi->request_id == rid)
1848       break;
1849   }
1850   if (zi == NULL)
1851   {
1852     GNUNET_break_op (0);
1853     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1854     return;
1855   }
1856
1857   struct ZoneIterationProcResult proc;
1858   proc.zi = zi;
1859
1860   find_next_zone_iteration_result (&proc);
1861   if (GNUNET_YES == proc.res_iteration_finished)
1862   {
1863     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration done\n");
1864   }
1865   else if (proc.records_included != 0)
1866   {
1867     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration return %u records\n", proc.records_included);
1868   }
1869   send_zone_iteration_result (&proc);
1870   clean_up_zone_iteration_result (&proc);
1871
1872   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1873 }
1874
1875 int zonekey_file_it (void *cls, const char *filename)
1876 {
1877   struct GNUNET_HashCode long_hash;
1878   int *counter = cls;
1879    if ((filename != NULL) && (NULL != strstr(filename, ".zkey")))
1880    {
1881      struct GNUNET_CRYPTO_RsaPrivateKey * privkey;
1882      struct GNUNET_NAMESTORE_CryptoContainer *c;
1883      privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename);
1884      if (privkey == NULL)
1885        return GNUNET_OK;
1886
1887      c = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1888      c->pubkey = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1889      c->privkey = privkey;
1890      GNUNET_CRYPTO_rsa_key_get_public(privkey, c->pubkey);
1891      GNUNET_CRYPTO_short_hash(c->pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &c->zone);
1892
1893      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found zonefile for zone `%s'\n", GNUNET_short_h2s (&c->zone));
1894      GNUNET_CRYPTO_short_hash_double (&c->zone, &long_hash);
1895      GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1896      (*counter) ++;
1897    }
1898    return GNUNET_OK;
1899 }
1900
1901
1902 /**
1903  * Process template requests.
1904  *
1905  * @param cls closure
1906  * @param server the initialized server
1907  * @param cfg configuration to use
1908  */
1909 static void
1910 run (void *cls, struct GNUNET_SERVER_Handle *server,
1911      const struct GNUNET_CONFIGURATION_Handle *cfg)
1912 {
1913   char * database;
1914   int counter = 0;
1915   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
1916
1917   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1918     {&handle_start, NULL,
1919      GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
1920     {&handle_lookup_name, NULL,
1921      GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
1922     {&handle_record_put, NULL,
1923     GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
1924     {&handle_record_create, NULL,
1925      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
1926     {&handle_record_remove, NULL,
1927      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
1928     {&handle_zone_to_name, NULL,
1929       GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, 0},
1930     {&handle_iteration_start, NULL,
1931      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)},
1932     {&handle_iteration_next, NULL,
1933      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0},
1934      {&handle_iteration_stop, NULL,
1935       GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, 0},
1936     {NULL, NULL, 0, 0}
1937   };
1938
1939   GSN_cfg = cfg;
1940
1941   /* Load private keys from disk */
1942   if (GNUNET_OK !=
1943       GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore", "zonefile_directory",
1944                                              &zonefile_directory))
1945   {
1946     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No directory to load zonefiles specified in configuration\n"));
1947     GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
1948     return;
1949   }
1950
1951   if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
1952   {
1953     if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
1954     {
1955       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Creating directory `%s' for zone files failed!\n"), zonefile_directory);
1956       GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
1957       return;
1958     }
1959     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created directory `%s' for zone files\n", zonefile_directory);
1960   }
1961
1962   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scanning directory `%s' for zone files\n", zonefile_directory);
1963   zonekeys = GNUNET_CONTAINER_multihashmap_create (10);
1964   GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
1965   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u zone files\n", counter);
1966
1967   /* Loading database plugin */
1968   if (GNUNET_OK !=
1969       GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
1970                                              &database))
1971     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
1972
1973   GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
1974   GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
1975   GNUNET_free (database);
1976   if (GSN_database == NULL)
1977   {
1978     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n",
1979         db_lib_name);
1980     GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
1981     return;
1982   }
1983
1984   /* Configuring server handles */
1985   GNUNET_SERVER_add_handlers (server, handlers);
1986   snc = GNUNET_SERVER_notification_context_create (server, 16);
1987   GNUNET_SERVER_disconnect_notify (server,
1988                                    &client_disconnect_notification,
1989                                    NULL);
1990
1991   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1992                                 NULL);
1993
1994 }
1995
1996
1997 /**
1998  * The main function for the template service.
1999  *
2000  * @param argc number of arguments from the command line
2001  * @param argv command line arguments
2002  * @return 0 ok, 1 on error
2003  */
2004 int
2005 main (int argc, char *const *argv)
2006 {
2007   return (GNUNET_OK ==
2008           GNUNET_SERVICE_run (argc, argv, "namestore",
2009                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
2010 }
2011
2012 /* end of gnunet-service-namestore.c */
2013