aboutsummaryrefslogtreecommitdiff
path: root/src/namestore
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-03-05 13:09:23 +0000
committerChristian Grothoff <christian@grothoff.org>2012-03-05 13:09:23 +0000
commit03b9677115d2879d968b2ed49d2c88fdce6bcab9 (patch)
treea0606192d5b7062c5e317c060100e9b35403f16c /src/namestore
parentebfd8a07a7380540ce0216861ffe23e5b303be19 (diff)
downloadgnunet-03b9677115d2879d968b2ed49d2c88fdce6bcab9.tar.gz
gnunet-03b9677115d2879d968b2ed49d2c88fdce6bcab9.zip
-renaming gnunet-gns to gnunet-namestore
Diffstat (limited to 'src/namestore')
-rw-r--r--src/namestore/Makefile.am16
-rw-r--r--src/namestore/gnunet-namestore.c501
2 files changed, 516 insertions, 1 deletions
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
index f937c502f..21c8166d0 100644
--- a/src/namestore/Makefile.am
+++ b/src/namestore/Makefile.am
@@ -55,7 +55,21 @@ libgnunetnamestore_la_LDFLAGS = \
55 -version-info 0:0:0 55 -version-info 0:0:0
56 56
57bin_PROGRAMS = \ 57bin_PROGRAMS = \
58 gnunet-service-namestore 58 gnunet-service-namestore \
59 gnunet-namestore
60
61
62gnunet_namestore_SOURCES = \
63 gnunet-namestore.c
64gnunet_namestore_LDADD = \
65 $(top_builddir)/src/util/libgnunetutil.la \
66 libgnunetnamestore.la \
67 $(GN_LIBINTL)
68gnunet_namestore_DEPENDENCIES = \
69 $(top_builddir)/src/util/libgnunetutil.la \
70 libgnunetnamestore.la
71
72
59 73
60gnunet_service_namestore_SOURCES = \ 74gnunet_service_namestore_SOURCES = \
61 gnunet-service-namestore.c 75 gnunet-service-namestore.c
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c
new file mode 100644
index 000000000..a6b45586b
--- /dev/null
+++ b/src/namestore/gnunet-namestore.c
@@ -0,0 +1,501 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file gnunet-gns.c
22 * @brief command line tool to manipulate the local zone
23 * @author Christian Grothoff
24 *
25 * TODO:
26 * - printing records
27 * - allow users to set record options (not just 'RF_AUTHORITY')
28 * - test
29 * - parsing SOA, PTR and MX value specifications (and define format!)
30 * - add options to list/lookup individual records
31 * - add option to shorten name (lookup PKEY, then lookup name by zone,
32 * then possibly lookup PSEU for the zone and update our zone)
33 */
34#include "platform.h"
35#include <gnunet_util_lib.h>
36#include <gnunet_dnsparser_lib.h>
37#include <gnunet_namestore_service.h>
38
39/**
40 * Handle to the namestore.
41 */
42static struct GNUNET_NAMESTORE_Handle *ns;
43
44/**
45 * Hash of the public key of our zone.
46 */
47static GNUNET_HashCode zone;
48
49/**
50 * Private key for the our zone.
51 */
52static struct GNUNET_CRYPTO_RsaPrivateKey *zone_pkey;
53
54/**
55 * Keyfile to manipulate.
56 */
57static char *keyfile;
58
59/**
60 * Desired action is to add a record.
61 */
62static int add;
63
64/**
65 * Queue entry for the 'add' operation.
66 */
67static struct GNUNET_NAMESTORE_QueueEntry *add_qe;
68
69/**
70 * Desired action is to list records.
71 */
72static int list;
73
74/**
75 * List iterator for the 'list' operation.
76 */
77static struct GNUNET_NAMESTORE_ZoneIterator *list_it;
78
79/**
80 * Desired action is to remove a record.
81 */
82static int del;
83
84/**
85 * Queue entry for the 'del' operation.
86 */
87static struct GNUNET_NAMESTORE_QueueEntry *del_qe;
88
89/**
90 * Name of the records to add/list/remove.
91 */
92static char *name;
93
94/**
95 * Value of the record to add/remove.
96 */
97static char *value;
98
99/**
100 * Type of the record to add/remove, NULL to remove all.
101 */
102static char *typestring;
103
104/**
105 * Desired expiration time.
106 */
107static char *expirationstring;
108
109
110/**
111 * Task run on shutdown. Cleans up everything.
112 *
113 * @param cls unused
114 * @param tc scheduler context
115 */
116static void
117do_shutdown (void *cls,
118 const struct GNUNET_SCHEDULER_TaskContext *tc)
119{
120 if (NULL != ns)
121 {
122 GNUNET_NAMESTORE_disconnect (ns, GNUNET_NO);
123 ns = NULL;
124 }
125 if (NULL != zone_pkey)
126 {
127 GNUNET_CRYPTO_rsa_key_free (zone_pkey);
128 zone_pkey = NULL;
129 }
130}
131
132
133/**
134 * Continuation called to notify client about result of the
135 * operation.
136 *
137 * @param cls closure, unused
138 * @param success GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
139 * GNUNET_NO if content was already there
140 * GNUNET_YES (or other positive value) on success
141 * @param emsg NULL on success, otherwise an error message
142 */
143static void
144add_continuation (void *cls,
145 int32_t success,
146 const char *emsg)
147{
148 add_qe = NULL;
149 if (success != GNUNET_YES)
150 fprintf (stderr,
151 _("Adding record failed: %s\n"),
152 (success == GNUNET_NO) ? "record exists" : emsg);
153 if ( (NULL == del_qe) &&
154 (NULL == list_it) )
155 GNUNET_SCHEDULER_shutdown ();
156}
157
158
159/**
160 * Continuation called to notify client about result of the
161 * operation.
162 *
163 * @param cls closure, unused
164 * @param success GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
165 * GNUNET_NO if content was already there
166 * GNUNET_YES (or other positive value) on success
167 * @param emsg NULL on success, otherwise an error message
168 */
169static void
170del_continuation (void *cls,
171 int32_t success,
172 const char *emsg)
173{
174 del_qe = NULL;
175 if (success != GNUNET_YES)
176 fprintf (stderr,
177 _("Deleting record failed: %s\n"),
178 emsg);
179 if ( (NULL == add_qe) &&
180 (NULL == list_it) )
181 GNUNET_SCHEDULER_shutdown ();
182}
183
184
185/**
186 * Process a record that was stored in the namestore.
187 *
188 * @param cls closure
189 * @param zone_key public key of the zone
190 * @param expire when does the corresponding block in the DHT expire (until
191 * when should we never do a DHT lookup for the same name again)?;
192 * GNUNET_TIME_UNIT_ZERO_ABS if there are no records of any type in the namestore,
193 * or the expiration time of the block in the namestore (even if there are zero
194 * records matching the desired record type)
195 * @param name name that is being mapped (at most 255 characters long)
196 * @param rd_count number of entries in 'rd' array
197 * @param rd array of records with data to store
198 * @param signature signature of the record block, NULL if signature is unavailable (i.e.
199 * because the user queried for a particular record type only)
200 */
201static void
202display_record (void *cls,
203 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
204 struct GNUNET_TIME_Absolute expire,
205 const char *name,
206 unsigned int rd_len,
207 const struct GNUNET_NAMESTORE_RecordData *rd,
208 const struct GNUNET_CRYPTO_RsaSignature *signature)
209{
210 if (NULL == name)
211 {
212 list_it = NULL;
213 if ( (NULL == del_qe) &&
214 (NULL == add_qe) )
215 GNUNET_SCHEDULER_shutdown ();
216 return;
217 }
218 // FIXME: display record!
219 GNUNET_NAMESTORE_zone_iterator_next (list_it);
220}
221
222
223/**
224 * Main function that will be run.
225 *
226 * @param cls closure
227 * @param args remaining command-line arguments
228 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
229 * @param cfg configuration
230 */
231static void
232run (void *cls, char *const *args, const char *cfgfile,
233 const struct GNUNET_CONFIGURATION_Handle *cfg)
234{
235 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
236 uint32_t type;
237 const void *data;
238 size_t data_size;
239 struct in_addr value_a;
240 struct in6_addr value_aaaa;
241 struct GNUNET_TIME_Relative etime;
242 struct GNUNET_NAMESTORE_RecordData rd;
243
244 if (NULL == keyfile)
245 {
246 fprintf (stderr,
247 _("Option `%s' not given, but I need a zone key file!\n"),
248 "z");
249 return;
250 }
251 zone_pkey = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
252 GNUNET_free (keyfile);
253 keyfile = NULL;
254 if (! (add|del|list))
255 {
256 /* nothing more to be done */
257 GNUNET_CRYPTO_rsa_key_free (zone_pkey);
258 zone_pkey = NULL;
259 return;
260 }
261 if (NULL == zone_pkey)
262 {
263 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
264 _("Failed to read or create private zone key\n"));
265 return;
266 }
267 GNUNET_CRYPTO_rsa_key_get_public (zone_pkey,
268 &pub);
269 GNUNET_CRYPTO_hash (&pub, sizeof (pub), &zone);
270
271 ns = GNUNET_NAMESTORE_connect (cfg);
272 if (NULL == ns)
273 {
274 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
275 _("Failed to connect to namestore\n"));
276 return;
277 }
278 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
279 &do_shutdown, NULL);
280 if (NULL == typestring)
281 type = 0;
282 else
283 type = GNUNET_NAMESTORE_typename_to_number (typestring);
284 if (UINT32_MAX == type)
285 {
286 fprintf (stderr, _("Unsupported type `%s'\n"), typestring);
287 GNUNET_SCHEDULER_shutdown ();
288 return;
289 } else if (add | del)
290 {
291 fprintf (stderr,
292 _("Missing option `%s' for operation `%s'\n"),
293 "-t", _("add/del"));
294 GNUNET_SCHEDULER_shutdown ();
295 return;
296 }
297 if (NULL != value)
298 {
299 switch (type)
300 {
301 case 0:
302 fprintf (stderr, _("Need a record type to interpret value `%s'\n"), value);
303 GNUNET_SCHEDULER_shutdown ();
304 break;
305 case GNUNET_DNSPARSER_TYPE_A:
306 if (1 != inet_pton (AF_INET, value, &value_a))
307 {
308 fprintf (stderr, _("Value `%s' invalid for record type `%s'\n"),
309 value,
310 typestring);
311 GNUNET_SCHEDULER_shutdown ();
312 return;
313 }
314 data = &value_a;
315 data_size = sizeof (value_a);
316 break;
317 case GNUNET_DNSPARSER_TYPE_NS:
318 data = value;
319 data_size = strlen (value);
320 break;
321 case GNUNET_DNSPARSER_TYPE_CNAME:
322 data = value;
323 data_size = strlen (value);
324 break;
325 case GNUNET_DNSPARSER_TYPE_SOA:
326 // FIXME
327 fprintf (stderr, _("Record type `%s' not implemented yet\n"), typestring);
328 GNUNET_SCHEDULER_shutdown ();
329 return;
330 case GNUNET_DNSPARSER_TYPE_PTR:
331 // FIXME
332 fprintf (stderr, _("Record type `%s' not implemented yet\n"), typestring);
333 GNUNET_SCHEDULER_shutdown ();
334 return;
335 case GNUNET_DNSPARSER_TYPE_MX:
336 // FIXME
337 fprintf (stderr, _("Record type `%s' not implemented yet\n"), typestring);
338 GNUNET_SCHEDULER_shutdown ();
339 return;
340 case GNUNET_DNSPARSER_TYPE_TXT:
341 data = value;
342 data_size = strlen (value);
343 break;
344 case GNUNET_DNSPARSER_TYPE_AAAA:
345 if (1 != inet_pton (AF_INET6, value, &value_aaaa))
346 {
347 fprintf (stderr, _("Value `%s' invalid for record type `%s'\n"),
348 value,
349 typestring);
350 GNUNET_SCHEDULER_shutdown ();
351 return;
352 }
353 data = &value_aaaa;
354 data_size = sizeof (value_aaaa);
355 break;
356 case GNUNET_GNS_TYPE_PKEY:
357 fprintf (stderr, _("Record type `%s' not implemented yet\n"), typestring);
358 GNUNET_SCHEDULER_shutdown ();
359 return;
360 case GNUNET_GNS_TYPE_PSEU:
361 data = value;
362 data_size = strlen (value);
363 break;
364 default:
365 GNUNET_assert (0);
366 }
367 } else if (add | del)
368 {
369 fprintf (stderr,
370 _("Missing option `%s' for operation `%s'\n"),
371 "-V", _("add/del"));
372 GNUNET_SCHEDULER_shutdown ();
373 return;
374 }
375 if (NULL != expirationstring)
376 {
377 if (GNUNET_OK !=
378 GNUNET_STRINGS_fancy_time_to_relative (expirationstring,
379 &etime))
380 {
381 fprintf (stderr,
382 _("Invalid time format `%s'\n"),
383 expirationstring);
384 GNUNET_SCHEDULER_shutdown ();
385 return;
386 }
387 } else if (add | del)
388 {
389 fprintf (stderr,
390 _("Missing option `%s' for operation `%s'\n"),
391 "-e", _("add/del"));
392 GNUNET_SCHEDULER_shutdown ();
393 return;
394 }
395 if (add)
396 {
397 if (NULL == name)
398 {
399 fprintf (stderr,
400 _("Missing option `%s' for operation `%s'\n"),
401 "-n", _("add"));
402 GNUNET_SCHEDULER_shutdown ();
403 return;
404 }
405 rd.data = data;
406 rd.data_size = data_size;
407 rd.record_type = type;
408 rd.expiration = GNUNET_TIME_relative_to_absolute (etime);
409 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; // FIXME: not always...
410 add_qe = GNUNET_NAMESTORE_record_create (ns,
411 zone_pkey,
412 name,
413 &rd,
414 &add_continuation,
415 NULL);
416 }
417 if (del)
418 {
419 if (NULL == name)
420 {
421 fprintf (stderr,
422 _("Missing option `%s' for operation `%s'\n"),
423 "-n", _("del"));
424 GNUNET_SCHEDULER_shutdown ();
425 return;
426 }
427 rd.data = data;
428 rd.data_size = data_size;
429 rd.record_type = type;
430 rd.expiration = GNUNET_TIME_relative_to_absolute (etime);
431 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; // FIXME: not always...
432 del_qe = GNUNET_NAMESTORE_record_create (ns,
433 zone_pkey,
434 name,
435 &rd,
436 &del_continuation,
437 NULL);
438 }
439 if (list)
440 {
441 list_it = GNUNET_NAMESTORE_zone_iteration_start (ns,
442 &zone,
443 0, 0,
444 &display_record,
445 NULL);
446 }
447}
448
449
450/**
451 * The main function for gnunet-gns.
452 *
453 * @param argc number of arguments from the command line
454 * @param argv command line arguments
455 * @return 0 ok, 1 on error
456 */
457int
458main (int argc, char *const *argv)
459{
460 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
461 {'a', "add", NULL,
462 gettext_noop ("add record"), 0,
463 &GNUNET_GETOPT_set_one, &add},
464 {'d', "delete", NULL,
465 gettext_noop ("delete record"), 0,
466 &GNUNET_GETOPT_set_one, &del},
467 {'D', "display", NULL,
468 gettext_noop ("display records"), 0,
469 &GNUNET_GETOPT_set_one, &list},
470 {'e', "expiration", "TIME",
471 gettext_noop ("expiration time to use (for adding only)"), 1,
472 &GNUNET_GETOPT_set_string, &expirationstring},
473 {'n', "name", "NAME",
474 gettext_noop ("name of the record to add/delete/display"), 1,
475 &GNUNET_GETOPT_set_string, &name},
476 {'t', "type", "TYPE",
477 gettext_noop ("type of the record to add/delete/display"), 1,
478 &GNUNET_GETOPT_set_string, &typestring},
479 {'V', "value", "VALUE",
480 gettext_noop ("value of the record to add/delete"), 1,
481 &GNUNET_GETOPT_set_string, &value},
482 {'z', "zonekey", "FILENAME",
483 gettext_noop ("filename with the zone key"), 1,
484 &GNUNET_GETOPT_set_string, &keyfile},
485 GNUNET_GETOPT_OPTION_END
486 };
487
488 int ret;
489
490 GNUNET_log_setup ("gnunet-gns", "WARNING", NULL);
491 ret =
492 (GNUNET_OK ==
493 GNUNET_PROGRAM_run (argc, argv, "gnunet-gns",
494 _("GNUnet GNS zone manipulation tool"),
495 options,
496 &run, NULL)) ? 0 : 1;
497
498 return ret;
499}
500
501/* end of gnunet-gns.c */