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