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