diff options
Diffstat (limited to 'src/namestore')
28 files changed, 8334 insertions, 846 deletions
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am index 47517b9..7783506 100644 --- a/src/namestore/Makefile.am +++ b/src/namestore/Makefile.am @@ -2,10 +2,11 @@ INCLUDES = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet -pkgcfgdir= $(pkgnamedir)/config.d/ +pkgcfgdir= $(pkgdatadir)/config.d/ + +pkgcfg_DATA = \ + namestore.conf -pkgcfg_NAME = \ - namestore.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @@ -24,19 +25,30 @@ endif check_PROGRAMS = \ $(SQLITE_TESTS) \ + test_namestore_record_serialization \ + test_namestore_api_sign_verify \ test_namestore_api \ + test_namestore_api_put \ + test_namestore_api_lookup \ + test_namestore_api_lookup_specific_type \ + test_namestore_api_create \ + test_namestore_api_create_update \ + test_namestore_api_remove \ + test_namestore_api_remove_not_existing_record \ + test_namestore_api_zone_to_name \ test_namestore_api_zone_iteration \ - test_namestore_record_serialization + test_namestore_api_zone_iteration_specific_zone \ + test_namestore_api_zone_iteration_stop -if HAVE_EXPERIMENTAL - check_PROGRAMS +if ENABLE_TEST_RUN +TESTS = $(check_PROGRAMS) endif lib_LTLIBRARIES = \ libgnunetnamestore.la - + libgnunetnamestore_la_SOURCES = \ - namestore_api.c namestore.h + namestore_api.c namestore_common.c namestore.h libgnunetnamestore_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ @@ -46,15 +58,34 @@ libgnunetnamestore_la_LDFLAGS = \ -version-info 0:0:0 bin_PROGRAMS = \ - gnunet-service-namestore + gnunet-service-namestore \ + gnunet-namestore + + +gnunet_namestore_SOURCES = \ + gnunet-namestore.c +gnunet_namestore_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetnamestore.la \ + $(GN_LIBINTL) +gnunet_namestore_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetnamestore.la + + gnunet_service_namestore_SOURCES = \ - gnunet-service-namestore.c \ - namestore_common.c + gnunet-service-namestore.c + gnunet_service_namestore_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetnamestore.la \ $(GN_LIBINTL) +gnunet_service_namestore_DEPENDENCIES = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetnamestore.la if HAVE_SQLITE SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la @@ -64,31 +95,100 @@ plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) libgnunet_plugin_namestore_sqlite_la_SOURCES = \ - plugin_namestore_sqlite.c + plugin_namestore_sqlite.c namestore_common.c libgnunet_plugin_namestore_sqlite_la_LIBADD = \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 libgnunet_plugin_namestore_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) +libgnunet_plugin_namestore_sqlite_la_DEPENDENCIES = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetnamestore.la +test_namestore_api_sign_verify_SOURCES = \ + test_namestore_api_sign_verify.c +test_namestore_api_sign_verify_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_SOURCES = \ - test_namestore_api.c \ - namestore_common.c + test_namestore_api.c test_namestore_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la - + +test_namestore_api_put_SOURCES = \ + test_namestore_api_put.c +test_namestore_api_put_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_lookup_SOURCES = \ + test_namestore_api_lookup.c +test_namestore_api_lookup_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_lookup_specific_type_SOURCES = \ + test_namestore_api_lookup_specific_type.c +test_namestore_api_lookup_specific_type_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + + +test_namestore_api_create_SOURCES = \ + test_namestore_api_create.c +test_namestore_api_create_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_create_update_SOURCES = \ + test_namestore_api_create_update.c +test_namestore_api_create_update_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + + +test_namestore_api_remove_SOURCES = \ + test_namestore_api_remove.c +test_namestore_api_remove_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_remove_not_existing_record_SOURCES = \ + test_namestore_api_remove_not_existing_record.c +test_namestore_api_remove_not_existing_record_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_zone_to_name_SOURCES = \ + test_namestore_api_zone_to_name.c +test_namestore_api_zone_to_name_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + test_namestore_api_zone_iteration_SOURCES = \ - test_namestore_api_zone_iteration.c \ - namestore_common.c + test_namestore_api_zone_iteration.c test_namestore_api_zone_iteration_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_zone_iteration_specific_zone_SOURCES = \ + test_namestore_api_zone_iteration_specific_zone.c +test_namestore_api_zone_iteration_specific_zone_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_zone_iteration_stop_SOURCES = \ + test_namestore_api_zone_iteration_stop.c +test_namestore_api_zone_iteration_stop_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_record_serialization_SOURCES = \ - test_namestore_record_serialization.c \ - namestore_common.c + test_namestore_record_serialization.c test_namestore_record_serialization_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la @@ -96,7 +196,9 @@ test_namestore_record_serialization_LDADD = \ EXTRA_DIST = \ test_namestore_api.conf \ test_plugin_namestore_sqlite.conf\ - hostkey + test_hostkey \ + zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey \ + zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey test_plugin_namestore_sqlite_SOURCES = \ diff --git a/src/namestore/Makefile.in b/src/namestore/Makefile.in index 2ed2a46..180232d 100644 --- a/src/namestore/Makefile.in +++ b/src/namestore/Makefile.in @@ -16,6 +16,7 @@ @SET_MAKE@ + VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ @@ -36,10 +37,22 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -check_PROGRAMS = $(am__EXEEXT_1) test_namestore_api$(EXEEXT) \ +check_PROGRAMS = $(am__EXEEXT_1) \ + test_namestore_record_serialization$(EXEEXT) \ + test_namestore_api_sign_verify$(EXEEXT) \ + test_namestore_api$(EXEEXT) test_namestore_api_put$(EXEEXT) \ + test_namestore_api_lookup$(EXEEXT) \ + test_namestore_api_lookup_specific_type$(EXEEXT) \ + test_namestore_api_create$(EXEEXT) \ + test_namestore_api_create_update$(EXEEXT) \ + test_namestore_api_remove$(EXEEXT) \ + test_namestore_api_remove_not_existing_record$(EXEEXT) \ + test_namestore_api_zone_to_name$(EXEEXT) \ test_namestore_api_zone_iteration$(EXEEXT) \ - test_namestore_record_serialization$(EXEEXT) -bin_PROGRAMS = gnunet-service-namestore$(EXEEXT) + test_namestore_api_zone_iteration_specific_zone$(EXEEXT) \ + test_namestore_api_zone_iteration_stop$(EXEEXT) +bin_PROGRAMS = gnunet-service-namestore$(EXEEXT) \ + gnunet-namestore$(EXEEXT) subdir = src/namestore DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/namestore.conf.in @@ -84,15 +97,11 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ - "$(DESTDIR)$(bindir)" + "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = -libgnunet_plugin_namestore_sqlite_la_DEPENDENCIES = \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(am__DEPENDENCIES_1) am_libgnunet_plugin_namestore_sqlite_la_OBJECTS = \ - plugin_namestore_sqlite.lo + plugin_namestore_sqlite.lo namestore_common.lo libgnunet_plugin_namestore_sqlite_la_OBJECTS = \ $(am_libgnunet_plugin_namestore_sqlite_la_OBJECTS) AM_V_lt = $(am__v_lt_$(V)) @@ -109,7 +118,8 @@ libgnunetnamestore_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) -am_libgnunetnamestore_la_OBJECTS = namestore_api.lo +am_libgnunetnamestore_la_OBJECTS = namestore_api.lo \ + namestore_common.lo libgnunetnamestore_la_OBJECTS = $(am_libgnunetnamestore_la_OBJECTS) libgnunetnamestore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ @@ -118,31 +128,101 @@ libgnunetnamestore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ @HAVE_SQLITE_TRUE@am__EXEEXT_1 = \ @HAVE_SQLITE_TRUE@ test_plugin_namestore_sqlite$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) +am_gnunet_namestore_OBJECTS = gnunet-namestore.$(OBJEXT) +gnunet_namestore_OBJECTS = $(am_gnunet_namestore_OBJECTS) am_gnunet_service_namestore_OBJECTS = \ - gnunet-service-namestore.$(OBJEXT) namestore_common.$(OBJEXT) + gnunet-service-namestore.$(OBJEXT) gnunet_service_namestore_OBJECTS = \ $(am_gnunet_service_namestore_OBJECTS) -gnunet_service_namestore_DEPENDENCIES = \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(am__DEPENDENCIES_1) -am_test_namestore_api_OBJECTS = test_namestore_api.$(OBJEXT) \ - namestore_common.$(OBJEXT) +am_test_namestore_api_OBJECTS = test_namestore_api.$(OBJEXT) test_namestore_api_OBJECTS = $(am_test_namestore_api_OBJECTS) test_namestore_api_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_create_OBJECTS = \ + test_namestore_api_create.$(OBJEXT) +test_namestore_api_create_OBJECTS = \ + $(am_test_namestore_api_create_OBJECTS) +test_namestore_api_create_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_create_update_OBJECTS = \ + test_namestore_api_create_update.$(OBJEXT) +test_namestore_api_create_update_OBJECTS = \ + $(am_test_namestore_api_create_update_OBJECTS) +test_namestore_api_create_update_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_lookup_OBJECTS = \ + test_namestore_api_lookup.$(OBJEXT) +test_namestore_api_lookup_OBJECTS = \ + $(am_test_namestore_api_lookup_OBJECTS) +test_namestore_api_lookup_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_lookup_specific_type_OBJECTS = \ + test_namestore_api_lookup_specific_type.$(OBJEXT) +test_namestore_api_lookup_specific_type_OBJECTS = \ + $(am_test_namestore_api_lookup_specific_type_OBJECTS) +test_namestore_api_lookup_specific_type_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_put_OBJECTS = test_namestore_api_put.$(OBJEXT) +test_namestore_api_put_OBJECTS = $(am_test_namestore_api_put_OBJECTS) +test_namestore_api_put_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_remove_OBJECTS = \ + test_namestore_api_remove.$(OBJEXT) +test_namestore_api_remove_OBJECTS = \ + $(am_test_namestore_api_remove_OBJECTS) +test_namestore_api_remove_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_remove_not_existing_record_OBJECTS = \ + test_namestore_api_remove_not_existing_record.$(OBJEXT) +test_namestore_api_remove_not_existing_record_OBJECTS = \ + $(am_test_namestore_api_remove_not_existing_record_OBJECTS) +test_namestore_api_remove_not_existing_record_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_sign_verify_OBJECTS = \ + test_namestore_api_sign_verify.$(OBJEXT) +test_namestore_api_sign_verify_OBJECTS = \ + $(am_test_namestore_api_sign_verify_OBJECTS) +test_namestore_api_sign_verify_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_zone_iteration_OBJECTS = \ - test_namestore_api_zone_iteration.$(OBJEXT) \ - namestore_common.$(OBJEXT) + test_namestore_api_zone_iteration.$(OBJEXT) test_namestore_api_zone_iteration_OBJECTS = \ $(am_test_namestore_api_zone_iteration_OBJECTS) test_namestore_api_zone_iteration_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_zone_iteration_specific_zone_OBJECTS = \ + test_namestore_api_zone_iteration_specific_zone.$(OBJEXT) +test_namestore_api_zone_iteration_specific_zone_OBJECTS = \ + $(am_test_namestore_api_zone_iteration_specific_zone_OBJECTS) +test_namestore_api_zone_iteration_specific_zone_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_zone_iteration_stop_OBJECTS = \ + test_namestore_api_zone_iteration_stop.$(OBJEXT) +test_namestore_api_zone_iteration_stop_OBJECTS = \ + $(am_test_namestore_api_zone_iteration_stop_OBJECTS) +test_namestore_api_zone_iteration_stop_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_zone_to_name_OBJECTS = \ + test_namestore_api_zone_to_name.$(OBJEXT) +test_namestore_api_zone_to_name_OBJECTS = \ + $(am_test_namestore_api_zone_to_name_OBJECTS) +test_namestore_api_zone_to_name_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_record_serialization_OBJECTS = \ - test_namestore_record_serialization.$(OBJEXT) \ - namestore_common.$(OBJEXT) + test_namestore_record_serialization.$(OBJEXT) test_namestore_record_serialization_OBJECTS = \ $(am_test_namestore_record_serialization_OBJECTS) test_namestore_record_serialization_DEPENDENCIES = \ @@ -181,21 +261,46 @@ AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libgnunet_plugin_namestore_sqlite_la_SOURCES) \ - $(libgnunetnamestore_la_SOURCES) \ + $(libgnunetnamestore_la_SOURCES) $(gnunet_namestore_SOURCES) \ $(gnunet_service_namestore_SOURCES) \ $(test_namestore_api_SOURCES) \ + $(test_namestore_api_create_SOURCES) \ + $(test_namestore_api_create_update_SOURCES) \ + $(test_namestore_api_lookup_SOURCES) \ + $(test_namestore_api_lookup_specific_type_SOURCES) \ + $(test_namestore_api_put_SOURCES) \ + $(test_namestore_api_remove_SOURCES) \ + $(test_namestore_api_remove_not_existing_record_SOURCES) \ + $(test_namestore_api_sign_verify_SOURCES) \ $(test_namestore_api_zone_iteration_SOURCES) \ + $(test_namestore_api_zone_iteration_specific_zone_SOURCES) \ + $(test_namestore_api_zone_iteration_stop_SOURCES) \ + $(test_namestore_api_zone_to_name_SOURCES) \ $(test_namestore_record_serialization_SOURCES) \ $(test_plugin_namestore_sqlite_SOURCES) DIST_SOURCES = $(libgnunet_plugin_namestore_sqlite_la_SOURCES) \ - $(libgnunetnamestore_la_SOURCES) \ + $(libgnunetnamestore_la_SOURCES) $(gnunet_namestore_SOURCES) \ $(gnunet_service_namestore_SOURCES) \ $(test_namestore_api_SOURCES) \ + $(test_namestore_api_create_SOURCES) \ + $(test_namestore_api_create_update_SOURCES) \ + $(test_namestore_api_lookup_SOURCES) \ + $(test_namestore_api_lookup_specific_type_SOURCES) \ + $(test_namestore_api_put_SOURCES) \ + $(test_namestore_api_remove_SOURCES) \ + $(test_namestore_api_remove_not_existing_record_SOURCES) \ + $(test_namestore_api_sign_verify_SOURCES) \ $(test_namestore_api_zone_iteration_SOURCES) \ + $(test_namestore_api_zone_iteration_specific_zone_SOURCES) \ + $(test_namestore_api_zone_iteration_stop_SOURCES) \ + $(test_namestore_api_zone_to_name_SOURCES) \ $(test_namestore_record_serialization_SOURCES) \ $(test_plugin_namestore_sqlite_SOURCES) +DATA = $(pkgcfg_DATA) ETAGS = etags CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -252,6 +357,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBADD_DL = @LIBADD_DL@ @@ -285,6 +391,7 @@ LT_DLLOADERS = @LT_DLLOADERS@ LT_DLPREOPEN = @LT_DLPREOPEN@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ +MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ @@ -403,9 +510,9 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet -pkgcfgdir = $(pkgnamedir)/config.d/ -pkgcfg_NAME = \ - namestore.conf +pkgcfgdir = $(pkgdatadir)/config.d/ +pkgcfg_DATA = \ + namestore.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @@ -413,11 +520,12 @@ pkgcfg_NAME = \ @HAVE_SQLITE_TRUE@SQLITE_TESTS = \ @HAVE_SQLITE_TRUE@ test_plugin_namestore_sqlite +@ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) lib_LTLIBRARIES = \ libgnunetnamestore.la libgnunetnamestore_la_SOURCES = \ - namestore_api.c namestore.h + namestore_api.c namestore_common.c namestore.h libgnunetnamestore_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ @@ -428,48 +536,145 @@ libgnunetnamestore_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 +gnunet_namestore_SOURCES = \ + gnunet-namestore.c + +gnunet_namestore_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetnamestore.la \ + $(GN_LIBINTL) + +gnunet_namestore_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetnamestore.la + gnunet_service_namestore_SOURCES = \ - gnunet-service-namestore.c \ - namestore_common.c + gnunet-service-namestore.c gnunet_service_namestore_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetnamestore.la \ $(GN_LIBINTL) +gnunet_service_namestore_DEPENDENCIES = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetnamestore.la + @HAVE_SQLITE_TRUE@SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) libgnunet_plugin_namestore_sqlite_la_SOURCES = \ - plugin_namestore_sqlite.c + plugin_namestore_sqlite.c namestore_common.c libgnunet_plugin_namestore_sqlite_la_LIBADD = \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 libgnunet_plugin_namestore_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) +libgnunet_plugin_namestore_sqlite_la_DEPENDENCIES = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetnamestore.la + +test_namestore_api_sign_verify_SOURCES = \ + test_namestore_api_sign_verify.c + +test_namestore_api_sign_verify_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + test_namestore_api_SOURCES = \ - test_namestore_api.c \ - namestore_common.c + test_namestore_api.c test_namestore_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la +test_namestore_api_put_SOURCES = \ + test_namestore_api_put.c + +test_namestore_api_put_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_lookup_SOURCES = \ + test_namestore_api_lookup.c + +test_namestore_api_lookup_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_lookup_specific_type_SOURCES = \ + test_namestore_api_lookup_specific_type.c + +test_namestore_api_lookup_specific_type_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_create_SOURCES = \ + test_namestore_api_create.c + +test_namestore_api_create_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_create_update_SOURCES = \ + test_namestore_api_create_update.c + +test_namestore_api_create_update_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_remove_SOURCES = \ + test_namestore_api_remove.c + +test_namestore_api_remove_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_remove_not_existing_record_SOURCES = \ + test_namestore_api_remove_not_existing_record.c + +test_namestore_api_remove_not_existing_record_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_zone_to_name_SOURCES = \ + test_namestore_api_zone_to_name.c + +test_namestore_api_zone_to_name_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + test_namestore_api_zone_iteration_SOURCES = \ - test_namestore_api_zone_iteration.c \ - namestore_common.c + test_namestore_api_zone_iteration.c test_namestore_api_zone_iteration_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la +test_namestore_api_zone_iteration_specific_zone_SOURCES = \ + test_namestore_api_zone_iteration_specific_zone.c + +test_namestore_api_zone_iteration_specific_zone_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_zone_iteration_stop_SOURCES = \ + test_namestore_api_zone_iteration_stop.c + +test_namestore_api_zone_iteration_stop_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + test_namestore_record_serialization_SOURCES = \ - test_namestore_record_serialization.c \ - namestore_common.c + test_namestore_record_serialization.c test_namestore_record_serialization_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ @@ -478,7 +683,9 @@ test_namestore_record_serialization_LDADD = \ EXTRA_DIST = \ test_namestore_api.conf \ test_plugin_namestore_sqlite.conf\ - hostkey + test_hostkey \ + zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey \ + zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey test_plugin_namestore_sqlite_SOURCES = \ test_plugin_namestore.c @@ -640,15 +847,51 @@ clean-checkPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list +gnunet-namestore$(EXEEXT): $(gnunet_namestore_OBJECTS) $(gnunet_namestore_DEPENDENCIES) + @rm -f gnunet-namestore$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gnunet_namestore_OBJECTS) $(gnunet_namestore_LDADD) $(LIBS) gnunet-service-namestore$(EXEEXT): $(gnunet_service_namestore_OBJECTS) $(gnunet_service_namestore_DEPENDENCIES) @rm -f gnunet-service-namestore$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_namestore_OBJECTS) $(gnunet_service_namestore_LDADD) $(LIBS) test_namestore_api$(EXEEXT): $(test_namestore_api_OBJECTS) $(test_namestore_api_DEPENDENCIES) @rm -f test_namestore_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_OBJECTS) $(test_namestore_api_LDADD) $(LIBS) +test_namestore_api_create$(EXEEXT): $(test_namestore_api_create_OBJECTS) $(test_namestore_api_create_DEPENDENCIES) + @rm -f test_namestore_api_create$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_create_OBJECTS) $(test_namestore_api_create_LDADD) $(LIBS) +test_namestore_api_create_update$(EXEEXT): $(test_namestore_api_create_update_OBJECTS) $(test_namestore_api_create_update_DEPENDENCIES) + @rm -f test_namestore_api_create_update$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_create_update_OBJECTS) $(test_namestore_api_create_update_LDADD) $(LIBS) +test_namestore_api_lookup$(EXEEXT): $(test_namestore_api_lookup_OBJECTS) $(test_namestore_api_lookup_DEPENDENCIES) + @rm -f test_namestore_api_lookup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_lookup_OBJECTS) $(test_namestore_api_lookup_LDADD) $(LIBS) +test_namestore_api_lookup_specific_type$(EXEEXT): $(test_namestore_api_lookup_specific_type_OBJECTS) $(test_namestore_api_lookup_specific_type_DEPENDENCIES) + @rm -f test_namestore_api_lookup_specific_type$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_lookup_specific_type_OBJECTS) $(test_namestore_api_lookup_specific_type_LDADD) $(LIBS) +test_namestore_api_put$(EXEEXT): $(test_namestore_api_put_OBJECTS) $(test_namestore_api_put_DEPENDENCIES) + @rm -f test_namestore_api_put$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_put_OBJECTS) $(test_namestore_api_put_LDADD) $(LIBS) +test_namestore_api_remove$(EXEEXT): $(test_namestore_api_remove_OBJECTS) $(test_namestore_api_remove_DEPENDENCIES) + @rm -f test_namestore_api_remove$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_remove_OBJECTS) $(test_namestore_api_remove_LDADD) $(LIBS) +test_namestore_api_remove_not_existing_record$(EXEEXT): $(test_namestore_api_remove_not_existing_record_OBJECTS) $(test_namestore_api_remove_not_existing_record_DEPENDENCIES) + @rm -f test_namestore_api_remove_not_existing_record$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_remove_not_existing_record_OBJECTS) $(test_namestore_api_remove_not_existing_record_LDADD) $(LIBS) +test_namestore_api_sign_verify$(EXEEXT): $(test_namestore_api_sign_verify_OBJECTS) $(test_namestore_api_sign_verify_DEPENDENCIES) + @rm -f test_namestore_api_sign_verify$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_sign_verify_OBJECTS) $(test_namestore_api_sign_verify_LDADD) $(LIBS) test_namestore_api_zone_iteration$(EXEEXT): $(test_namestore_api_zone_iteration_OBJECTS) $(test_namestore_api_zone_iteration_DEPENDENCIES) @rm -f test_namestore_api_zone_iteration$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_zone_iteration_OBJECTS) $(test_namestore_api_zone_iteration_LDADD) $(LIBS) +test_namestore_api_zone_iteration_specific_zone$(EXEEXT): $(test_namestore_api_zone_iteration_specific_zone_OBJECTS) $(test_namestore_api_zone_iteration_specific_zone_DEPENDENCIES) + @rm -f test_namestore_api_zone_iteration_specific_zone$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_zone_iteration_specific_zone_OBJECTS) $(test_namestore_api_zone_iteration_specific_zone_LDADD) $(LIBS) +test_namestore_api_zone_iteration_stop$(EXEEXT): $(test_namestore_api_zone_iteration_stop_OBJECTS) $(test_namestore_api_zone_iteration_stop_DEPENDENCIES) + @rm -f test_namestore_api_zone_iteration_stop$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_zone_iteration_stop_OBJECTS) $(test_namestore_api_zone_iteration_stop_LDADD) $(LIBS) +test_namestore_api_zone_to_name$(EXEEXT): $(test_namestore_api_zone_to_name_OBJECTS) $(test_namestore_api_zone_to_name_DEPENDENCIES) + @rm -f test_namestore_api_zone_to_name$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_zone_to_name_OBJECTS) $(test_namestore_api_zone_to_name_LDADD) $(LIBS) test_namestore_record_serialization$(EXEEXT): $(test_namestore_record_serialization_OBJECTS) $(test_namestore_record_serialization_DEPENDENCIES) @rm -f test_namestore_record_serialization$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_record_serialization_OBJECTS) $(test_namestore_record_serialization_LDADD) $(LIBS) @@ -662,12 +905,24 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-namestore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-namestore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namestore_api.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namestore_common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namestore_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_namestore_sqlite.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_create.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_create_update.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_lookup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_lookup_specific_type.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_put.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_remove.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_remove_not_existing_record.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_sign_verify.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_zone_iteration.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_zone_iteration_specific_zone.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_zone_iteration_stop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_zone_to_name.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_record_serialization.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin_namestore.Po@am__quote@ @@ -700,6 +955,26 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs +install-pkgcfgDATA: $(pkgcfg_DATA) + @$(NORMAL_INSTALL) + test -z "$(pkgcfgdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" + @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ + done + +uninstall-pkgcfgDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgcfgdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgcfgdir)" && rm -f $$files ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -753,6 +1028,98 @@ GTAGS: distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -785,12 +1152,13 @@ distdir: $(DISTFILES) done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am -all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)"; do \ + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -842,7 +1210,7 @@ info: info-am info-am: -install-data-am: install-pluginLTLIBRARIES +install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am @@ -889,29 +1257,28 @@ ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ - uninstall-pluginLTLIBRARIES + uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ - clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ - clean-libtool clean-pluginLTLIBRARIES ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-binPROGRAMS install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-libLTLIBRARIES install-man install-pdf \ - install-pdf-am install-pluginLTLIBRARIES install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ - uninstall-am uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ - uninstall-pluginLTLIBRARIES - - -@HAVE_EXPERIMENTAL_TRUE@ check_PROGRAMS +.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ + clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + install-man install-pdf install-pdf-am install-pkgcfgDATA \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ + uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c new file mode 100644 index 0000000..a0d1de1 --- /dev/null +++ b/src/namestore/gnunet-namestore.c @@ -0,0 +1,507 @@ +/* + This file is part of GNUnet. + (C) 2012 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file gnunet-namestore.c + * @brief command line tool to manipulate the local zone + * @author Christian Grothoff + * + * TODO: + * - allow users to set record options (not just 'RF_AUTHORITY') + * - test + * - add options to list/lookup individual records + */ +#include "platform.h" +#include <gnunet_util_lib.h> +#include <gnunet_dnsparser_lib.h> +#include <gnunet_namestore_service.h> + +/** + * Handle to the namestore. + */ +static struct GNUNET_NAMESTORE_Handle *ns; + +/** + * Hash of the public key of our zone. + */ +static struct GNUNET_CRYPTO_ShortHashCode zone; + +/** + * Private key for the our zone. + */ +static struct GNUNET_CRYPTO_RsaPrivateKey *zone_pkey; + +/** + * Keyfile to manipulate. + */ +static char *keyfile; + +/** + * Desired action is to add a record. + */ +static int add; + +/** + * Queue entry for the 'add' operation. + */ +static struct GNUNET_NAMESTORE_QueueEntry *add_qe; + +/** + * Desired action is to list records. + */ +static int list; + +/** + * List iterator for the 'list' operation. + */ +static struct GNUNET_NAMESTORE_ZoneIterator *list_it; + +/** + * Desired action is to remove a record. + */ +static int del; + +/** + * Is record public + */ +static int public; + +/** + * Is record authority + */ +static int nonauthority; + +/** + * Queue entry for the 'del' operation. + */ +static struct GNUNET_NAMESTORE_QueueEntry *del_qe; + +/** + * Name of the records to add/list/remove. + */ +static char *name; + +/** + * Value of the record to add/remove. + */ +static char *value; + +/** + * Type of the record to add/remove, NULL to remove all. + */ +static char *typestring; + +/** + * Desired expiration time. + */ +static char *expirationstring; + + +/** + * Task run on shutdown. Cleans up everything. + * + * @param cls unused + * @param tc scheduler context + */ +static void +do_shutdown (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (NULL != ns) + { + GNUNET_NAMESTORE_disconnect (ns, GNUNET_NO); + ns = NULL; + } + if (NULL != zone_pkey) + { + GNUNET_CRYPTO_rsa_key_free (zone_pkey); + zone_pkey = NULL; + } +} + + +/** + * Continuation called to notify client about result of the + * operation. + * + * @param cls closure, unused + * @param success GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) + * GNUNET_NO if content was already there + * GNUNET_YES (or other positive value) on success + * @param emsg NULL on success, otherwise an error message + */ +static void +add_continuation (void *cls, + int32_t success, + const char *emsg) +{ + add_qe = NULL; + if (success != GNUNET_YES) + fprintf (stderr, + _("Adding record failed: %s\n"), + (success == GNUNET_NO) ? "record exists" : emsg); + if ( (NULL == del_qe) && + (NULL == list_it) ) + GNUNET_SCHEDULER_shutdown (); +} + + +/** + * Continuation called to notify client about result of the + * operation. + * + * @param cls closure, unused + * @param success GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) + * GNUNET_NO if content was already there + * GNUNET_YES (or other positive value) on success + * @param emsg NULL on success, otherwise an error message + */ +static void +del_continuation (void *cls, + int32_t success, + const char *emsg) +{ + del_qe = NULL; + if (success != GNUNET_YES) + fprintf (stderr, + _("Deleting record failed: %s\n"), + emsg); + if ( (NULL == add_qe) && + (NULL == list_it) ) + GNUNET_SCHEDULER_shutdown (); +} + + +/** + * Process a record that was stored in the namestore. + * + * @param cls closure + * @param zone_key public key of the zone + * @param expire when does the corresponding block in the DHT expire (until + * when should we never do a DHT lookup for the same name again)?; + * GNUNET_TIME_UNIT_ZERO_ABS if there are no records of any type in the namestore, + * or the expiration time of the block in the namestore (even if there are zero + * records matching the desired record type) + * @param name name that is being mapped (at most 255 characters long) + * @param rd_len number of entries in 'rd' array + * @param rd array of records with data to store + * @param signature signature of the record block, NULL if signature is unavailable (i.e. + * because the user queried for a particular record type only) + */ +static void +display_record (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_len, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + const char *typestring; + char *s; + unsigned int i; + + if (NULL == name) + { + list_it = NULL; + if ( (NULL == del_qe) && + (NULL == add_qe) ) + GNUNET_SCHEDULER_shutdown (); + return; + } + FPRINTF (stdout, + "%s:\n", + name); + for (i=0;i<rd_len;i++) + { + typestring = GNUNET_NAMESTORE_number_to_typename (rd[i].record_type); + s = GNUNET_NAMESTORE_value_to_string (rd[i].record_type, + rd[i].data, + rd[i].data_size); + if (NULL == s) + { + FPRINTF (stdout, _("\tCorrupt or unsupported record of type %u\n"), + (unsigned int) rd[i].record_type); + continue; + } + FPRINTF (stdout, "\t%s: %s\n", typestring, s); + GNUNET_free (s); + } + FPRINTF (stdout, "%s", "\n"); + GNUNET_NAMESTORE_zone_iterator_next (list_it); +} + + +/** + * Main function that will be run. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; + uint32_t type; + void *data = NULL; + size_t data_size = 0; + struct GNUNET_TIME_Relative etime; + struct GNUNET_NAMESTORE_RecordData rd; + + if (NULL == keyfile) + { + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", &keyfile)) + { + fprintf (stderr, + _("Option `%s' not given, but I need a zone key file!\n"), + "z"); + return; + } + fprintf (stderr, + _("Using default zone file `%s'\n"), + keyfile); + } + zone_pkey = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + GNUNET_free (keyfile); + keyfile = NULL; + if (! (add|del|list)) + { + /* nothing more to be done */ + fprintf (stderr, + _("No options given\n")); + GNUNET_CRYPTO_rsa_key_free (zone_pkey); + zone_pkey = NULL; + return; + } + if (NULL == zone_pkey) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to read or create private zone key\n")); + return; + } + GNUNET_CRYPTO_rsa_key_get_public (zone_pkey, + &pub); + GNUNET_CRYPTO_short_hash (&pub, sizeof (pub), &zone); + + ns = GNUNET_NAMESTORE_connect (cfg); + if (NULL == ns) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to connect to namestore\n")); + return; + } + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, + &do_shutdown, NULL); + if (NULL == typestring) + type = 0; + else + type = GNUNET_NAMESTORE_typename_to_number (typestring); + if (UINT32_MAX == type) + { + fprintf (stderr, _("Unsupported type `%s'\n"), typestring); + GNUNET_SCHEDULER_shutdown (); + return; + } + if ((NULL == typestring) && (add | del)) + { + fprintf (stderr, + _("Missing option `%s' for operation `%s'\n"), + "-t", _("add/del")); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (NULL != value) + { + if (GNUNET_OK != + GNUNET_NAMESTORE_string_to_value (type, + value, + &data, + &data_size)) + { + fprintf (stderr, _("Value `%s' invalid for record type `%s'\n"), + value, + typestring); + GNUNET_SCHEDULER_shutdown (); + return; + } + } else if (add | del) + { + fprintf (stderr, + _("Missing option `%s' for operation `%s'\n"), + "-V", _("add/del")); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (NULL != expirationstring) + { + if (0 == strcmp (expirationstring, "never")) + { + etime = GNUNET_TIME_UNIT_FOREVER_REL; + } + else if (GNUNET_OK != + GNUNET_STRINGS_fancy_time_to_relative (expirationstring, + &etime)) + { + fprintf (stderr, + _("Invalid time format `%s'\n"), + expirationstring); + GNUNET_SCHEDULER_shutdown (); + return; + } + } else if (add) + { + fprintf (stderr, + _("Missing option `%s' for operation `%s'\n"), + "-e", _("add")); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (add) + { + if (NULL == name) + { + fprintf (stderr, + _("Missing option `%s' for operation `%s'\n"), + "-n", _("add")); + GNUNET_SCHEDULER_shutdown (); + return; + } + rd.data = data; + rd.data_size = data_size; + rd.record_type = type; + rd.expiration = GNUNET_TIME_relative_to_absolute (etime); + if (1 != nonauthority) + rd.flags |= GNUNET_NAMESTORE_RF_AUTHORITY; + if (1 != public) + rd.flags |= GNUNET_NAMESTORE_RF_PRIVATE; + add_qe = GNUNET_NAMESTORE_record_create (ns, + zone_pkey, + name, + &rd, + &add_continuation, + NULL); + } + if (del) + { + if (NULL == name) + { + fprintf (stderr, + _("Missing option `%s' for operation `%s'\n"), + "-n", _("del")); + GNUNET_SCHEDULER_shutdown (); + return; + } + rd.data = data; + rd.data_size = data_size; + rd.record_type = type; + rd.expiration.abs_value = 0; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + del_qe = GNUNET_NAMESTORE_record_remove (ns, + zone_pkey, + name, + &rd, + &del_continuation, + NULL); + } + if (list) + { + uint32_t must_not_flags = 0; + + if (1 == nonauthority) /* List non-authority records */ + must_not_flags |= GNUNET_NAMESTORE_RF_AUTHORITY; + + if (1 == public) + must_not_flags |= GNUNET_NAMESTORE_RF_PRIVATE; + + list_it = GNUNET_NAMESTORE_zone_iteration_start (ns, + &zone, + 0, + must_not_flags, + &display_record, + NULL); + } + GNUNET_free_non_null (data); +} + + +/** + * The main function for gnunet-namestore. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, char *const *argv) +{ + nonauthority = -1; + public = -1; + + static const struct GNUNET_GETOPT_CommandLineOption options[] = { + {'a', "add", NULL, + gettext_noop ("add record"), 0, + &GNUNET_GETOPT_set_one, &add}, + {'d', "delete", NULL, + gettext_noop ("delete record"), 0, + &GNUNET_GETOPT_set_one, &del}, + {'D', "display", NULL, + gettext_noop ("display records"), 0, + &GNUNET_GETOPT_set_one, &list}, + {'e', "expiration", "TIME", + gettext_noop ("expiration time for record to use (for adding only), \"never\" is possible"), 1, + &GNUNET_GETOPT_set_string, &expirationstring}, + {'n', "name", "NAME", + gettext_noop ("name of the record to add/delete/display"), 1, + &GNUNET_GETOPT_set_string, &name}, + {'t', "type", "TYPE", + gettext_noop ("type of the record to add/delete/display"), 1, + &GNUNET_GETOPT_set_string, &typestring}, + {'V', "value", "VALUE", + gettext_noop ("value of the record to add/delete"), 1, + &GNUNET_GETOPT_set_string, &value}, + {'p', "public", NULL, + gettext_noop ("create or list public record"), 0, + &GNUNET_GETOPT_set_one, &public}, + {'N', "non-authority", NULL, + gettext_noop ("create or list non-authority record"), 0, + &GNUNET_GETOPT_set_one, &nonauthority}, + {'z', "zonekey", "FILENAME", + gettext_noop ("filename with the zone key"), 1, + &GNUNET_GETOPT_set_string, &keyfile}, + GNUNET_GETOPT_OPTION_END + }; + + int ret; + + GNUNET_log_setup ("gnunet-namestore", "WARNING", NULL); + ret = + (GNUNET_OK == + GNUNET_PROGRAM_run (argc, argv, "gnunet-namestore", + _("GNUnet zone manipulation tool"), + options, + &run, NULL)) ? 0 : 1; + + return ret; +} + +/* end of gnunet-namestore.c */ diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c index 92eb218..d6c2998 100644 --- a/src/namestore/gnunet-service-namestore.c +++ b/src/namestore/gnunet-service-namestore.c @@ -28,9 +28,10 @@ #include "gnunet_service_lib.h" #include "gnunet_namestore_service.h" #include "gnunet_namestore_plugin.h" +#include "gnunet_signatures.h" #include "namestore.h" - +#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) /** * A namestore operation. @@ -42,11 +43,22 @@ struct GNUNET_NAMESTORE_ZoneIteration struct GNUNET_NAMESTORE_Client * client; - GNUNET_HashCode zone; + int has_zone; + + struct GNUNET_CRYPTO_ShortHashCode zone; - uint64_t op_id; + uint64_t request_id; uint32_t offset; + /** + * Which flags must be included + */ + uint16_t must_have_flags; + + /** + * Which flags must not be included + */ + uint16_t must_not_have_flags; }; @@ -64,25 +76,165 @@ struct GNUNET_NAMESTORE_Client struct GNUNET_NAMESTORE_ZoneIteration *op_tail; }; +struct GNUNET_NAMESTORE_CryptoContainer +{ + char * filename; + + struct GNUNET_CRYPTO_ShortHashCode zone; + struct GNUNET_CRYPTO_RsaPrivateKey *privkey; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey; +}; /** - * Configuration handle. - */ +* Configuration handle. +*/ const struct GNUNET_CONFIGURATION_Handle *GSN_cfg; -static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; +/** +* Database handle +*/ +struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; + +/** +* Zonefile directory +*/ +static char *zonefile_directory; + +static char *db_lib_name; + /** * Our notification context. */ static struct GNUNET_SERVER_NotificationContext *snc; -static char *db_lib_name; - static struct GNUNET_NAMESTORE_Client *client_head; static struct GNUNET_NAMESTORE_Client *client_tail; +struct GNUNET_CONTAINER_MultiHashMap *zonekeys; + + +/** + * Write zonefile to disk + * @param filename where to write + * @param c the crypto container + * + * @return GNUNET_OK on success, GNUNET_SYSERR on fail + */ + +int +write_key_to_file (const char *filename, struct GNUNET_NAMESTORE_CryptoContainer *c) +{ + struct GNUNET_CRYPTO_RsaPrivateKey *ret = c->privkey; + struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc; + struct GNUNET_DISK_FileHandle *fd; + + if (GNUNET_YES == GNUNET_DISK_file_test (filename)) + { + struct GNUNET_CRYPTO_ShortHashCode zone; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; + struct GNUNET_CRYPTO_RsaPrivateKey * privkey; + + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename); + if (privkey == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("File zone `%s' but corrupt content already exists, failed to write! \n"), GNUNET_short_h2s (&zone)); + return GNUNET_SYSERR; + } + + GNUNET_CRYPTO_rsa_key_get_public (privkey, &pubkey); + GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone); + GNUNET_CRYPTO_rsa_key_free (privkey); + + if (0 == memcmp (&zone, &c->zone, sizeof(zone))) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("File zone `%s' containing this key already exists\n"), GNUNET_short_h2s (&zone)); + return GNUNET_OK; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("File zone `%s' but different zone key already exists, failed to write! \n"), GNUNET_short_h2s (&zone)); + return GNUNET_OK; + } + } + 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); + if (NULL == fd) + { + if (errno == EEXIST) + { + if (GNUNET_YES != GNUNET_DISK_file_test (filename)) + { + /* must exist but not be accessible, fail for good! */ + if (0 != ACCESS (filename, R_OK)) + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename); + else + GNUNET_break (0); /* what is going on!? */ + return GNUNET_SYSERR; + } + } + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename); + return GNUNET_SYSERR; + } + + if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES)) + { + GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); + return GNUNET_SYSERR; + } + enc = GNUNET_CRYPTO_rsa_encode_key (ret); + GNUNET_assert (enc != NULL); + GNUNET_assert (ntohs (enc->len) == GNUNET_DISK_file_write (fd, enc, ntohs (enc->len))); + GNUNET_free (enc); + GNUNET_DISK_file_sync (fd); + if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded))) + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); + GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _("Stored zonekey for zone `%s' in file `%s'\n"), GNUNET_short_h2s(&c->zone), c->filename); + return GNUNET_OK; +} + +int zone_to_disk_it (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + struct GNUNET_NAMESTORE_CryptoContainer * c = value; + if (c->filename != NULL) + write_key_to_file(c->filename, c); + else + { + GNUNET_asprintf(&c->filename, "%s/%s.zkey", zonefile_directory, GNUNET_short_h2s (&c->zone)); + write_key_to_file(c->filename, c); + } + + + GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (zonekeys, key, value)); + GNUNET_CRYPTO_rsa_key_free (c->privkey); + GNUNET_free (c->pubkey); + GNUNET_free (c->filename); + GNUNET_free (c); + + return GNUNET_OK; +} + + +struct GNUNET_TIME_Absolute +get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd) +{ + unsigned int c; + struct GNUNET_TIME_Absolute expire = GNUNET_TIME_UNIT_FOREVER_ABS; + + if (NULL == rd) + return GNUNET_TIME_UNIT_ZERO_ABS; + for (c = 0; c < rd_count; c++) + expire = GNUNET_TIME_absolute_min (rd[c].expiration, expire); + return expire; +} /** * Task run during shutdown. @@ -94,12 +246,16 @@ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); - struct GNUNET_NAMESTORE_ZoneIteration * no; struct GNUNET_NAMESTORE_ZoneIteration * tmp; struct GNUNET_NAMESTORE_Client * nc; struct GNUNET_NAMESTORE_Client * next; + GNUNET_SERVER_notification_context_destroy (snc); + snc = NULL; + GNUNET_CONTAINER_multihashmap_iterate(zonekeys, &zone_to_disk_it, NULL); + GNUNET_CONTAINER_multihashmap_destroy(zonekeys); + for (nc = client_head; nc != NULL; nc = next) { next = nc->next; @@ -109,17 +265,14 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) tmp = no->next; GNUNET_free (no); } - + GNUNET_SERVER_client_drop(nc->client); GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc); GNUNET_free (nc); - } - GNUNET_SERVER_notification_context_destroy (snc); - snc = NULL; - GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database)); GNUNET_free (db_lib_name); + GNUNET_free_non_null(zonefile_directory); } static struct GNUNET_NAMESTORE_Client * @@ -137,7 +290,6 @@ client_lookup (struct GNUNET_SERVER_Client *client) return nc; } - /** * Called whenever a client is disconnected. Frees our * resources associated with that client. @@ -160,16 +312,22 @@ client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) if ((NULL == client) || (NULL == nc)) return; - for (no = nc->op_head; no != NULL; no = no->next) + no = nc->op_head; + while (NULL != no) { GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no); GNUNET_free (no); + no = nc->op_head; } + GNUNET_SERVER_client_drop(nc->client); GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc); GNUNET_free (nc); + nc = NULL; } + + static void handle_start (void *cls, struct GNUNET_SERVER_Client * client, const struct GNUNET_MessageHeader * message) @@ -180,18 +338,40 @@ static void handle_start (void *cls, nc->client = client; GNUNET_SERVER_notification_context_add (snc, client); GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc); - + GNUNET_SERVER_client_keep (client); GNUNET_SERVER_receive_done (client, GNUNET_OK); } struct LookupNameContext { struct GNUNET_NAMESTORE_Client *nc; - uint32_t id; + uint32_t request_id; uint32_t record_type; + struct GNUNET_CRYPTO_ShortHashCode *zone; + char * name; }; - +void drop_iterator (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_len, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct GNUNET_CRYPTO_ShortHashCode zone_hash; + int * stop = cls; + if (NULL != zone_key) + { + GNUNET_CRYPTO_short_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_hash); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting zone `%s'\n", GNUNET_short_h2s (&zone_hash)); + GSN_database->delete_zone (GSN_database->cls, &zone_hash); + } + else + { + (*stop) = GNUNET_YES; + } +} static void @@ -206,24 +386,26 @@ handle_lookup_name_it (void *cls, /* send response */ struct LookupNameContext *lnc = cls; struct LookupNameResponseMessage *lnr_msg; - - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key_tmp; - struct GNUNET_NAMESTORE_RecordData * rd_tmp; + struct GNUNET_NAMESTORE_RecordData *rd_selected = NULL; + struct GNUNET_NAMESTORE_CryptoContainer *cc; + struct GNUNET_CRYPTO_RsaSignature *signature_new = NULL; + struct GNUNET_TIME_Absolute e; + struct GNUNET_CRYPTO_ShortHashCode zone_key_hash; + GNUNET_HashCode long_hash; + char *rd_tmp; char *name_tmp; - struct GNUNET_CRYPTO_RsaSignature *signature_tmp; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE"); - + size_t rd_ser_len; size_t r_size = 0; - size_t name_len = 0; - if (NULL != name) - name_len = strlen(name) + 1; int copied_elements = 0; - int contains_signature = 0; + int contains_signature = GNUNET_NO; + int authoritative = GNUNET_NO; int c; + if (NULL != name) + name_len = strlen(name) + 1; + /* count records to copy */ if (rd_count != 0) { @@ -233,68 +415,114 @@ handle_lookup_name_it (void *cls, for (c = 0; c < rd_count; c ++) if (rd[c].record_type == lnc->record_type) copied_elements++; /* found matching record */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records with type %u for name `%s' in zone `%s'\n", + copied_elements, lnc->record_type, lnc->name, GNUNET_short_h2s(lnc->zone)); + rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData)); + copied_elements = 0; + for (c = 0; c < rd_count; c ++) + { + if (rd[c].record_type == lnc->record_type) + { + /* found matching record */ + memcpy (&rd_selected[copied_elements], &rd[c], sizeof (struct GNUNET_NAMESTORE_RecordData)); + copied_elements++; + } + } } else + { copied_elements = rd_count; + rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd; + } + } + else + { + /* No results */ + copied_elements = 0; + rd_selected = NULL; + expire = GNUNET_TIME_UNIT_ZERO_ABS; } - if ((copied_elements == rd_count) && (signature != NULL)) - contains_signature = GNUNET_YES; + rd_ser_len = GNUNET_NAMESTORE_records_get_size(copied_elements, rd_selected); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(copied_elements, rd_selected, rd_ser_len, rd_ser); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records for name `%s' in zone `%s'\n", + copied_elements, lnc->name, GNUNET_short_h2s(lnc->zone)); + + if ((copied_elements == rd_count) && (NULL != signature)) + contains_signature = GNUNET_YES; /* returning all records, so include signature */ + else + contains_signature = GNUNET_NO; /* returning not all records, so do not include signature */ + + + if ((NULL != zone_key) && (copied_elements == rd_count)) + { + GNUNET_CRYPTO_short_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_key_hash); + GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash); + if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash)) + { + cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash); + e = get_block_expiration_time(rd_count, rd); + signature_new = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd, rd_count); + GNUNET_assert (signature_new != NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for name `%s' with %u records in zone `%s'\n",name, copied_elements, GNUNET_short_h2s(&zone_key_hash)); + authoritative = GNUNET_YES; + } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am not authoritative for name `%s' in zone `%s'\n",name, GNUNET_short_h2s(&zone_key_hash)); + } r_size = sizeof (struct LookupNameResponseMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + name_len + - copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData) + - contains_signature * sizeof (struct GNUNET_CRYPTO_RsaSignature); + rd_ser_len; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE"); lnr_msg = GNUNET_malloc (r_size); - - lnr_msg->header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE); - lnr_msg->header.size = ntohs (r_size); - lnr_msg->op_id = htonl (lnc->id); - lnr_msg->rc_count = htonl (copied_elements); + lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE); + lnr_msg->gns_header.header.size = ntohs (r_size); + lnr_msg->gns_header.r_id = htonl (lnc->request_id); + lnr_msg->rd_count = htons (copied_elements); + lnr_msg->rd_len = htons (rd_ser_len); lnr_msg->name_len = htons (name_len); - lnr_msg->expire = GNUNET_TIME_absolute_hton(expire); - lnr_msg->contains_sig = htons (contains_signature); + lnr_msg->expire = GNUNET_TIME_absolute_hton(get_block_expiration_time(copied_elements, rd_selected)); - - zone_key_tmp = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &lnr_msg[1]; - name_tmp = (char *) &zone_key_tmp[1]; - rd_tmp = (struct GNUNET_NAMESTORE_RecordData *) &name_tmp[name_len]; - signature_tmp = (struct GNUNET_CRYPTO_RsaSignature *) &rd_tmp[copied_elements]; + if (rd_selected != rd) + GNUNET_free (rd_selected); if (zone_key != NULL) - memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + lnr_msg->public_key = (*zone_key); else + memset(&lnr_msg->public_key, '\0', sizeof (lnr_msg->public_key)); + + if (GNUNET_YES == authoritative) + { /* use new created signature */ + lnr_msg->contains_sig = htons (GNUNET_YES); + GNUNET_assert (signature_new != NULL); + lnr_msg->signature = *signature_new; + GNUNET_free (signature_new); + } + else if (GNUNET_YES == contains_signature) { - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy; - memset (&dummy, '0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); - memcpy (zone_key_tmp, &dummy, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + /* use existing signature */ + lnr_msg->contains_sig = htons (GNUNET_YES); + GNUNET_assert (signature != NULL); + lnr_msg->signature = *signature; } - memcpy (name_tmp, name, name_len); - /* copy records */ - copied_elements = 0; - if (rd_count != 0) + else { - if (lnc->record_type != 0) - { - /* special record type needed */ - for (c = 0; c < rd_count; c ++) - if (rd[c].record_type == lnc->record_type) - { - /* found matching record */ - memcpy (&rd_tmp[copied_elements], &rd[c], rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); - copied_elements++; - } - } - else - memcpy (rd_tmp, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + /* use no signature */ + memset (&lnr_msg->signature, '\0', sizeof (lnr_msg->signature)); } - if (GNUNET_YES == contains_signature) - memcpy (signature_tmp, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature)); - GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO); + name_tmp = (char *) &lnr_msg[1]; + rd_tmp = &name_tmp[name_len]; + + memcpy (name_tmp, name, name_len); + memcpy (rd_tmp, rd_ser, rd_ser_len); + GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO); GNUNET_free (lnr_msg); } @@ -305,13 +533,11 @@ static void handle_lookup_name (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME"); struct LookupNameContext lnc; struct GNUNET_NAMESTORE_Client *nc; - GNUNET_HashCode name_hash; size_t name_len; char * name; - uint32_t id = 0; + uint32_t rid = 0; uint32_t type = 0; - if (ntohs (message->size) < sizeof (struct LookupNameMessage)) { GNUNET_break_op (0); @@ -328,7 +554,7 @@ static void handle_lookup_name (void *cls, } struct LookupNameMessage * ln_msg = (struct LookupNameMessage *) message; - id = ntohl (ln_msg->op_id); + rid = ntohl (ln_msg->gns_header.r_id); name_len = ntohl (ln_msg->name_len); type = ntohl (ln_msg->record_type); @@ -339,17 +565,26 @@ static void handle_lookup_name (void *cls, return; } - name = GNUNET_malloc (name_len); - memcpy (name, &ln_msg[1], name_len); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up record for name `%s'\n", name); - GNUNET_CRYPTO_hash(name, name_len-1, &name_hash); - GNUNET_free (name); + name = (char *) &ln_msg[1]; + if (name[name_len -1] != '\0') + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + if (0 == type) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up all records for name `%s' in zone `%s'\n", name, GNUNET_short_h2s(&ln_msg->zone)); + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up records with type %u for name `%s' in zone `%s'\n", type, name, GNUNET_short_h2s(&ln_msg->zone)); /* do the actual lookup */ - lnc.id = id; + lnc.request_id = rid; lnc.nc = nc; lnc.record_type = type; - GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, &ln_msg->zone, 0, &handle_lookup_name_it, &lnc); + lnc.name = name; + lnc.zone = &ln_msg->zone; + GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, name, 0, &handle_lookup_name_it, &lnc); GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -361,8 +596,6 @@ static void handle_record_put (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT"); struct GNUNET_NAMESTORE_Client *nc; struct GNUNET_TIME_Absolute expire; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key; - struct GNUNET_NAMESTORE_RecordData *rd; struct GNUNET_CRYPTO_RsaSignature *signature; struct RecordPutResponseMessage rpr_msg; size_t name_len; @@ -370,7 +603,7 @@ static void handle_record_put (void *cls, size_t msg_size_exp; char * name; char * rd_ser; - uint32_t id = 0; + uint32_t rid = 0; uint32_t rd_ser_len; uint32_t rd_count; int res = GNUNET_SYSERR; @@ -391,12 +624,28 @@ static void handle_record_put (void *cls, } struct RecordPutMessage * rp_msg = (struct RecordPutMessage *) message; - id = ntohl (rp_msg->op_id); + + rid = ntohl (rp_msg->gns_header.r_id); + msg_size = ntohs (rp_msg->gns_header.header.size); name_len = ntohs (rp_msg->name_len); + rd_count = ntohs (rp_msg->rd_count); rd_ser_len = ntohs(rp_msg->rd_len); - msg_size = ntohs (message->size); - msg_size_exp = sizeof (struct RecordPutMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + name_len + rd_ser_len; + if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len; if (msg_size != msg_size_exp) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size); @@ -404,25 +653,42 @@ static void handle_record_put (void *cls, GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } + if ((name_len == 0) || (name_len > 256)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + name = (char *) &rp_msg[1]; - if ((name_len == 0) || (name_len > 256)) + if (name[name_len -1] != '\0') { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } - zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &rp_msg[1]; - name = (char *) &zone_key[1]; expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire); signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature; + rd_ser = &name[name_len]; - rd_count = GNUNET_NAMESTORE_records_deserialize(&rd, rd_ser, rd_ser_len); + struct GNUNET_NAMESTORE_RecordData rd[rd_count]; + res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd); + if (res != GNUNET_OK) + { + GNUNET_break_op (0); + goto send; + } + + struct GNUNET_CRYPTO_ShortHashCode zone_hash; + GNUNET_CRYPTO_short_hash (&rp_msg->public_key, sizeof (rp_msg->public_key), &zone_hash); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting %u record for name `%s' in zone `%s'\n", rd_count, name, GNUNET_short_h2s(&zone_hash)); /* Database operation */ res = GSN_database->put_records(GSN_database->cls, - zone_key, + &rp_msg->public_key, expire, name, rd_count, rd, @@ -432,20 +698,157 @@ static void handle_record_put (void *cls, name, (res == GNUNET_OK) ? "OK" : "FAIL"); /* Send response */ - +send: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE"); - rpr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE); - rpr_msg.op_id = rp_msg->op_id; - rpr_msg.header.size = htons (sizeof (struct RecordPutResponseMessage)); - if (GNUNET_OK == res) - rpr_msg.op_result = htons (GNUNET_OK); - else - rpr_msg.op_result = htons (GNUNET_NO); + rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE); + rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage)); + rpr_msg.gns_header.r_id = htonl (rid); + rpr_msg.op_result = htonl (res); GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); } +struct CreateRecordContext +{ + struct GNUNET_NAMESTORE_RecordData *rd; + struct GNUNET_CRYPTO_RsaPrivateKey *pkey; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey; + struct GNUNET_TIME_Absolute expire; + char *name; + int res; +}; + + +static void +handle_create_record_it (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct CreateRecordContext * crc = cls; + struct GNUNET_NAMESTORE_RecordData *rd_new = NULL; + struct GNUNET_CRYPTO_RsaSignature dummy_signature; + struct GNUNET_TIME_Absolute block_expiration; + int res; + int exist = GNUNET_SYSERR; + int update = GNUNET_NO; + int c; + int rd_count_new = 0; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, crc->name); + for (c = 0; c < rd_count; c++) + { + if ((crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PKEY) && (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PKEY)) + { + /* Update unique PKEY */ + exist = c; + update = GNUNET_YES; + break; + } + else if ((crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PSEU) && (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PSEU)) + { + /* Update unique PSEU */ + exist = c; + update = GNUNET_YES; + break; + } + else if ((crc->rd->record_type == rd[c].record_type) && + (crc->rd->data_size == rd[c].data_size) && + (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found existing records for `%s' to update expiration date!\n", crc->name); + exist = c; + if (crc->rd->expiration.abs_value != rd[c].expiration.abs_value) + update = GNUNET_YES; + break; + } + } + + if (exist == GNUNET_SYSERR) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New record does not exist for name `%s'!\n", crc->name); + + if (exist == GNUNET_SYSERR) + { + rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData)); + memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + rd_count_new = rd_count + 1; + rd_new[rd_count] = *(crc->rd); + } + else if (update == GNUNET_NO) + { + /* Exact same record already exists */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No update for %s' record required!\n", crc->name); + res = GNUNET_NO; + goto end; + } + else if (update == GNUNET_YES) + { + /* Update record */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating existing records for `%s'!\n", crc->name); + rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData)); + memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + rd_count_new = rd_count; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating expiration from %llu to %llu!\n", rd_new[exist].expiration.abs_value, crc->rd->expiration.abs_value); + rd_new[exist] = *(crc->rd); + } + + block_expiration = GNUNET_TIME_absolute_max(crc->expire, expire); + if (block_expiration.abs_value != expire.abs_value) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updated block expiration time\n"); + + memset (&dummy_signature, '\0', sizeof (dummy_signature)); + + /* Database operation */ + GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0)); + res = GSN_database->put_records(GSN_database->cls, + (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey, + block_expiration, + crc->name, + rd_count_new, rd_new, + &dummy_signature); + GNUNET_break (GNUNET_OK == res); + if (res == GNUNET_OK) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully put record for `%s' in database \n", crc->name); + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to put record for `%s' in database \n", crc->name); + res = GNUNET_YES; + +end: + GNUNET_free_non_null (rd_new); + + switch (res) { + case GNUNET_SYSERR: + /* failed to create the record */ + crc->res = GNUNET_SYSERR; + break; + case GNUNET_YES: + /* database operations OK */ + if (GNUNET_YES == update) + { + /* we updated an existing record */ + crc->res = GNUNET_NO; + } + else + { + /* we created a new record */ + crc->res = GNUNET_YES; + } + break; + case GNUNET_NO: + /* identical entry existed, so we did nothing */ + crc->res = GNUNET_NO; + break; + default: + break; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res); + +} static void handle_record_create (void *cls, struct GNUNET_SERVER_Client * client, @@ -453,13 +856,26 @@ static void handle_record_create (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE"); struct GNUNET_NAMESTORE_Client *nc; + struct GNUNET_NAMESTORE_CryptoContainer *cc; + struct CreateRecordContext crc; + struct GNUNET_CRYPTO_RsaPrivateKey *pkey; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; struct RecordCreateResponseMessage rcr_msg; + struct GNUNET_CRYPTO_ShortHashCode pubkey_hash; + GNUNET_HashCode long_hash; size_t name_len; size_t msg_size; size_t msg_size_exp; - uint32_t id = 0; + size_t rd_ser_len; + size_t key_len; + uint32_t rid = 0; + char *pkey_tmp; + char *name_tmp; + char *rd_ser; + int rd_count; int res = GNUNET_SYSERR; + crc.res = GNUNET_SYSERR; if (ntohs (message->size) < sizeof (struct RecordCreateMessage)) { @@ -477,10 +893,13 @@ static void handle_record_create (void *cls, } struct RecordCreateMessage * rp_msg = (struct RecordCreateMessage *) message; - id = ntohl (rp_msg->op_id); + rid = ntohl (rp_msg->gns_header.r_id); name_len = ntohs (rp_msg->name_len); msg_size = ntohs (message->size); - msg_size_exp = sizeof (struct RecordCreateMessage) + name_len + sizeof (struct GNUNET_NAMESTORE_RecordData); + rd_count = ntohs (rp_msg->rd_count); + rd_ser_len = ntohs (rp_msg->rd_len); + key_len = ntohs (rp_msg->pkey_len); + msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len; if (msg_size != msg_size_exp) { @@ -490,7 +909,6 @@ static void handle_record_create (void *cls, return; } - if ((name_len == 0) || (name_len > 256)) { GNUNET_break_op (0); @@ -498,23 +916,195 @@ static void handle_record_create (void *cls, return; } - /* DO WORK HERE */ + pkey_tmp = (char *) &rp_msg[1]; + name_tmp = &pkey_tmp[key_len]; + rd_ser = &name_tmp[name_len]; - /* Send response */ + if (name_tmp[name_len -1] != '\0') + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + struct GNUNET_NAMESTORE_RecordData rd[rd_count]; + res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd); + if ((res != GNUNET_OK) || (rd_count != 1)) + { + GNUNET_break_op (0); + goto send; + } + /* Extracting and converting private key */ + pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len); + GNUNET_assert (pkey != NULL); + GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub); + GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash); + GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash); + + if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received new private key for zone `%s'\n",GNUNET_short_h2s(&pubkey_hash)); + + cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer)); + cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len); + cc->pubkey = GNUNET_malloc(sizeof (pub)); + memcpy (cc->pubkey, &pub, sizeof(pub)); + cc->zone = pubkey_hash; + GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + } + + crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire); + crc.res = GNUNET_SYSERR; + crc.pkey = pkey; + crc.pubkey = &pub; + crc.rd = rd; + crc.name = name_tmp; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash)); + + /* Get existing records for name */ + res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc); + if (res != GNUNET_SYSERR) + res = GNUNET_OK; + GNUNET_CRYPTO_rsa_key_free(pkey); + pkey = NULL; + + /* Send response */ +send: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE"); - rcr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE); - rcr_msg.op_id = rp_msg->op_id; - rcr_msg.header.size = htons (sizeof (struct RecordCreateResponseMessage)); - if (GNUNET_OK == res) - rcr_msg.op_result = htons (GNUNET_OK); + rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE); + rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage)); + rcr_msg.gns_header.r_id = htonl (rid); + if ((GNUNET_OK == res) && (crc.res == GNUNET_YES)) + rcr_msg.op_result = htonl (GNUNET_YES); + else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO)) + rcr_msg.op_result = htonl (GNUNET_NO); else - rcr_msg.op_result = htons (GNUNET_NO); + rcr_msg.op_result = htonl (GNUNET_SYSERR); GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); } + +struct RemoveRecordContext +{ + struct GNUNET_NAMESTORE_RecordData *rd; + struct GNUNET_CRYPTO_RsaPrivateKey *pkey; + int remove_name; + uint16_t op_res; +}; + +static void +handle_record_remove_it (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct RemoveRecordContext *rrc = cls; + unsigned int c; + int res; + int found; + unsigned int rd_count_new; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count); + + if (rd_count == 0) + { + /* Could not find record to remove */ + rrc->op_res = 1; + return; + } + + /* Find record to remove */ + found = GNUNET_SYSERR; + for (c = 0; c < rd_count; c++) + { + /* + if (rd[c].flags != rrc->rd->flags) + continue;*/ + if (rd[c].record_type != rrc->rd->record_type) + continue; + /* + if (rd[c].data_size != rrc->rd->data_size) + continue; + GNUNET_break(0); + if (0 != memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size)) + continue; + GNUNET_break(0); */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count); + found = c; + break; + } + if (GNUNET_SYSERR == found) + { + /* Could not find record to remove */ + rrc->op_res = 2; + return; + } + + if (rd_count-1 == 0) + { + struct GNUNET_CRYPTO_ShortHashCode pubkey_hash; + GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash); + res = GSN_database->remove_records (GSN_database->cls, + &pubkey_hash, + name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No records left for name `%s', removing name\n", + name, res); + if (GNUNET_OK != res) + { + /* Could put records into database */ + rrc->op_res = 4; + return; + } + rrc->op_res = 0; + return; + } + + rd_count_new = rd_count -1; + struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new]; + + unsigned int c2 = 0; + for (c = 0; c < rd_count; c++) + { + if (c != found) + { + GNUNET_assert (c2 < rd_count_new); + rd_new[c2] = rd[c]; + c2++; + } + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new); + + /* Create dummy signature */ + struct GNUNET_CRYPTO_RsaSignature dummy_signature; + memset (&dummy_signature, '\0', sizeof (dummy_signature)); + + + /* Put records */ + res = GSN_database->put_records(GSN_database->cls, + zone_key, + expire, + name, + rd_count_new, rd_new, + &dummy_signature); + if (GNUNET_OK != res) + { + /* Could put records into database */ + rrc->op_res = 4; + return; + } + + rrc->op_res = 0; +} + static void handle_record_remove (void *cls, struct GNUNET_SERVER_Client * client, const struct GNUNET_MessageHeader * message) @@ -522,10 +1112,21 @@ static void handle_record_remove (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE"); struct GNUNET_NAMESTORE_Client *nc; struct RecordRemoveResponseMessage rrr_msg; - size_t name_len; - size_t msg_size; - size_t msg_size_exp; - uint32_t id = 0; + struct GNUNET_CRYPTO_RsaPrivateKey *pkey; + struct GNUNET_NAMESTORE_CryptoContainer *cc = NULL; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; + struct GNUNET_CRYPTO_ShortHashCode pubkey_hash; + GNUNET_HashCode long_hash; + char * pkey_tmp = NULL; + char * name_tmp = NULL; + char * rd_ser = NULL; + size_t key_len = 0; + size_t name_len = 0; + size_t rd_ser_len = 0; + size_t msg_size = 0; + size_t msg_size_exp = 0; + uint32_t rd_count; + uint32_t rid = 0; int res = GNUNET_SYSERR; @@ -544,12 +1145,29 @@ static void handle_record_remove (void *cls, return; } - struct RecordRemoveMessage * rp_msg = (struct RecordRemoveMessage *) message; - id = ntohl (rp_msg->op_id); - name_len = ntohs (rp_msg->name_len); + struct RecordRemoveMessage * rr_msg = (struct RecordRemoveMessage *) message; + rid = ntohl (rr_msg->gns_header.r_id); + name_len = ntohs (rr_msg->name_len); + rd_ser_len = ntohs (rr_msg->rd_len); + rd_count = ntohs (rr_msg->rd_count); + key_len = ntohs (rr_msg->pkey_len); msg_size = ntohs (message->size); - msg_size_exp = sizeof (struct RecordRemoveMessage) + name_len + sizeof (struct GNUNET_NAMESTORE_RecordData); + if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + if ((name_len >=256) || (name_len == 0)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len; if (msg_size != msg_size_exp) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size); @@ -558,6 +1176,10 @@ static void handle_record_remove (void *cls, return; } + pkey_tmp = (char *) &rr_msg[1]; + name_tmp = &pkey_tmp[key_len]; + rd_ser = &name_tmp[name_len]; + if ((name_len == 0) || (name_len > 256)) { @@ -566,41 +1188,268 @@ static void handle_record_remove (void *cls, return; } - /* DO WORK HERE */ + if (name_tmp[name_len -1] != '\0') + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } - /* Send response */ + /* Extracting and converting private key */ + pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len); + GNUNET_assert (pkey != NULL); + GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub); + GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash); + GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE"); - rrr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE); - rrr_msg.op_id = rp_msg->op_id; - rrr_msg.header.size = htons (sizeof (struct RecordRemoveResponseMessage)); - if (GNUNET_OK == res) - rrr_msg.op_result = htons (GNUNET_OK); + if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received new private key for zone `%s'\n",GNUNET_short_h2s(&pubkey_hash)); + cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer)); + cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len); + cc->pubkey = GNUNET_malloc(sizeof (pub)); + memcpy (cc->pubkey, &pub, sizeof(pub)); + cc->zone = pubkey_hash; + + GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + } + + + struct GNUNET_NAMESTORE_RecordData rd[rd_count]; + res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd); + if ((res != GNUNET_OK) || (rd_count > 1)) + { + GNUNET_break_op (0); + goto send; + } + + if (0 == rd_count) + { + /* remove the whole name and all records */ + /* Database operation */ + res = GSN_database->remove_records (GSN_database->cls, + &pubkey_hash, + name_tmp); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing name `%s': %s\n", + name_tmp, (GNUNET_OK == res) ? "OK" : "FAIL"); + + if (GNUNET_OK != res) + /* Could not remove entry from database */ + res = 4; + else + res = 0; + } else - rrr_msg.op_result = htons (GNUNET_NO); + { + /* remove a single record */ + struct RemoveRecordContext rrc; + rrc.rd = rd; + rrc.pkey = pkey; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash)); + + /* Database operation */ + res = GSN_database->iterate_records (GSN_database->cls, + &pubkey_hash, + name_tmp, + 0, + handle_record_remove_it, &rrc); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n", + name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL"); + res = rrc.op_res; + } + /* Send response */ +send: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE"); + rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE); + rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage)); + rrr_msg.gns_header.r_id = htonl (rid); + rrr_msg.op_result = htonl (res); GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO); + GNUNET_CRYPTO_rsa_key_free (pkey); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + + +struct ZoneToNameCtx +{ + struct GNUNET_NAMESTORE_Client *nc; + uint32_t rid; +}; + +static void +handle_zone_to_name_it (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct ZoneToNameCtx * ztn_ctx = cls; + struct ZoneToNameResponseMessage *ztnr_msg; + int16_t res = GNUNET_SYSERR; + uint16_t name_len = 0; + uint16_t rd_ser_len = 0 ; + int32_t contains_sig = 0; + size_t msg_size = 0; + + char *rd_ser = NULL; + char *name_tmp; + char *rd_tmp; + char *sig_tmp; + + if ((zone_key != NULL) && (name != NULL)) + { + /* found result */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found results: name is `%s', has %u records\n", name, rd_count); + res = GNUNET_YES; + name_len = strlen (name) +1; + } + else + { + /* no result found */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no results\n"); + res = GNUNET_NO; + name_len = 0; + } + + if (rd_count > 0) + { + rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd); + rd_ser = GNUNET_malloc (rd_ser_len); + GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser); + } + else + rd_ser_len = 0; + + if (signature != NULL) + contains_sig = GNUNET_YES; + else + contains_sig = GNUNET_NO; + + + + msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature); + ztnr_msg = GNUNET_malloc (msg_size); + + name_tmp = (char *) &ztnr_msg[1]; + rd_tmp = &name_tmp[name_len]; + sig_tmp = &rd_tmp[rd_ser_len]; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_TO_NAME_RESPONSE"); + ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE); + ztnr_msg->gns_header.header.size = htons (msg_size); + ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid); + ztnr_msg->res = htons (res); + ztnr_msg->rd_len = htons (rd_ser_len); + ztnr_msg->rd_count = htons (rd_count); + ztnr_msg->name_len = htons (name_len); + ztnr_msg->expire = GNUNET_TIME_absolute_hton(expire); + if (zone_key != NULL) + ztnr_msg->zone_key = *zone_key; + else + memset (&ztnr_msg->zone_key, '\0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + + if ((name_len > 0) && (name != NULL)) + memcpy (name_tmp, name, name_len); + + 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); + if ((rd_ser_len > 0) && (rd_ser != NULL)) + memcpy (rd_tmp, rd_ser, rd_ser_len); + if ((GNUNET_YES == contains_sig) && (signature != NULL)) + memcpy (sig_tmp, signature, contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature)); + + GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, (const struct GNUNET_MessageHeader *) ztnr_msg, GNUNET_NO); + GNUNET_free (ztnr_msg); + GNUNET_free_non_null (rd_ser); +} + + +static void handle_zone_to_name (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME"); + struct GNUNET_NAMESTORE_Client *nc; + struct ZoneToNameCtx ztn_ctx; + size_t msg_size = 0; + uint32_t rid = 0; + + if (ntohs (message->size) != sizeof (struct ZoneToNameMessage)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + struct ZoneToNameMessage *ztn_msg = (struct ZoneToNameMessage *) message; + + if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + rid = ntohl (ztn_msg->gns_header.r_id); + + ztn_ctx.rid = rid; + ztn_ctx.nc = nc; + + struct GNUNET_CRYPTO_ShortHashAsciiEncoded z_tmp; + GNUNET_CRYPTO_short_hash_to_enc(&ztn_msg->zone, &z_tmp); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up name for zone `%s' in zone `%s'\n", + (char *) &z_tmp, + GNUNET_short_h2s (&ztn_msg->value_zone)); + + GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx); + GNUNET_SERVER_receive_done (client, GNUNET_OK); } + +/** + * Copy record, data has to be free separetely + */ +void +copy_record (const struct GNUNET_NAMESTORE_RecordData *src, struct GNUNET_NAMESTORE_RecordData *dest) +{ + + memcpy (dest, src, sizeof (struct GNUNET_NAMESTORE_RecordData)); + dest->data = GNUNET_malloc (src->data_size); + memcpy ((void *) dest->data, src->data, src->data_size); +} + struct ZoneIterationProcResult { - int have_zone_key; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key; + struct GNUNET_NAMESTORE_ZoneIteration *zi; - int have_signature; + int res_iteration_finished; + int records_included; + int has_signature; + + char *name; + struct GNUNET_CRYPTO_ShortHashCode zone_hash; + struct GNUNET_NAMESTORE_RecordData *rd; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key; struct GNUNET_CRYPTO_RsaSignature signature; struct GNUNET_TIME_Absolute expire; - - int have_name; - char name[256]; - - unsigned int rd_count; - char *rd_ser; }; -void zone_iteration_proc (void *cls, +void zone_iteraterate_proc (void *cls, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, struct GNUNET_TIME_Absolute expire, const char *name, @@ -608,40 +1457,230 @@ void zone_iteration_proc (void *cls, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature) { - struct ZoneIterationProcResult *zipr = cls; - size_t len; - if (zone_key != NULL) + struct ZoneIterationProcResult *proc = cls; + struct GNUNET_NAMESTORE_RecordData *rd_filtered; + struct GNUNET_CRYPTO_RsaSignature * new_signature; + struct GNUNET_NAMESTORE_CryptoContainer *cc; + struct GNUNET_CRYPTO_ShortHashCode hash; + GNUNET_HashCode long_hash; + struct GNUNET_TIME_Absolute e; + unsigned int rd_count_filtered = 0; + int include; + int c; + + proc->res_iteration_finished = GNUNET_NO; + proc->records_included = 0; + + if ((zone_key == NULL) && (name == NULL)) { - zipr->zone_key = *zone_key; - zipr->have_zone_key = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n"); + proc->res_iteration_finished = GNUNET_YES; + proc->rd = NULL; + proc->name = NULL; } - else - zipr->have_zone_key = GNUNET_NO; + else if ((zone_key != NULL) && (name != NULL)) /* just a safety check */ + { + rd_filtered = GNUNET_malloc (rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received result for zone iteration: `%s'\n", name); + for (c = 0; c < rd_count; c++) + { + include = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must have 0x%x \n", + c, rd[c].flags, proc->zi->must_have_flags); + /* Checking must have flags */ + if ((rd[c].flags & proc->zi->must_have_flags) == proc->zi->must_have_flags) + { + /* Include */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c); + include = GNUNET_NO; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must not have 0x%x\n", + c, rd[c].flags, proc->zi->must_not_have_flags); + if ((rd[c].flags & proc->zi->must_not_have_flags) != 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c); + include = GNUNET_NO; + } + else + { + /* Include */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c); + } + if (GNUNET_YES == include) + { + copy_record (&rd[c], &rd_filtered[rd_count_filtered]); + rd_count_filtered++; + } + + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Included %i of %i records \n", rd_count_filtered, rd_count); + + proc->records_included = rd_count_filtered; + if (0 == rd_count_filtered) + { + GNUNET_free (rd_filtered); + rd_filtered = NULL; + } + proc->rd = rd_filtered; + proc->name = GNUNET_strdup(name); + memcpy (&proc->zone_key, zone_key, sizeof (proc->zone_key)); - zipr->expire = expire; + /* Signature */ + proc->has_signature = GNUNET_NO; + GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &hash); + GNUNET_CRYPTO_short_hash_double(&hash, &long_hash); + proc->zone_hash = hash; - if (name != NULL) + if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash)) + { + cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash); + e = get_block_expiration_time(rd_count_filtered, rd_filtered); + proc->expire = e; + new_signature = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd_filtered, rd_count_filtered); + GNUNET_assert (signature != NULL); + proc->signature = (*new_signature); + GNUNET_free (new_signature); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n", + name, GNUNET_short_h2s(&hash), rd_count_filtered, e.abs_value); + proc->has_signature = GNUNET_YES; + } + else if (rd_count_filtered == rd_count) + { + proc->expire = expire; + if (NULL != signature) + { + proc->signature = (*signature); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n", + name, GNUNET_short_h2s(&hash), rd_count_filtered, expire.abs_value); + proc->has_signature = GNUNET_YES; + } + else + { + memset (&proc->signature, '\0', sizeof (proc->signature)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No signature provided for `%s'\n", name); + } + } + } + else { - memcpy (zipr->name, name, strlen(name) + 1); - zipr->have_name = GNUNET_YES; + GNUNET_break (0); + return; } + +} + +void find_next_zone_iteration_result (struct ZoneIterationProcResult *proc) +{ + + struct GNUNET_CRYPTO_ShortHashCode *zone; + + if (GNUNET_YES == proc->zi->has_zone) + zone = &proc->zi->zone; else - zipr->have_name = GNUNET_NO; + zone = NULL; + + do + { + GSN_database->iterate_records (GSN_database->cls, zone , NULL, proc->zi->offset, &zone_iteraterate_proc, proc); + proc->zi->offset++; + } + while ((proc->records_included == 0) && (GNUNET_NO == proc->res_iteration_finished)); +} - zipr->rd_count = rd_count; - if (signature != NULL) +void send_zone_iteration_result (struct ZoneIterationProcResult *proc) +{ + struct GNUNET_NAMESTORE_ZoneIteration *zi = proc->zi; + + if (GNUNET_YES == proc->res_iteration_finished) { - zipr->signature = *signature; - zipr->have_signature = GNUNET_YES; + struct ZoneIterationResponseMessage zir_msg; + if (zi->has_zone == GNUNET_YES) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for zone `%s'\n", GNUNET_short_h2s(&zi->zone)); + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for all zones\n"); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending empty `%s' message\n", "ZONE_ITERATION_RESPONSE"); + zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE); + zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage)); + zir_msg.gns_header.r_id = htonl(zi->request_id); + zir_msg.expire = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_ZERO_ABS); + zir_msg.name_len = htons (0); + zir_msg.reserved = htons (0); + zir_msg.rd_count = htons (0); + zir_msg.rd_len = htons (0); + memset (&zir_msg.public_key, '\0', sizeof (zir_msg.public_key)); + memset (&zir_msg.signature, '\0', sizeof (zir_msg.signature)); + GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing zone iterator\n"); + GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi); + GNUNET_free (zi); + return; } else - zipr->have_signature = GNUNET_NO; + { + GNUNET_assert (proc->records_included > 0); + + struct ZoneIterationResponseMessage *zir_msg; + if (zi->has_zone == GNUNET_YES) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over zone `%s'\n", + proc->name, GNUNET_short_h2s(&zi->zone)); + if (zi->has_zone == GNUNET_NO) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over all zones\n", + proc->name); + + size_t name_len; + size_t rd_ser_len; + size_t msg_size; + char *name_tmp; + char *rd_tmp; + name_len = strlen (proc->name) +1; + + rd_ser_len = GNUNET_NAMESTORE_records_get_size(proc->records_included, proc->rd); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(proc->records_included, proc->rd, rd_ser_len, rd_ser); + msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len; + zir_msg = GNUNET_malloc(msg_size); + + name_tmp = (char *) &zir_msg[1]; + rd_tmp = &name_tmp[name_len]; + + zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE); + zir_msg->gns_header.header.size = htons (msg_size); + zir_msg->gns_header.r_id = htonl(zi->request_id); + zir_msg->expire = GNUNET_TIME_absolute_hton(proc->expire); + zir_msg->reserved = htons (0); + zir_msg->name_len = htons (name_len); + zir_msg->rd_count = htons (proc->records_included); + zir_msg->rd_len = htons (rd_ser_len); + zir_msg->signature = proc->signature; + zir_msg->public_key = proc->zone_key; + memcpy (name_tmp, proc->name, name_len); + memcpy (rd_tmp, rd_ser, rd_ser_len); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with size %u\n", "ZONE_ITERATION_RESPONSE", msg_size); + GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) zir_msg, GNUNET_NO); + GNUNET_free (zir_msg); + } +} - if ((rd_count > 0) && (rd != NULL)) +void clean_up_zone_iteration_result (struct ZoneIterationProcResult *proc) +{ + int c; + GNUNET_free_non_null (proc->name); + for (c = 0; c < proc->records_included; c++) { - len = GNUNET_NAMESTORE_records_serialize (&zipr->rd_ser, rd_count, rd); + GNUNET_free ((void *) proc->rd[c].data); } + GNUNET_free_non_null (proc->rd); + proc->name = NULL; + proc->rd = NULL; } static void handle_iteration_start (void *cls, @@ -653,9 +1692,6 @@ static void handle_iteration_start (void *cls, struct ZoneIterationStartMessage * zis_msg = (struct ZoneIterationStartMessage *) message; struct GNUNET_NAMESTORE_Client *nc; struct GNUNET_NAMESTORE_ZoneIteration *zi; - struct ZoneIterationResponseMessage zir_msg; - struct ZoneIterationProcResult zipr; - int res; nc = client_lookup(client); if (nc == NULL) @@ -666,22 +1702,43 @@ static void handle_iteration_start (void *cls, } zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration)); - zi->op_id = ntohl (zis_msg->op_id); + zi->request_id = ntohl (zis_msg->gns_header.r_id); zi->offset = 0; zi->client = nc; - zi->zone = zis_msg->zone; - - GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi); + zi->must_have_flags = ntohs (zis_msg->must_have_flags); + zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags); - res = GSN_database->iterate_records (GSN_database->cls, &zis_msg->zone, NULL, zi->offset , &zone_iteration_proc, &zipr); + struct GNUNET_CRYPTO_ShortHashCode dummy; + memset (&dummy, '\0', sizeof (dummy)); + if (0 == memcmp (&dummy, &zis_msg->zone, sizeof (dummy))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n"); + zi->zone = zis_msg->zone; + zi->has_zone = GNUNET_NO; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over zone `%s'\n", GNUNET_short_h2s (&zis_msg->zone)); + zi->zone = zis_msg->zone; + zi->has_zone = GNUNET_YES; + } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_RESPONSE"); - zir_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE); - zir_msg.op_id = htonl(zi->op_id); - zir_msg.header.size = htons (sizeof (struct ZoneIterationResponseMessage)); + GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi); - GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO); + struct ZoneIterationProcResult proc; + proc.zi = zi; + find_next_zone_iteration_result (&proc); + if (GNUNET_YES == proc.res_iteration_finished) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration done\n"); + } + else if (proc.records_included != 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration return %u records\n", proc.records_included); + } + send_zone_iteration_result (&proc); + clean_up_zone_iteration_result (&proc); GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -695,7 +1752,7 @@ static void handle_iteration_stop (void *cls, struct GNUNET_NAMESTORE_Client *nc; struct GNUNET_NAMESTORE_ZoneIteration *zi; struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message; - uint32_t id; + uint32_t rid; nc = client_lookup(client); if (nc == NULL) @@ -705,10 +1762,10 @@ static void handle_iteration_stop (void *cls, return; } - id = ntohl (zis_msg->op_id); + rid = ntohl (zis_msg->gns_header.r_id); for (zi = nc->op_head; zi != NULL; zi = zi->next) { - if (zi->op_id == id) + if (zi->request_id == rid) break; } if (zi == NULL) @@ -719,7 +1776,10 @@ static void handle_iteration_stop (void *cls, } GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_h2s (&zi->zone)); + if (GNUNET_YES == zi->has_zone) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_short_h2s (&zi->zone)); + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration all zones\n"); GNUNET_free (zi); GNUNET_SERVER_receive_done (client, GNUNET_OK); @@ -734,8 +1794,7 @@ static void handle_iteration_next (void *cls, struct GNUNET_NAMESTORE_Client *nc; struct GNUNET_NAMESTORE_ZoneIteration *zi; struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message; - uint32_t id; - int res; + uint32_t rid; nc = client_lookup(client); if (nc == NULL) @@ -745,10 +1804,10 @@ static void handle_iteration_next (void *cls, return; } - id = ntohl (zis_msg->op_id); + rid = ntohl (zis_msg->gns_header.r_id); for (zi = nc->op_head; zi != NULL; zi = zi->next) { - if (zi->op_id == id) + if (zi->request_id == rid) break; } if (zi == NULL) @@ -758,10 +1817,49 @@ static void handle_iteration_next (void *cls, return; } - zi->offset++; - res = GSN_database->iterate_records (GSN_database->cls, &zi->zone, NULL, zi->offset , &zone_iteration_proc, zi); + struct ZoneIterationProcResult proc; + proc.zi = zi; + + find_next_zone_iteration_result (&proc); + if (GNUNET_YES == proc.res_iteration_finished) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration done\n"); + } + else if (proc.records_included != 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration return %u records\n", proc.records_included); + } + send_zone_iteration_result (&proc); + clean_up_zone_iteration_result (&proc); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); } +int zonekey_file_it (void *cls, const char *filename) +{ + GNUNET_HashCode long_hash; + int *counter = cls; + if ((filename != NULL) && (NULL != strstr(filename, ".zkey"))) + { + struct GNUNET_CRYPTO_RsaPrivateKey * privkey; + struct GNUNET_NAMESTORE_CryptoContainer *c; + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename); + if (privkey == NULL) + return GNUNET_OK; + + c = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer)); + c->pubkey = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + c->privkey = privkey; + GNUNET_CRYPTO_rsa_key_get_public(privkey, c->pubkey); + GNUNET_CRYPTO_short_hash(c->pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &c->zone); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found zonefile for zone `%s'\n", GNUNET_short_h2s (&c->zone)); + GNUNET_CRYPTO_short_hash_double (&c->zone, &long_hash); + GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + (*counter) ++; + } + return GNUNET_OK; +} /** @@ -776,7 +1874,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { char * database; - + int counter = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); static const struct GNUNET_SERVER_MessageHandler handlers[] = { @@ -790,17 +1888,45 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0}, {&handle_record_remove, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0}, + {&handle_zone_to_name, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, 0}, {&handle_iteration_start, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)}, - {&handle_iteration_stop, NULL, - GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage)}, {&handle_iteration_next, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0}, + {&handle_iteration_stop, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, 0}, {NULL, NULL, 0, 0} }; GSN_cfg = cfg; + /* Load private keys from disk */ + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore", "zonefile_directory", + &zonefile_directory)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No directory to load zonefiles specified in configuration\n")); + GNUNET_SCHEDULER_add_now (&cleanup_task, NULL); + return; + } + + if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory)) + { + if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Creating directory `%s' for zone files failed!\n"), zonefile_directory); + GNUNET_SCHEDULER_add_now (&cleanup_task, NULL); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created directory `%s' for zone files\n", zonefile_directory); + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scanning directory `%s' for zone files\n", zonefile_directory); + zonekeys = GNUNET_CONTAINER_multihashmap_create (10); + GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u zone files\n", counter); + /* Loading database plugin */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database", @@ -809,10 +1935,14 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database); GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg); + GNUNET_free (database); if (GSN_database == NULL) + { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n", db_lib_name); - GNUNET_free (database); + GNUNET_SCHEDULER_add_now (&cleanup_task, NULL); + return; + } /* Configuring server handles */ GNUNET_SERVER_add_handlers (server, handlers); @@ -843,3 +1973,4 @@ main (int argc, char *const *argv) } /* end of gnunet-service-namestore.c */ + diff --git a/src/namestore/namestore.conf.in b/src/namestore/namestore.conf.in index c9b9984..d93aea6 100644 --- a/src/namestore/namestore.conf.in +++ b/src/namestore/namestore.conf.in @@ -11,6 +11,7 @@ BINARY = gnunet-service-namestore ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; DATABASE = sqlite +ZONEFILE_DIRECTORY = $SERVICEHOME/namestore/zonefiles [namestore-sqlite] FILENAME = $SERVICEHOME/namestore/sqlite.db diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h index 22fc860..5a42c14 100644 --- a/src/namestore/namestore.h +++ b/src/namestore/namestore.h @@ -29,6 +29,7 @@ /* * Collect message types here, move to protocols later */ +#define GNUNET_MESSAGE_TYPE_NAMESTORE_START 430 #define GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME 431 #define GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE 432 #define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT 433 @@ -37,23 +38,64 @@ #define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE 436 #define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE 437 #define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE 438 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME 439 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE 440 -#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START 439 -#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE 440 -#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT 441 -#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP 442 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START 445 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE 446 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT 447 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP 448 -size_t -GNUNET_NAMESTORE_records_serialize (char ** dest, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd); +/** + * Convert a short hash to a string (for printing debug messages). + * This is one of the very few calls in the entire API that is + * NOT reentrant! + * + * @param hc the short hash code + * @return string form; will be overwritten by next call to GNUNET_h2s. + */ +const char * +GNUNET_short_h2s (const struct GNUNET_CRYPTO_ShortHashCode * hc); + + +/** + * Sign name and records + * + * @param key the private key + * @param expire block expiration + * @param name the name + * @param rd record data + * @param rd_count number of records + * + * @return the signature + */ +struct GNUNET_CRYPTO_RsaSignature * +GNUNET_NAMESTORE_create_signature (const struct GNUNET_CRYPTO_RsaPrivateKey *key, + struct GNUNET_TIME_Absolute expire, + const char *name, + const struct GNUNET_NAMESTORE_RecordData *rd, + unsigned int rd_count); + + +/** + * Compares if two records are equal + * + * @param a Record a + * @param b Record b + * + * @return GNUNET_YES or GNUNET_NO + */ int -GNUNET_NAMESTORE_records_deserialize ( struct GNUNET_NAMESTORE_RecordData **dest, char *src, size_t len); +GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a, + const struct GNUNET_NAMESTORE_RecordData *b); + +GNUNET_NETWORK_STRUCT_BEGIN /** * A GNS record serialized for network transmission. - * layout is [struct GNUNET_NAMESTORE_NetworkRecord][char[data_size] data] + * + * Layout is [struct GNUNET_NAMESTORE_NetworkRecord][char[data_size] data] */ struct GNUNET_NAMESTORE_NetworkRecord { @@ -80,9 +122,8 @@ struct GNUNET_NAMESTORE_NetworkRecord -GNUNET_NETWORK_STRUCT_BEGIN /** - * Connect to namestore service + * Connect to namestore service. FIXME: UNNECESSARY. */ struct StartMessage { @@ -93,329 +134,451 @@ struct StartMessage struct GNUNET_MessageHeader header; }; -GNUNET_NETWORK_STRUCT_END -GNUNET_NETWORK_STRUCT_BEGIN /** * Generic namestore message with op id */ -struct GenericMessage +struct GNUNET_NAMESTORE_Header { /** - * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_* + * header.type will be GNUNET_MESSAGE_TYPE_NAMESTORE_* + * header.size will be message size */ struct GNUNET_MessageHeader header; /** - * Operation ID in NBO + * Request ID in NBO */ - uint32_t op_id; + uint32_t r_id; }; -GNUNET_NETWORK_STRUCT_END /** - * Connect to namestore service + * Lookup a name in the namestore */ -GNUNET_NETWORK_STRUCT_BEGIN struct LookupNameMessage { + struct GNUNET_NAMESTORE_Header gns_header; + /** - * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME + * The zone */ - struct GNUNET_MessageHeader header; + struct GNUNET_CRYPTO_ShortHashCode zone; /** - * Operation ID in NBO + * Requested record type */ - uint32_t op_id; - - /* The zone */ - GNUNET_HashCode zone; - - /* Requested record type */ uint32_t record_type; - /* Requested record type */ + /** + * Length of the name + */ uint32_t name_len; + + /* 0-terminated name here */ }; -GNUNET_NETWORK_STRUCT_END /** * Lookup response - * Memory layout: - * [struct LookupNameResponseMessage][struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded][char *name][rc_count * struct GNUNET_NAMESTORE_RecordData][struct GNUNET_CRYPTO_RsaSignature] */ -GNUNET_NETWORK_STRUCT_BEGIN struct LookupNameResponseMessage { /** * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE */ - struct GNUNET_MessageHeader header; + struct GNUNET_NAMESTORE_Header gns_header; /** - * Operation ID in NBO + * Expiration time */ - uint32_t op_id; - struct GNUNET_TIME_AbsoluteNBO expire; + + /** + * Name length + */ uint16_t name_len; - uint16_t contains_sig; + /** + * Bytes of serialized record data + */ + uint16_t rd_len; + + /** + * Number of records contained + */ + uint16_t rd_count; + + /** + * Is the signature valid + * GNUNET_YES or GNUNET_NO + */ + int16_t contains_sig; - /* Requested record type */ - uint32_t rc_count; + /** + * All zeros if 'contains_sig' is GNUNET_NO. + */ + struct GNUNET_CRYPTO_RsaSignature signature; + + /** + * The public key for the name + */ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key; + + /* 0-terminated name and serialized record data */ + /* rd_len bytes serialized record data */ }; -GNUNET_NETWORK_STRUCT_END /** * Put a record to the namestore - * Memory layout: - * [struct RecordPutMessage][struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded][char *name][rc_count * struct GNUNET_NAMESTORE_RecordData] */ -GNUNET_NETWORK_STRUCT_BEGIN struct RecordPutMessage { /** * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_RECORD_PUT */ - struct GNUNET_MessageHeader header; + struct GNUNET_NAMESTORE_Header gns_header; /** - * Operation ID in NBO + * Expiration time */ - uint32_t op_id; - - /* Contenct starts here */ + struct GNUNET_TIME_AbsoluteNBO expire; - /* name length */ + /** + * Name length + */ uint16_t name_len; - /* Length of serialized rd data */ + /** + * Length of serialized record data + */ uint16_t rd_len; - struct GNUNET_TIME_AbsoluteNBO expire; + /** + * Number of records contained + */ + uint16_t rd_count; + + /** + * always zero (for alignment) + */ + uint16_t reserved; + /** + * The signature + */ struct GNUNET_CRYPTO_RsaSignature signature; + + /** + * The public key + */ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key; + + /* name (0-terminated) followed by "rd_count" serialized records */ + }; -GNUNET_NETWORK_STRUCT_END + /** * Put a record to the namestore response */ -GNUNET_NETWORK_STRUCT_BEGIN struct RecordPutResponseMessage { /** * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE */ - struct GNUNET_MessageHeader header; - - /** - * Operation ID in NBO - */ - uint32_t op_id; - - /* Contenct starts here */ + struct GNUNET_NAMESTORE_Header gns_header; /** - * name length: GNUNET_NO (0) on error, GNUNET_OK (1) on success + * result: + * GNUNET_SYSERR on failure + * GNUNET_OK on success */ - uint16_t op_result; + int32_t op_result; }; -GNUNET_NETWORK_STRUCT_END /** - * Put a record to the namestore + * Create a record and put it to the namestore * Memory layout: - * [struct RecordPutMessage][struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded][char *name][rc_count * struct GNUNET_NAMESTORE_RecordData] */ -GNUNET_NETWORK_STRUCT_BEGIN struct RecordCreateMessage { /** * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE */ - struct GNUNET_MessageHeader header; + struct GNUNET_NAMESTORE_Header gns_header; + + struct GNUNET_TIME_AbsoluteNBO expire; /** - * Operation ID in NBO + * Name length */ - uint32_t op_id; + uint16_t name_len; - /* Contenct starts here */ + /** + * Length of serialized record data + */ + uint16_t rd_len; - /* name length */ - uint16_t name_len; + /** + * Record count + */ + uint16_t rd_count; - struct GNUNET_CRYPTO_RsaSignature signature; + /** + * private key length + */ + uint16_t pkey_len; + + /* followed by: + * GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded private key with length pkey_len + * name with length name_len + * serialized record data with length rd_len + * */ }; -GNUNET_NETWORK_STRUCT_END /** * Create a record to the namestore response - * Memory layout: */ -GNUNET_NETWORK_STRUCT_BEGIN struct RecordCreateResponseMessage { /** * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE */ - struct GNUNET_MessageHeader header; - - /** - * Operation ID in NBO - */ - uint32_t op_id; - - /* Contenct starts here */ + struct GNUNET_NAMESTORE_Header gns_header; /** - * name length: GNUNET_NO (0) on error, GNUNET_OK (1) on success + * name length: GNUNET_NO already exists, GNUNET_YES on success, GNUNET_SYSERR error */ - uint16_t op_result; + int32_t op_result; }; -GNUNET_NETWORK_STRUCT_END + /** * Remove a record from the namestore * Memory layout: - * [struct RecordRemoveMessage][char *name][struct GNUNET_NAMESTORE_RecordData] */ -GNUNET_NETWORK_STRUCT_BEGIN struct RecordRemoveMessage { /** * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE */ - struct GNUNET_MessageHeader header; + struct GNUNET_NAMESTORE_Header gns_header; /** - * Operation ID in NBO + * Name length */ - uint32_t op_id; + uint16_t name_len; - /* Contenct starts here */ + /** + * Length of serialized rd data + */ + uint16_t rd_len; - /* name length */ - uint16_t name_len; + /** + * Number of records contained + */ + uint16_t rd_count; - struct GNUNET_CRYPTO_RsaSignature signature; + /** + * Length of private key + */ + uint16_t pkey_len; + + /* followed by: + * GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded private key with length pkey_len + * name with length name_len + * serialized record data with length rd_len + * */ }; -GNUNET_NETWORK_STRUCT_END /** * Remove a record from the namestore response */ -GNUNET_NETWORK_STRUCT_BEGIN struct RecordRemoveResponseMessage { /** * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE */ - struct GNUNET_MessageHeader header; + struct GNUNET_NAMESTORE_Header gns_header; /** - * Operation ID in NBO + * result: + * 0 : successful + * 1 : no records for entry + * 2 : Could not find record to remove + * 3 : Failed to create new signature + * 4 : Failed to put new set of records in database + */ + int32_t op_result; +}; + + +/** + * Lookup a name for a zone hash + */ +struct ZoneToNameMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME */ - uint32_t op_id; + struct GNUNET_NAMESTORE_Header gns_header; - /* Contenct starts here */ + /** + * The hash of public key of the zone to look up in + */ + struct GNUNET_CRYPTO_ShortHashCode zone; /** - * name length: GNUNET_NO (0) on error, GNUNET_OK (1) on success + * The hash of the public key of the target zone */ - uint16_t op_result; + struct GNUNET_CRYPTO_ShortHashCode value_zone; }; -GNUNET_NETWORK_STRUCT_END + +/** + * Respone for zone to name lookup + */ +struct ZoneToNameResponseMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE + */ + struct GNUNET_NAMESTORE_Header gns_header; + + /** + * Record block expiration + */ + struct GNUNET_TIME_AbsoluteNBO expire; + + /** + * Length of the name + */ + uint16_t name_len; + + /** + * Length of serialized record data + */ + uint16_t rd_len; + + /** + * Number of records contained + */ + uint16_t rd_count; + + /* result in NBO: GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error */ + int16_t res; + + /** + * Signature + */ + struct GNUNET_CRYPTO_RsaSignature signature; + + /** + * Publik key + */ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key; + +}; + /** * Start a zone iteration for the given zone */ -GNUNET_NETWORK_STRUCT_BEGIN struct ZoneIterationStartMessage { /** * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START */ - struct GNUNET_MessageHeader header; + struct GNUNET_NAMESTORE_Header gns_header; /** - * Operation ID in NBO + * Zone hash */ - uint32_t op_id; - - /* Contenct starts here */ + struct GNUNET_CRYPTO_ShortHashCode zone; + /** + * Which flags must be included + */ uint16_t must_have_flags; - uint16_t must_not_have_flags; - GNUNET_HashCode zone; + /** + * Which flags must not be included + */ + uint16_t must_not_have_flags; }; -GNUNET_NETWORK_STRUCT_END + /** * Ask for next result of zone iteration for the given operation */ -GNUNET_NETWORK_STRUCT_BEGIN struct ZoneIterationNextMessage { /** * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT */ - struct GNUNET_MessageHeader header; - - /** - * Operation ID in NBO - */ - uint32_t op_id; + struct GNUNET_NAMESTORE_Header gns_header; }; -GNUNET_NETWORK_STRUCT_END /** * Stop zone iteration for the given operation */ -GNUNET_NETWORK_STRUCT_BEGIN struct ZoneIterationStopMessage { /** * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP */ - struct GNUNET_MessageHeader header; - - /** - * Operation ID in NBO - */ - uint32_t op_id; + struct GNUNET_NAMESTORE_Header gns_header; }; -GNUNET_NETWORK_STRUCT_END /** - * Ask for next result of zone iteration for the given operation + * Next result of zone iteration for the given operation + * // FIXME: use 'struct LookupResponseMessage' instead? (identical except + * for having 'contains_sig' instead of 'reserved', but fully compatible otherwise). */ -GNUNET_NETWORK_STRUCT_BEGIN struct ZoneIterationResponseMessage { /** * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE */ - struct GNUNET_MessageHeader header; + struct GNUNET_NAMESTORE_Header gns_header; + + struct GNUNET_TIME_AbsoluteNBO expire; + + uint16_t name_len; + + /* Record data length */ + uint16_t rd_len; /** - * Operation ID in NBO + * Number of records contained */ - uint32_t op_id; + uint16_t rd_count; + + /** + * always zero (for alignment) + */ + uint16_t reserved; + + /** + * All zeros if 'contains_sig' is GNUNET_NO. + */ + struct GNUNET_CRYPTO_RsaSignature signature; + + /** + * The public key + */ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key; + + + }; GNUNET_NETWORK_STRUCT_END diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c index 1d41399..151fb97 100644 --- a/src/namestore/namestore_api.c +++ b/src/namestore/namestore_api.c @@ -27,11 +27,14 @@ #include "platform.h" #include "gnunet_util_lib.h" +#include "gnunet_crypto_lib.h" #include "gnunet_constants.h" +#include "gnunet_dnsparser_lib.h" #include "gnunet_arm_service.h" +#include "gnunet_signatures.h" #include "gnunet_namestore_service.h" #include "namestore.h" -#define DEBUG_GNS_API GNUNET_EXTRA_LOGGING + #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__) @@ -40,7 +43,15 @@ */ struct GNUNET_NAMESTORE_QueueEntry { + + /** + * Kept in a DLL. + */ struct GNUNET_NAMESTORE_QueueEntry *next; + + /** + * Kept in a DLL. + */ struct GNUNET_NAMESTORE_QueueEntry *prev; struct GNUNET_NAMESTORE_Handle *nsh; @@ -62,7 +73,15 @@ struct GNUNET_NAMESTORE_QueueEntry */ struct GNUNET_NAMESTORE_ZoneIterator { + + /** + * Kept in a DLL. + */ struct GNUNET_NAMESTORE_ZoneIterator *next; + + /** + * Kept in a DLL. + */ struct GNUNET_NAMESTORE_ZoneIterator *prev; uint32_t op_id; @@ -70,9 +89,10 @@ struct GNUNET_NAMESTORE_ZoneIterator struct GNUNET_NAMESTORE_Handle *h; GNUNET_NAMESTORE_RecordProcessor proc; void* proc_cls; - GNUNET_HashCode zone; + struct GNUNET_CRYPTO_ShortHashCode zone; uint32_t no_flags; uint32_t flags; + int has_zone; }; @@ -172,7 +192,7 @@ struct GNUNET_NAMESTORE_SimpleRecord struct GNUNET_NAMESTORE_SimpleRecord *prev; const char *name; - const GNUNET_HashCode *zone; + const struct GNUNET_CRYPTO_ShortHashCode *zone; uint32_t record_type; struct GNUNET_TIME_Absolute expiration; enum GNUNET_NAMESTORE_RecordFlags flags; @@ -181,6 +201,7 @@ struct GNUNET_NAMESTORE_SimpleRecord }; + /** * Disconnect from service and then reconnect. * @@ -198,57 +219,77 @@ handle_lookup_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe, "LOOKUP_NAME_RESPONSE"); struct GNUNET_NAMESTORE_Handle *h = qe->nsh; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key; + + /* Operation done, remove */ + GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe); + + char *name; - struct GNUNET_NAMESTORE_RecordData *rd = NULL; + char * rd_tmp; + struct GNUNET_CRYPTO_RsaSignature *signature = NULL; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy; struct GNUNET_TIME_Absolute expire; - unsigned int rd_count = 0; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key_tmp; + size_t exp_msg_len; size_t msg_len = 0; size_t name_len = 0; + size_t rd_len = 0; int contains_sig = GNUNET_NO; + int rd_count = 0; - rd_count = ntohl (msg->rc_count); - msg_len = ntohs (msg->header.size); + rd_len = ntohs (msg->rd_len); + rd_count = ntohs (msg->rd_count); + msg_len = ntohs (msg->gns_header.header.size); name_len = ntohs (msg->name_len); contains_sig = ntohs (msg->contains_sig); expire = GNUNET_TIME_absolute_ntoh(msg->expire); - if (msg_len != sizeof (struct LookupNameResponseMessage) + + exp_msg_len = sizeof (struct LookupNameResponseMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + - name_len + - rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData) + - contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature)) + name_len + rd_len; + + if (msg_len != exp_msg_len) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message size describes with `%u' bytes but calculated size is %u bytes \n", + msg_len, exp_msg_len); + GNUNET_break_op (0); + return; + } + + name = (char *) &msg[1]; + if (name_len > 0) + { + GNUNET_assert ('\0' == name[name_len -1]); + GNUNET_assert ((name_len - 1) == strlen(name)); + } + rd_tmp = &name[name_len]; + + /* deserialize records */ + struct GNUNET_NAMESTORE_RecordData rd[rd_count]; + if (GNUNET_OK != GNUNET_NAMESTORE_records_deserialize(rd_len, rd_tmp, rd_count, rd)) { GNUNET_break_op (0); return; } - zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1]; - name = (char *) &zone_key[1]; - rd = (struct GNUNET_NAMESTORE_RecordData *) &name[name_len]; /* reset values if values not contained */ if (contains_sig == GNUNET_NO) signature = NULL; else - signature = (struct GNUNET_CRYPTO_RsaSignature *) &rd[rd_count]; - if (rd_count == 0) - rd = NULL; + signature = &msg->signature; if (name_len == 0) name = NULL; - memset (&dummy, '0', sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); - if (0 == memcmp (zone_key, &dummy, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))) - zone_key = NULL; + if (name != NULL) + public_key_tmp = &msg->public_key; + else + public_key_tmp = NULL; if (qe->proc != NULL) { - qe->proc (qe->proc_cls, zone_key, expire, name, rd_count, rd, signature); + qe->proc (qe->proc_cls, public_key_tmp, expire, name, rd_count, (rd_count > 0) ? rd : NULL, signature); } - /* Operation done, remove */ - GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe); GNUNET_free (qe); } @@ -262,20 +303,21 @@ handle_record_put_response (struct GNUNET_NAMESTORE_QueueEntry *qe, "RECORD_PUT_RESPONSE"); struct GNUNET_NAMESTORE_Handle *h = qe->nsh; - int res = GNUNET_OK; + /* Operation done, remove */ + GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe); + + int res = ntohl (msg->op_result); - if (ntohs (msg->op_result) == GNUNET_OK) + if (res == GNUNET_OK) { - res = GNUNET_OK; if (qe->cont != NULL) { qe->cont (qe->cont_cls, res, _("Namestore added record successfully")); } } - else if (ntohs (msg->op_result) == GNUNET_NO) + else if (res == GNUNET_SYSERR) { - res = GNUNET_SYSERR; if (qe->cont != NULL) { qe->cont (qe->cont_cls, res, _("Namestore failed to add record")); @@ -287,9 +329,6 @@ handle_record_put_response (struct GNUNET_NAMESTORE_QueueEntry *qe, return; } - /* Operation done, remove */ - GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe); - GNUNET_free (qe); } @@ -303,34 +342,165 @@ handle_record_create_response (struct GNUNET_NAMESTORE_QueueEntry *qe, "RECORD_CREATE_RESPONSE"); struct GNUNET_NAMESTORE_Handle *h = qe->nsh; - int res = GNUNET_OK; + /* Operation done, remove */ + GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe); - if (ntohs (msg->op_result) == GNUNET_OK) + int res = ntohl (msg->op_result); + if (res == GNUNET_YES) { - res = GNUNET_OK; if (qe->cont != NULL) { qe->cont (qe->cont_cls, res, _("Namestore added record successfully")); } } - else if (ntohs (msg->op_result) == GNUNET_NO) + else if (res == GNUNET_NO) { - res = GNUNET_SYSERR; if (qe->cont != NULL) { - qe->cont (qe->cont_cls, res, _("Namestore failed to add record")); + qe->cont (qe->cont_cls, res, _("Namestore record already existed")); } } else { - GNUNET_break_op (0); - return; + if (qe->cont != NULL) + { + qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Namestore failed to add record\n")); + } + } + + GNUNET_free (qe); +} + + +static void +handle_record_remove_response (struct GNUNET_NAMESTORE_QueueEntry *qe, + struct RecordRemoveResponseMessage* msg, + size_t size) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n", + "RECORD_REMOVE_RESPONSE"); + + struct GNUNET_NAMESTORE_Handle *h = qe->nsh; + /* Operation done, remove */ + GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe); + + int res = ntohl (msg->op_result); + /** + * result: + * 0 : successful + * 1 : No records for entry + * 2 : Could not find record to remove + * 3 : Failed to create new signature + * 4 : Failed to put new set of records in database + */ + switch (res) { + case 0: + if (qe->cont != NULL) + { + qe->cont (qe->cont_cls, GNUNET_YES, _("Namestore removed record successfully")); + } + + break; + case 1: + if (qe->cont != NULL) + { + qe->cont (qe->cont_cls, GNUNET_NO, _("No records for entry")); + } + + break; + case 2: + if (qe->cont != NULL) + { + qe->cont (qe->cont_cls, GNUNET_NO, _("Could not find record to remove")); + } + + break; + case 3: + if (qe->cont != NULL) + { + qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Failed to create new signature")); + } + + break; + case 4: + if (qe->cont != NULL) + { + qe->cont (qe->cont_cls, GNUNET_SYSERR, _("Failed to put new set of records in database")); + } + break; + default: + GNUNET_break_op (0); + break; } + GNUNET_free (qe); +} + +static void +handle_zone_to_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe, + struct ZoneToNameResponseMessage* msg, + size_t size) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n", + "ZONE_TO_NAME_RESPONSE"); + + struct GNUNET_NAMESTORE_Handle *h = qe->nsh; /* Operation done, remove */ GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe); + int res = ntohs (msg->res); + + struct GNUNET_TIME_Absolute expire; + size_t name_len; + size_t rd_ser_len; + unsigned int rd_count; + + char * name_tmp; + char * rd_tmp; + + if (res == GNUNET_SYSERR) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "An error occured during zone to name operation\n"); + if (qe->proc != NULL) + qe->proc (qe->proc_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, NULL, 0, NULL, NULL); + } + else if (res == GNUNET_NO) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore has no result for zone to name mapping \n"); + if (qe->proc != NULL) + qe->proc (qe->proc_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, NULL, 0, NULL, NULL); + } + else if (res == GNUNET_YES) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore has result for zone to name mapping \n"); + + name_len = ntohs (msg->name_len); + rd_count = ntohs (msg->rd_count); + rd_ser_len = ntohs (msg->rd_len); + expire = GNUNET_TIME_absolute_ntoh(msg->expire); + + name_tmp = (char *) &msg[1]; + if (name_len > 0) + { + GNUNET_assert ('\0' == name_tmp[name_len -1]); + GNUNET_assert (name_len -1 == strlen(name_tmp)); + } + rd_tmp = &name_tmp[name_len]; + + struct GNUNET_NAMESTORE_RecordData rd[rd_count]; + if (GNUNET_OK != GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_tmp, rd_count, rd)) + { + GNUNET_break_op (0); + return; + } + + if (qe->proc != NULL) + qe->proc (qe->proc_cls, &msg->zone_key, expire, name_tmp, rd_count, rd, &msg->signature); + } + else + GNUNET_break_op (0); + GNUNET_free (qe); } @@ -367,6 +537,22 @@ manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe, } handle_record_create_response (qe, (struct RecordCreateResponseMessage *) msg, size); break; + case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE: + if (size != sizeof (struct RecordRemoveResponseMessage)) + { + GNUNET_break_op (0); + break; + } + handle_record_remove_response (qe, (struct RecordRemoveResponseMessage *) msg, size); + break; + case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE: + if (size < sizeof (struct ZoneToNameResponseMessage)) + { + GNUNET_break_op (0); + break; + } + handle_zone_to_name_response (qe, (struct ZoneToNameResponseMessage *) msg, size); + break; default: GNUNET_break_op (0); break; @@ -381,12 +567,67 @@ handle_zone_iteration_response (struct GNUNET_NAMESTORE_ZoneIterator *ze, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n", "ZONE_ITERATION_RESPONSE"); + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubdummy; + size_t msg_len = 0; + size_t exp_msg_len = 0; + size_t name_len = 0; + size_t rd_len = 0; + unsigned rd_count = 0; - if (ze->proc != NULL) + char *name_tmp; + char *rd_ser_tmp; + struct GNUNET_TIME_Absolute expire; + + msg_len = ntohs (msg->gns_header.header.size); + rd_len = ntohs (msg->rd_len); + rd_count = ntohs (msg->rd_count); + name_len = ntohs (msg->name_len); + expire = GNUNET_TIME_absolute_ntoh (msg->expire); + + exp_msg_len = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_len; + if (msg_len != exp_msg_len) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message size describes with `%u' bytes but calculated size is %u bytes \n", + msg_len, exp_msg_len); + GNUNET_break_op (0); + return; + } + if (0 != ntohs (msg->reserved)) + { + GNUNET_break_op (0); + return; + } + + memset (&pubdummy, '\0', sizeof (pubdummy)); + if ((0 == name_len) && (0 == (memcmp (&msg->public_key, &pubdummy, sizeof (pubdummy))))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration is completed!\n"); + + GNUNET_CONTAINER_DLL_remove(ze->h->z_head, ze->h->z_tail, ze); + + if (ze->proc != NULL) + ze->proc(ze->proc_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, NULL , 0, NULL, NULL); + + GNUNET_free (ze); + return; + } + + name_tmp = (char *) &msg[1]; + if ((name_tmp[name_len -1] != '\0') || (name_len > 256)) + { + GNUNET_break_op (0); + return; + } + rd_ser_tmp = (char *) &name_tmp[name_len]; + struct GNUNET_NAMESTORE_RecordData rd[rd_count]; + if (GNUNET_OK != GNUNET_NAMESTORE_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd)) { - // FIXME - ze->proc(ze->proc_cls, NULL, GNUNET_TIME_absolute_get_forever(), "dummy", 0, NULL, NULL); + GNUNET_break_op (0); + return; } + + if (ze->proc != NULL) + ze->proc(ze->proc_cls, &msg->public_key, expire, name_tmp, rd_count, rd, &msg->signature); } @@ -423,12 +664,12 @@ static void process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_NAMESTORE_Handle *h = cls; - struct GenericMessage * gm; + struct GNUNET_NAMESTORE_Header * gm; struct GNUNET_NAMESTORE_QueueEntry *qe; struct GNUNET_NAMESTORE_ZoneIterator *ze; uint16_t size; uint16_t type; - uint32_t op_id = UINT32_MAX; + uint32_t r_id = UINT32_MAX; if (NULL == msg) { @@ -439,7 +680,7 @@ process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg) size = ntohs (msg->size); type = ntohs (msg->type); - if (size < sizeof (struct GenericMessage)) + if (size < sizeof (struct GNUNET_NAMESTORE_Header)) { GNUNET_break_op (0); GNUNET_CLIENT_receive (h->client, &process_namestore_message, h, @@ -447,13 +688,13 @@ process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg) return; } - gm = (struct GenericMessage *) msg; - op_id = ntohl (gm->op_id); + gm = (struct GNUNET_NAMESTORE_Header *) msg; + r_id = ntohl (gm->r_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, op_id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, r_id); /* Find matching operation */ - if (op_id > h->op_id) + if (r_id > h->op_id) { /* No matching pending operation found */ GNUNET_break_op (0); @@ -465,7 +706,7 @@ process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg) /* Is it a record related operation ? */ for (qe = h->op_head; qe != NULL; qe = qe->next) { - if (qe->op_id == op_id) + if (qe->op_id == r_id) break; } if (qe != NULL) @@ -476,7 +717,7 @@ process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg) /* Is it a zone iteration operation ? */ for (ze = h->z_head; ze != NULL; ze = ze->next) { - if (ze->op_id == op_id) + if (ze->op_id == r_id) break; } if (ze != NULL) @@ -622,7 +863,7 @@ static void force_reconnect (struct GNUNET_NAMESTORE_Handle *h) { h->reconnect = GNUNET_NO; - GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (h->client); h->client = NULL; h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task, @@ -655,23 +896,15 @@ GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) return h; } - -/** - * Disconnect from the namestore service (and free associated - * resources). - * - * @param h handle to the namestore - * @param drop set to GNUNET_YES to delete all data in namestore (!) - */ -void -GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop) +static void +clean_up_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PendingMessage *p; struct GNUNET_NAMESTORE_QueueEntry *q; struct GNUNET_NAMESTORE_ZoneIterator *z; - + struct GNUNET_NAMESTORE_Handle *h = cls; GNUNET_assert (h != NULL); - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); while (NULL != (p = h->pending_head)) { GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p); @@ -692,7 +925,7 @@ GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop) if (NULL != h->client) { - GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task) @@ -706,6 +939,21 @@ GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop) /** + * Disconnect from the namestore service (and free associated + * resources). + * + * @param h handle to the namestore + * @param drop set to GNUNET_YES to delete all data in namestore (!) + */ +void +GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from namestore service\n"); + GNUNET_SCHEDULER_add_now (&clean_up_task, h); +} + + +/** * Store an item in the namestore. If the item is already present, * the expiration time is updated to the max of the existing time and * the new time. This API is used when we cache signatures from other @@ -714,7 +962,7 @@ GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop) * @param h handle to the namestore * @param zone_key public key of the zone * @param name name that is being mapped (at most 255 characters long) - * @param expire when does the corresponding block in the DHT expire (until + * @param freshness when does the corresponding block in the DHT expire (until * when should we never do a DHT lookup for the same name again)? * @param rd_count number of entries in 'rd' array * @param rd array of records with data to store @@ -727,7 +975,7 @@ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, const char *name, - struct GNUNET_TIME_Absolute expire, + struct GNUNET_TIME_Absolute freshness, unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature, @@ -738,52 +986,63 @@ GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h, struct PendingMessage *pe; /* pointer to elements */ - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key_tmp; char * rd_tmp; - char * rd_ser; char * name_tmp; size_t msg_size = 0; - size_t name_len = strlen(name) + 1; + size_t name_len = 0; size_t rd_ser_len = 0; - uint32_t id = 0; + uint32_t rid = 0; GNUNET_assert (NULL != h); - id = get_op_id(h); + GNUNET_assert (NULL != zone_key); + GNUNET_assert (NULL != name); + GNUNET_assert (NULL != rd); + GNUNET_assert (NULL != signature); + + name_len = strlen(name) + 1; + if (name_len > 256) + { + GNUNET_break (0); + return NULL; + } + + rid = get_op_id(h); qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); qe->nsh = h; qe->cont = cont; qe->cont_cls = cont_cls; - qe->op_id = id; + qe->op_id = rid; GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe); /* set msg_size*/ - rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, rd_count, rd); + rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser); struct RecordPutMessage * msg; - msg_size = sizeof (struct RecordPutMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + name_len + rd_ser_len; + msg_size = sizeof (struct RecordPutMessage) + name_len + rd_ser_len; /* create msg here */ pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); pe->size = msg_size; pe->is_init = GNUNET_NO; msg = (struct RecordPutMessage *) &pe[1]; - zone_key_tmp = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1]; - name_tmp = (char *) &zone_key_tmp[1]; + name_tmp = (char *) &msg[1]; rd_tmp = &name_tmp[name_len]; - msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT); - msg->header.size = htons (msg_size); - msg->op_id = htonl (id); - memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT); + msg->gns_header.header.size = htons (msg_size); + msg->gns_header.r_id = htonl (rid); msg->signature = *signature; msg->name_len = htons (name_len); - memcpy (name_tmp, name, name_len); - msg->expire = GNUNET_TIME_absolute_hton (expire); + msg->expire = GNUNET_TIME_absolute_hton (freshness); msg->rd_len = htons (rd_ser_len); + msg->rd_count = htons (rd_count); + msg->public_key = *zone_key; + memcpy (name_tmp, name, name_len); memcpy (rd_tmp, rd_ser, rd_ser_len); - GNUNET_free (rd_ser); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size); @@ -799,6 +1058,7 @@ GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h, * to validate signatures received from the network. * * @param public_key public key of the zone + * @param expire block expiration * @param name name that is being mapped (at most 255 characters long) * @param rd_count number of entries in 'rd' array * @param rd array of records with data to store @@ -807,12 +1067,53 @@ GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h, */ int GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key, + const struct GNUNET_TIME_Absolute expire, const char *name, unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature) { - return GNUNET_SYSERR; + int res = GNUNET_SYSERR; + size_t rd_ser_len = 0; + size_t name_len = 0; + char * name_tmp; + char * rd_tmp; + struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose; + struct GNUNET_TIME_AbsoluteNBO *expire_tmp; + struct GNUNET_TIME_AbsoluteNBO expire_nbo = GNUNET_TIME_absolute_hton(expire); + + GNUNET_assert (public_key != NULL); + GNUNET_assert (name != NULL); + GNUNET_assert (rd != NULL); + GNUNET_assert (signature != NULL); + + + rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser); + + name_len = strlen (name) + 1; + if (name_len > 256) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + sig_purpose = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + rd_ser_len + name_len); + sig_purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)+ rd_ser_len + name_len); + sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); + expire_tmp = (struct GNUNET_TIME_AbsoluteNBO *) &sig_purpose[1]; + name_tmp = (char *) &expire_tmp[1]; + rd_tmp = &name_tmp[name_len]; + memcpy (expire_tmp, &expire_nbo, sizeof (struct GNUNET_TIME_AbsoluteNBO)); + memcpy (name_tmp, name, name_len); + memcpy (rd_tmp, rd_ser, rd_ser_len); + + res = GNUNET_CRYPTO_rsa_verify(GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, sig_purpose, signature, public_key); + + GNUNET_free (sig_purpose); + + return res; } /** @@ -839,26 +1140,45 @@ GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h, struct GNUNET_NAMESTORE_QueueEntry *qe; struct PendingMessage *pe; char * name_tmp; + char * pkey_tmp; char * rd_tmp; - char * rd_ser; size_t rd_ser_len = 0; size_t msg_size = 0; size_t name_len = 0; - uint32_t id = 0; + size_t key_len = 0; + uint32_t rid = 0; GNUNET_assert (NULL != h); + GNUNET_assert (NULL != pkey); + GNUNET_assert (NULL != name); + GNUNET_assert (NULL != rd); + + name_len = strlen(name) + 1; + if (name_len > 256) + { + GNUNET_break (0); + return NULL; + } - id = get_op_id(h); + rid = get_op_id(h); qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); qe->nsh = h; qe->cont = cont; qe->cont_cls = cont_cls; - qe->op_id = id; + qe->op_id = rid; + GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe); /* set msg_size*/ - rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, 1, rd); + struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey); + GNUNET_assert (pkey_enc != NULL); + key_len = ntohs (pkey_enc->len); + + rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser); + struct RecordCreateMessage * msg; - msg_size = sizeof (struct RecordCreateMessage) + name_len + rd_ser_len; + msg_size = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len; /* create msg here */ pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); @@ -866,17 +1186,22 @@ GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h, pe->is_init = GNUNET_NO; msg = (struct RecordCreateMessage *) &pe[1]; - name_tmp = (char *) &msg[1]; + pkey_tmp = (char *) &msg[1]; + name_tmp = &pkey_tmp[key_len]; rd_tmp = &name_tmp[name_len]; - msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE); - msg->header.size = htons (msg_size); - msg->op_id = htonl (id); - //msg->signature = *signature; + msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE); + msg->gns_header.header.size = htons (msg_size); + msg->gns_header.r_id = htonl (rid); msg->name_len = htons (name_len); + msg->rd_count = htons (1); + msg->rd_len = htons (rd_ser_len); + msg->pkey_len = htons (key_len); + msg->expire = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_FOREVER_ABS); + memcpy (pkey_tmp, pkey_enc, key_len); memcpy (name_tmp, name, name_len); memcpy (rd_tmp, rd_ser, rd_ser_len); - GNUNET_free (rd_ser); + GNUNET_free (pkey_enc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size); @@ -896,7 +1221,7 @@ GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h, * @param h handle to the namestore * @param pkey private key of the zone * @param name name that is being mapped (at most 255 characters long) - * @param rd record data + * @param rd record data, remove specific record, NULL to remove the name and all records * @param cont continuation to call when done * @param cont_cls closure for cont * @return handle to abort the request @@ -911,27 +1236,43 @@ GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h, { struct GNUNET_NAMESTORE_QueueEntry *qe; struct PendingMessage *pe; - char * rd_tmp; - char * rd_ser; - char * name_tmp; + char *pkey_tmp; + char *rd_tmp; + char *name_tmp; size_t rd_ser_len = 0; size_t msg_size = 0; size_t name_len = 0; - uint32_t id = 0; + size_t key_len = 0; + uint32_t rid = 0; + uint16_t rd_count = 1; GNUNET_assert (NULL != h); - id = get_op_id(h); + rid = get_op_id(h); qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); qe->nsh = h; qe->cont = cont; qe->cont_cls = cont_cls; - qe->op_id = id; + qe->op_id = rid; + GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe); /* set msg_size*/ - rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, 1, rd); + struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey); + GNUNET_assert (pkey_enc != NULL); + key_len = ntohs (pkey_enc->len); + + if (NULL == rd) + rd_count = 0; + else + rd_count = 1; + rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_ser); + + name_len = strlen (name) + 1; + struct RecordRemoveMessage * msg; - msg_size = sizeof (struct RecordRemoveMessage) + name_len + rd_ser_len; + msg_size = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len; /* create msg here */ pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); @@ -939,17 +1280,22 @@ GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h, pe->is_init = GNUNET_NO; msg = (struct RecordRemoveMessage *) &pe[1]; - name_tmp = (char *) &msg[1]; + pkey_tmp = (char *) &msg[1]; + name_tmp = &pkey_tmp[key_len]; rd_tmp = &name_tmp[name_len]; - msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE); - msg->header.size = htons (msg_size); - msg->op_id = htonl (id); - //msg->signature = *signature; + msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE); + msg->gns_header.header.size = htons (msg_size); + msg->gns_header.r_id = htonl (rid); msg->name_len = htons (name_len); + msg->rd_len = htons (rd_ser_len); + msg->rd_count = htons (rd_count); + msg->pkey_len = htons (key_len); + memcpy (pkey_tmp, pkey_enc, key_len); memcpy (name_tmp, name, name_len); memcpy (rd_tmp, rd_ser, rd_ser_len); - GNUNET_free (rd_ser); + + GNUNET_free (pkey_enc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size); @@ -975,7 +1321,7 @@ GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h, */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, - const GNUNET_HashCode *zone, + const struct GNUNET_CRYPTO_ShortHashCode *zone, const char *name, uint32_t record_type, GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls) @@ -984,7 +1330,7 @@ GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, struct PendingMessage *pe; size_t msg_size = 0; size_t name_len = 0; - uint32_t id = 0; + uint32_t rid = 0; GNUNET_assert (NULL != h); GNUNET_assert (NULL != zone); @@ -997,12 +1343,12 @@ GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, return NULL; } - id = get_op_id(h); + rid = get_op_id(h); qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); qe->nsh = h; qe->proc = proc; qe->proc_cls = proc_cls; - qe->op_id = id; + qe->op_id = rid; GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe); /* set msg_size*/ @@ -1014,12 +1360,12 @@ GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, pe->size = msg_size; pe->is_init = GNUNET_NO; msg = (struct LookupNameMessage *) &pe[1]; - msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME); - msg->header.size = htons (msg_size); - msg->op_id = htonl (id); + msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME); + msg->gns_header.header.size = htons (msg_size); + msg->gns_header.r_id = htonl (rid); msg->record_type = htonl (record_type); - msg->zone = *zone; msg->name_len = htonl (name_len); + msg->zone = *zone; memcpy (&msg[1], name, name_len); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name); @@ -1032,6 +1378,72 @@ GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, } +/** + * Look for an existing PKEY delegation record for a given public key. + * Returns at most one result to the processor. + * + * @param h handle to the namestore + * @param zone hash of public key of the zone to look up in, never NULL + * @param value_zone hash of the public key of the target zone (value), never NULL + * @param proc function to call on the matching records, or with + * NULL (rd_count == 0) if there are no matching records + * @param proc_cls closure for proc + * @return a handle that can be used to + * cancel + */ +struct GNUNET_NAMESTORE_QueueEntry * +GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h, + const struct GNUNET_CRYPTO_ShortHashCode *zone, + const struct GNUNET_CRYPTO_ShortHashCode *value_zone, + GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls) +{ + struct GNUNET_NAMESTORE_QueueEntry *qe; + struct PendingMessage *pe; + size_t msg_size = 0; + uint32_t rid = 0; + + GNUNET_assert (NULL != h); + GNUNET_assert (NULL != zone); + GNUNET_assert (NULL != value_zone); + + rid = get_op_id(h); + qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); + qe->nsh = h; + qe->proc = proc; + qe->proc_cls = proc_cls; + qe->op_id = rid; + GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe); + + /* set msg_size*/ + msg_size = sizeof (struct ZoneToNameMessage); + pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); + + /* create msg here */ + struct ZoneToNameMessage * msg; + pe->size = msg_size; + pe->is_init = GNUNET_NO; + msg = (struct ZoneToNameMessage *) &pe[1]; + msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME); + msg->gns_header.header.size = htons (msg_size); + msg->gns_header.r_id = htonl (rid); + msg->zone = *zone; + msg->value_zone = *value_zone; + + char * z_tmp = GNUNET_strdup (GNUNET_short_h2s (zone)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s' in zone `%s'\n", + "NAMESTORE_ZONE_TO_NAME", + z_tmp, + GNUNET_short_h2s (value_zone)); + GNUNET_free (z_tmp); + + /* transmit message */ + GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); + do_transmit(h); + + return qe; +} + + /** * Starts a new zone iteration (used to periodically PUT all of our @@ -1053,7 +1465,7 @@ GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, */ struct GNUNET_NAMESTORE_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h, - const GNUNET_HashCode *zone, + const struct GNUNET_CRYPTO_ShortHashCode *zone, enum GNUNET_NAMESTORE_RecordFlags must_have_flags, enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags, GNUNET_NAMESTORE_RecordProcessor proc, @@ -1062,18 +1474,28 @@ GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h, struct GNUNET_NAMESTORE_ZoneIterator *it; struct PendingMessage *pe; size_t msg_size = 0; - uint32_t id = 0; + uint32_t rid = 0; GNUNET_assert (NULL != h); - GNUNET_assert (NULL != zone); - id = get_op_id(h); + + rid = get_op_id(h); it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator)); it->h = h; it->proc = proc; - it->proc_cls = proc; - it->op_id = id; - it->zone = *zone; + it->proc_cls = proc_cls; + it->op_id = rid; + + if (NULL != zone) + { + it->zone = *zone; + it->has_zone = GNUNET_YES; + } + else + { + memset (&it->zone, '\0', sizeof (it->zone)); + it->has_zone = GNUNET_NO; + } GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it); /* set msg_size*/ @@ -1085,14 +1507,23 @@ GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h, pe->size = msg_size; pe->is_init = GNUNET_NO; msg = (struct ZoneIterationStartMessage *) &pe[1]; - msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START); - msg->header.size = htons (msg_size); - msg->op_id = htonl (id); - msg->zone = *zone; + msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START); + msg->gns_header.header.size = htons (msg_size); + msg->gns_header.r_id = htonl (rid); + if (NULL != zone) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_short_h2s(zone)); + msg->zone = *zone; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for all zones\n", "ZONE_ITERATION_START"); + memset (&msg->zone, '\0', sizeof (msg->zone)); + } msg->must_have_flags = ntohs (must_have_flags); msg->must_not_have_flags = ntohs (must_not_have_flags); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone)); + /* transmit message */ GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); @@ -1117,6 +1548,15 @@ GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it) GNUNET_assert (NULL != it); h = it->h; + struct GNUNET_NAMESTORE_ZoneIterator *tmp = it->h->z_head; + + while (tmp != NULL) + { + if (tmp == it) + break; + tmp = tmp->next; + } + GNUNET_assert (NULL != tmp); /* set msg_size*/ msg_size = sizeof (struct ZoneIterationNextMessage); @@ -1127,11 +1567,11 @@ GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it) pe->size = msg_size; pe->is_init = GNUNET_NO; msg = (struct ZoneIterationNextMessage *) &pe[1]; - msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT); - msg->header.size = htons (msg_size); - msg->op_id = htonl (it->op_id); + msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT); + msg->gns_header.header.size = htons (msg_size); + msg->gns_header.r_id = htonl (it->op_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_NEXT", GNUNET_h2s(&it->zone)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_NEXT"); /* transmit message */ GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); @@ -1151,6 +1591,15 @@ GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it) struct PendingMessage *pe; size_t msg_size = 0; struct GNUNET_NAMESTORE_Handle *h = it->h; + struct GNUNET_NAMESTORE_ZoneIterator *tmp = it->h->z_head; + + while (tmp != NULL) + { + if (tmp == it) + break; + tmp = tmp->next; + } + GNUNET_assert (NULL != tmp); /* set msg_size*/ msg_size = sizeof (struct ZoneIterationStopMessage); @@ -1161,11 +1610,14 @@ GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it) pe->size = msg_size; pe->is_init = GNUNET_NO; msg = (struct ZoneIterationStopMessage *) &pe[1]; - msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP); - msg->header.size = htons (msg_size); - msg->op_id = htonl (it->op_id); + msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP); + msg->gns_header.header.size = htons (msg_size); + msg->gns_header.r_id = htonl (it->op_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone)); + if (GNUNET_YES == it->has_zone) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_STOP", GNUNET_short_h2s(&it->zone)); + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for all zones\n", "ZONE_ITERATION_STOP"); /* transmit message */ GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); diff --git a/src/namestore/namestore_common.c b/src/namestore/namestore_common.c index 37f0eab..95f6364 100644 --- a/src/namestore/namestore_common.c +++ b/src/namestore/namestore_common.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010 Christian Grothoff (and other contributing authors) + (C) 2009, 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -28,132 +28,536 @@ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" +#include "gnunet_signatures.h" #include "gnunet_arm_service.h" #include "gnunet_namestore_service.h" +#include "gnunet_dnsparser_lib.h" #include "namestore.h" -#define DEBUG_GNS_API GNUNET_EXTRA_LOGGING + #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__) + + +/** + * Internal format of a record in the serialized form. + */ +struct NetworkRecord +{ + + /** + * Expiration time for the DNS record. + */ + struct GNUNET_TIME_AbsoluteNBO expiration; + + /** + * Number of bytes in 'data', network byte order. + */ + uint32_t data_size; + + /** + * Type of the GNS/DNS record, network byte order. + */ + uint32_t record_type; + + /** + * Flags for the record, network byte order. + */ + uint32_t flags; + +}; + + /** - * Serialize an array of GNUNET_NAMESTORE_RecordData *rd to transmit over the - * network + * Convert a short hash to a string (for printing debug messages). + * This is one of the very few calls in the entire API that is + * NOT reentrant! * - * @param dest where to write the serialized data - * @param rd_count number of elements in array - * @param rd array + * @param hc the short hash code + * @return string form; will be overwritten by next call to GNUNET_h2s. + */ +const char * +GNUNET_short_h2s (const struct GNUNET_CRYPTO_ShortHashCode * hc) +{ + static struct GNUNET_CRYPTO_ShortHashAsciiEncoded ret; + + GNUNET_CRYPTO_short_hash_to_enc (hc, &ret); + return (const char *) &ret; +} + + +/** + * Calculate how many bytes we will need to serialize the given + * records. + * + * @param rd_count number of records in the rd array + * @param rd array of GNUNET_NAMESTORE_RecordData with rd_count elements + * + * @return the required size to serialize * - * @return number of bytes written to destination dest */ size_t -GNUNET_NAMESTORE_records_serialize (char ** dest, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +GNUNET_NAMESTORE_records_get_size (unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { - //size_t len = 0; - struct GNUNET_NAMESTORE_NetworkRecord * nr; - char * d = (*dest); - int c = 0; - int offset; + unsigned int i; + size_t ret; + ret = sizeof (struct NetworkRecord) * rd_count; + for (i=0;i<rd_count;i++) + { + GNUNET_assert ((ret + rd[i].data_size) >= ret); + ret += rd[i].data_size; + } + return ret; +} - size_t total_len = rd_count * sizeof (struct GNUNET_NAMESTORE_NetworkRecord); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Struct size: %u\n", total_len); - /* figure out total len required */ - for (c = 0; c < rd_count; c ++) +/** + * Serialize the given records to the given destination buffer. + * + * @param rd_count number of records in the rd array + * @param rd array of GNUNET_NAMESTORE_RecordData with rd_count elements + * @param dest_size size of the destination array + * @param dest where to write the result + * + * @return the size of serialized records + */ +ssize_t +GNUNET_NAMESTORE_records_serialize (unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + size_t dest_size, + char *dest) +{ + struct NetworkRecord rec; + unsigned int i; + size_t off; + + off = 0; + for (i=0;i<rd_count;i++) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data size record[%i] : %u\n", c, rd[c].data_size); - total_len += rd[c].data_size; + rec.expiration = GNUNET_TIME_absolute_hton (rd[i].expiration); + rec.data_size = htonl ((uint32_t) rd[i].data_size); + rec.record_type = htonl (rd[i].record_type); + rec.flags = htonl (rd[i].flags); + if (off + sizeof (rec) > dest_size) + return -1; + memcpy (&dest[off], &rec, sizeof (rec)); + off += sizeof (rec); + if (off + rd[i].data_size > dest_size) + return -1; + memcpy (&dest[off], rd[i].data, rd[i].data_size); + off += rd[i].data_size; } + return off; +} + +/** + * Compares if two records are equal + * + * @param a record + * @param b record + * + * @return GNUNET_YES or GNUNET_NO + */ +int +GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a, + const struct GNUNET_NAMESTORE_RecordData *b) +{ + if ((a->record_type == b->record_type) && + (a->expiration.abs_value == b->expiration.abs_value) && + (a->data_size == b->data_size) && + (0 == memcmp (a->data, b->data, a->data_size))) + return GNUNET_YES; + else + return GNUNET_NO; +} - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Serializing %i records with total length of %llu\n", rd_count, total_len); - (*dest) = GNUNET_malloc (total_len); - d = (*dest); +/** + * Deserialize the given records to the given destination. + * + * @param len size of the serialized record data + * @param src the serialized record data + * @param rd_count number of records in the rd array + * @param dest where to put the data + * + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +int +GNUNET_NAMESTORE_records_deserialize (size_t len, + const char *src, + unsigned int rd_count, + struct GNUNET_NAMESTORE_RecordData *dest) +{ + struct NetworkRecord rec; + unsigned int i; + size_t off; + + off = 0; + for (i=0;i<rd_count;i++) + { + if (off + sizeof (rec) > len) + return GNUNET_SYSERR; + memcpy (&rec, &src[off], sizeof (rec)); + dest[i].expiration = GNUNET_TIME_absolute_ntoh (rec.expiration); + dest[i].data_size = ntohl ((uint32_t) rec.data_size); + dest[i].record_type = ntohl (rec.record_type); + dest[i].flags = ntohl (rec.flags); + off += sizeof (rec); - /* copy records */ - offset = 0; + if (off + dest[i].data_size > len) + return GNUNET_SYSERR; + dest[i].data = &src[off]; + off += dest[i].data_size; + } + return GNUNET_OK; +} - for (c = 0; c < rd_count; c ++) +/** + * Sign name and records + * + * @param key the private key + * @param expire block expiration + * @param name the name + * @param rd record data + * @param rd_count number of records + * + * @return the signature + */ +struct GNUNET_CRYPTO_RsaSignature * +GNUNET_NAMESTORE_create_signature (const struct GNUNET_CRYPTO_RsaPrivateKey *key, + struct GNUNET_TIME_Absolute expire, + const char *name, + const struct GNUNET_NAMESTORE_RecordData *rd, + unsigned int rd_count) +{ + struct GNUNET_CRYPTO_RsaSignature *sig = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaSignature)); + struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose; + struct GNUNET_TIME_AbsoluteNBO expire_nbo = GNUNET_TIME_absolute_hton(expire); + size_t rd_ser_len; + size_t name_len; + + struct GNUNET_TIME_AbsoluteNBO *expire_tmp; + char * name_tmp; + char * rd_tmp; + int res; + + if (name == NULL) + { + GNUNET_break (0); + GNUNET_free (sig); + return NULL; + } + name_len = strlen (name) + 1; + + rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser); + + sig_purpose = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + rd_ser_len + name_len); + sig_purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)+ rd_ser_len + name_len); + sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); + expire_tmp = (struct GNUNET_TIME_AbsoluteNBO *) &sig_purpose[1]; + name_tmp = (char *) &expire_tmp[1]; + rd_tmp = &name_tmp[name_len]; + memcpy (expire_tmp, &expire_nbo, sizeof (struct GNUNET_TIME_AbsoluteNBO)); + memcpy (name_tmp, name, name_len); + memcpy (rd_tmp, rd_ser, rd_ser_len); + + res = GNUNET_CRYPTO_rsa_sign (key, sig_purpose, sig); + + GNUNET_free (sig_purpose); + + if (GNUNET_OK != res) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Serialized record [%i]: data_size %i\n", c,rd[c].data_size); - - nr = (struct GNUNET_NAMESTORE_NetworkRecord *) &d[offset]; - nr->data_size = htonl (rd[c].data_size); - nr->flags = htonl (rd[c].flags); - nr->record_type = htonl (rd[c].record_type); - nr->expiration = GNUNET_TIME_absolute_hton(rd[c].expiration); - - /*put data here */ - offset += sizeof (struct GNUNET_NAMESTORE_NetworkRecord); - memcpy (&d[offset], rd[c].data, rd[c].data_size); - offset += rd[c].data_size; + GNUNET_break (0); + GNUNET_free (sig); + return NULL; } + return sig; +} - GNUNET_assert (offset == total_len); - return total_len; +/** + * Checks if a name is wellformed + * + * @param name the name to check + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +int +GNUNET_NAMESTORE_check_name (const char * name) +{ + if (name == NULL) + return GNUNET_SYSERR; + if (strlen (name) > 63) + return GNUNET_SYSERR; + return GNUNET_OK; } /** - * Deserialize an array of GNUNET_NAMESTORE_RecordData *rd after transmission - * over the network + * Convert the 'value' of a record to a string. * - * @param source where to read the data to deserialize - * @param rd_count number of elements in array - * @param rd array + * @param type type of the record + * @param data value in binary encoding + * @param data_size number of bytes in data + * @return NULL on error, otherwise human-readable representation of the value + */ +char * +GNUNET_NAMESTORE_value_to_string (uint32_t type, + const void *data, + size_t data_size) +{ + char tmp[INET6_ADDRSTRLEN]; + struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc; + uint16_t mx_pref; + char* result; + char* soa_rname; + char* soa_mname; + uint32_t* soa_data; + uint32_t soa_serial; + uint32_t soa_refresh; + uint32_t soa_retry; + uint32_t soa_expire; + uint32_t soa_min; + + switch (type) + { + case 0: + return NULL; + case GNUNET_DNSPARSER_TYPE_A: + if (data_size != sizeof (struct in_addr)) + return NULL; + if (NULL == inet_ntop (AF_INET, data, tmp, sizeof (tmp))) + return NULL; + return GNUNET_strdup (tmp); + case GNUNET_DNSPARSER_TYPE_NS: + return GNUNET_strndup (data, data_size); + case GNUNET_DNSPARSER_TYPE_CNAME: + return GNUNET_strndup (data, data_size); + case GNUNET_DNSPARSER_TYPE_SOA: + soa_rname = (char*)data; + soa_mname = (char*)data+strlen(soa_rname)+1; + soa_data = (uint32_t*)(soa_mname+strlen(soa_mname)+1); + soa_serial = ntohl(soa_data[0]); + soa_refresh = ntohl(soa_data[1]); + soa_retry = ntohl(soa_data[2]); + soa_expire = ntohl(soa_data[3]); + soa_min = ntohl(soa_data[4]); + if (GNUNET_asprintf(&result, "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu", + soa_rname, soa_mname, + soa_serial, soa_refresh, soa_retry, soa_expire, soa_min)) + return result; + else + return NULL; + case GNUNET_DNSPARSER_TYPE_PTR: + return GNUNET_strndup (data, data_size); + case GNUNET_DNSPARSER_TYPE_MX: + mx_pref = ntohs(*((uint16_t*)data)); + if (GNUNET_asprintf(&result, "%hu,%s", mx_pref, data+sizeof(uint16_t)) + != 0) + return result; + else + return NULL; + case GNUNET_DNSPARSER_TYPE_TXT: + return GNUNET_strndup (data, data_size); + case GNUNET_DNSPARSER_TYPE_AAAA: + if (data_size != sizeof (struct in6_addr)) + return NULL; + if (NULL == inet_ntop (AF_INET6, data, tmp, sizeof (tmp))) + return NULL; + return GNUNET_strdup (tmp); + case GNUNET_NAMESTORE_TYPE_PKEY: + if (data_size != sizeof (struct GNUNET_CRYPTO_ShortHashCode)) + return NULL; + GNUNET_CRYPTO_short_hash_to_enc (data, + &enc); + return GNUNET_strdup ((const char*) enc.short_encoding); + case GNUNET_NAMESTORE_TYPE_PSEU: + return GNUNET_strndup (data, data_size); + case GNUNET_NAMESTORE_TYPE_LEHO: + return GNUNET_strndup (data, data_size); + default: + GNUNET_break (0); + } + GNUNET_break (0); // not implemented + return NULL; +} + + +/** + * Convert human-readable version of a 'value' of a record to the binary + * representation. * - * @return number of elements deserialized + * @param type type of the record + * @param s human-readable string + * @param data set to value in binary encoding (will be allocated) + * @param data_size set to number of bytes in data + * @return GNUNET_OK on success */ int -GNUNET_NAMESTORE_records_deserialize ( struct GNUNET_NAMESTORE_RecordData **dest, char *src, size_t len) +GNUNET_NAMESTORE_string_to_value (uint32_t type, + const char *s, + void **data, + size_t *data_size) { - struct GNUNET_NAMESTORE_NetworkRecord * nr; - struct GNUNET_NAMESTORE_RecordData *d = (*dest); - int elements; - size_t offset; - uint32_t data_size; - int c; - - offset = 0; - elements = 0; - while (offset < len) + struct in_addr value_a; + struct in6_addr value_aaaa; + struct GNUNET_CRYPTO_ShortHashCode pkey; + uint16_t mx_pref; + uint16_t mx_pref_n; + uint32_t soa_data[5]; + char result[253]; + char soa_rname[63]; + char soa_mname[63]; + uint32_t soa_serial; + uint32_t soa_refresh; + uint32_t soa_retry; + uint32_t soa_expire; + uint32_t soa_min; + + switch (type) { - nr = (struct GNUNET_NAMESTORE_NetworkRecord *) &src[offset]; - offset += sizeof (struct GNUNET_NAMESTORE_NetworkRecord); + case 0: + return GNUNET_SYSERR; + case GNUNET_DNSPARSER_TYPE_A: + if (1 != inet_pton (AF_INET, s, &value_a)) + return GNUNET_SYSERR; + *data = GNUNET_malloc (sizeof (struct in_addr)); + memcpy (*data, &value_a, sizeof (value_a)); + *data_size = sizeof (value_a); + return GNUNET_OK; + case GNUNET_DNSPARSER_TYPE_NS: + *data = GNUNET_strdup (s); + *data_size = strlen (s); + return GNUNET_OK; + case GNUNET_DNSPARSER_TYPE_CNAME: + *data = GNUNET_strdup (s); + *data_size = strlen (s); + return GNUNET_OK; + case GNUNET_DNSPARSER_TYPE_SOA: + + if (SSCANF(s, "rname=%s mname=%s %u,%u,%u,%u,%u", + soa_rname, soa_mname, + &soa_serial, &soa_refresh, &soa_retry, &soa_expire, &soa_min) + != 7) + return GNUNET_SYSERR; + + *data_size = sizeof (soa_data)+strlen(soa_rname)+strlen(soa_mname)+2; + *data = GNUNET_malloc (*data_size); + soa_data[0] = htonl(soa_serial); + soa_data[1] = htonl(soa_refresh); + soa_data[2] = htonl(soa_retry); + soa_data[3] = htonl(soa_expire); + soa_data[4] = htonl(soa_min); + strcpy(*data, soa_rname); + strcpy(*data+strlen(*data)+1, soa_mname); + memcpy(*data+strlen(*data)+1+strlen(soa_mname)+1, + soa_data, sizeof(soa_data)); + return GNUNET_OK; - data_size = ntohl (nr->data_size); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Datasize record[%i]: %u\n", elements, data_size); - offset += data_size; - elements ++; + case GNUNET_DNSPARSER_TYPE_PTR: + *data = GNUNET_strdup (s); + *data_size = strlen (s); + return GNUNET_OK; + case GNUNET_DNSPARSER_TYPE_MX: + if (SSCANF(s, "%hu,%s", &mx_pref, result) != 2) + return GNUNET_SYSERR; + *data_size = sizeof (uint16_t)+strlen(result)+1; + *data = GNUNET_malloc (*data_size); + mx_pref_n = htons(mx_pref); + memcpy(*data, &mx_pref_n, sizeof (uint16_t)); + strcpy((*data)+sizeof (uint16_t), result); + return GNUNET_OK; + case GNUNET_DNSPARSER_TYPE_TXT: + *data = GNUNET_strdup (s); + *data_size = strlen (s); + return GNUNET_OK; + case GNUNET_DNSPARSER_TYPE_AAAA: + if (1 != inet_pton (AF_INET6, s, &value_aaaa)) + return GNUNET_SYSERR; + *data = GNUNET_malloc (sizeof (struct in6_addr)); + *data_size = sizeof (struct in6_addr); + memcpy (*data, &value_aaaa, sizeof (value_aaaa)); + return GNUNET_OK; + case GNUNET_NAMESTORE_TYPE_PKEY: + if (GNUNET_OK != + GNUNET_CRYPTO_short_hash_from_string (s, &pkey)) + return GNUNET_SYSERR; + *data = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + memcpy (*data, &pkey, sizeof (pkey)); + *data_size = sizeof (struct GNUNET_CRYPTO_ShortHashCode); + return GNUNET_OK; + case GNUNET_NAMESTORE_TYPE_PSEU: + *data = GNUNET_strdup (s); + *data_size = strlen (s); + return GNUNET_OK; + case GNUNET_NAMESTORE_TYPE_LEHO: + *data = GNUNET_strdup (s); + *data_size = strlen (s); + return GNUNET_OK; + default: + GNUNET_break (0); } + return GNUNET_SYSERR; +} - GNUNET_assert (len == offset); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deserializing %i records with total length of %u\n", elements, len); - (*dest) = GNUNET_malloc (elements * sizeof (struct GNUNET_NAMESTORE_RecordData)); - d = (*dest); +static struct { + const char *name; + uint32_t number; +} name_map[] = { + { "A", GNUNET_DNSPARSER_TYPE_A }, + { "NS", GNUNET_DNSPARSER_TYPE_NS }, + { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME }, + { "SOA", GNUNET_DNSPARSER_TYPE_SOA }, + { "PTR", GNUNET_DNSPARSER_TYPE_PTR }, + { "MX", GNUNET_DNSPARSER_TYPE_MX }, + { "TXT", GNUNET_DNSPARSER_TYPE_TXT }, + { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA }, + { "PKEY", GNUNET_NAMESTORE_TYPE_PKEY }, + { "PSEU", GNUNET_NAMESTORE_TYPE_PSEU }, + { "LEHO", GNUNET_NAMESTORE_TYPE_LEHO }, + { NULL, UINT32_MAX } +}; - offset = 0; - for (c = 0; c < elements; c++) - { - nr = (struct GNUNET_NAMESTORE_NetworkRecord *) &src[offset]; - d[c].expiration = GNUNET_TIME_absolute_ntoh(nr->expiration); - d[c].record_type = ntohl (nr->record_type); - d[c].flags = ntohl (nr->flags); - d[c].data_size = ntohl (nr->data_size); - d[c].data = GNUNET_malloc (d[c].data_size); - GNUNET_assert (d[c].data != NULL); - - offset += sizeof (struct GNUNET_NAMESTORE_NetworkRecord); - memcpy((char *) d[c].data, &src[offset], d[c].data_size); - - offset += d[c].data_size; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deserialized record[%i] /w data_size %i\n", c, d[c].data_size); - } - GNUNET_assert(offset == len); - return elements; +/** + * Convert a type name (i.e. "AAAA") to the corresponding number. + * + * @param typename name to convert + * @return corresponding number, UINT32_MAX on error + */ +uint32_t +GNUNET_NAMESTORE_typename_to_number (const char *typename) +{ + unsigned int i; + + i=0; + while ( (name_map[i].name != NULL) && + (0 != strcasecmp (typename, name_map[i].name)) ) + i++; + return name_map[i].number; +} + + +/** + * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A") + * + * @param type number of a type to convert + * @return corresponding typestring, NULL on error + */ +const char * +GNUNET_NAMESTORE_number_to_typename (uint32_t type) +{ + unsigned int i; + + i=0; + while ( (name_map[i].name != NULL) && + (type != name_map[i].number) ) + i++; + return name_map[i].name; } -/* end of namestore_api.c */ + + +/* end of namestore_common.c */ diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c index c297216..f685887 100644 --- a/src/namestore/plugin_namestore_sqlite.c +++ b/src/namestore/plugin_namestore_sqlite.c @@ -26,6 +26,8 @@ #include "platform.h" #include "gnunet_namestore_plugin.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" #include <sqlite3.h> /** @@ -100,39 +102,15 @@ struct Plugin sqlite3_stmt *iterate_records; /** - * Precompiled SQL for delete zone + * Precompiled SQL to get the name for a given zone-value. */ - sqlite3_stmt *delete_zone; - -}; - - -/** - * Internal format of a record in the BLOB in the database. - */ -struct DbRecord -{ + sqlite3_stmt *zone_to_name; /** - * Expiration time for the DNS record. - */ - struct GNUNET_TIME_AbsoluteNBO expiration; - - /** - * Number of bytes in 'data', network byte order. - */ - uint32_t data_size; - - /** - * Type of the GNS/DNS record, network byte order. + * Precompiled SQL for delete zone */ - uint32_t record_type; + sqlite3_stmt *delete_zone; - /** - * Flags for the record, network byte order. - */ - uint32_t flags; - }; @@ -169,19 +147,22 @@ create_indices (sqlite3 * dbh) { /* create indices */ if ( (SQLITE_OK != - sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_name_rv ON ns090records (zone_hash,record_name_hash,rvalue)", + sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_name_rv ON ns091records (zone_hash,record_name_hash,rvalue)", + NULL, NULL, NULL)) || + (SQLITE_OK != + sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_delegation ON ns091records (zone_hash,zone_delegation)", NULL, NULL, NULL)) || (SQLITE_OK != - sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_rv ON ns090records (zone_hash,rvalue)", + sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_rv ON ns091records (zone_hash,rvalue)", NULL, NULL, NULL)) || (SQLITE_OK != - sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone ON ns090records (zone_hash)", + sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone ON ns091records (zone_hash)", NULL, NULL, NULL)) || (SQLITE_OK != - sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_name_rv ON ns090records (record_name_hash,rvalue)", + sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_name_rv ON ns091records (record_name_hash,rvalue)", NULL, NULL, NULL)) || (SQLITE_OK != - sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_rv ON ns090records (rvalue)", + sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_rv ON ns091records (rvalue)", NULL, NULL, NULL)) ) LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to create indices: %s\n", sqlite3_errmsg (dbh)); @@ -280,13 +261,14 @@ database_setup (struct Plugin *plugin) /* Create tables */ CHECK (SQLITE_OK == sq_prepare (plugin->dbh, - "SELECT 1 FROM sqlite_master WHERE tbl_name = 'ns090records'", + "SELECT 1 FROM sqlite_master WHERE tbl_name = 'ns091records'", &stmt)); if ((sqlite3_step (stmt) == SQLITE_DONE) && (sqlite3_exec (plugin->dbh, - "CREATE TABLE ns090records (" + "CREATE TABLE ns091records (" " zone_key BLOB NOT NULL DEFAULT ''," + " zone_delegation BLOB NOT NULL DEFAULT ''," " zone_hash BLOB NOT NULL DEFAULT ''," " record_count INT NOT NULL DEFAULT 0," " record_data BLOB NOT NULL DEFAULT ''," @@ -309,36 +291,41 @@ database_setup (struct Plugin *plugin) #define ALL "zone_key, record_name, record_count, record_data, block_expiration_time, signature" if ((sq_prepare (plugin->dbh, - "INSERT INTO ns090records (" ALL ", zone_hash, record_name_hash, rvalue) VALUES " - "(?, ?, ?, ?, ?, ?, ?, ?, ?)", + "INSERT INTO ns091records (" ALL ", zone_delegation, zone_hash, record_name_hash, rvalue) VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", &plugin->put_records) != SQLITE_OK) || (sq_prepare (plugin->dbh, - "DELETE FROM ns090records WHERE zone_hash=? AND record_name_hash=?", + "DELETE FROM ns091records WHERE zone_hash=? AND record_name_hash=?", &plugin->remove_records) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT " ALL - " FROM ns090records WHERE zone_hash=? AND record_name_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?", + " FROM ns091records WHERE zone_hash=? AND record_name_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?", &plugin->iterate_records) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT " ALL - " FROM ns090records WHERE zone_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?", + " FROM ns091records WHERE zone_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?", &plugin->iterate_by_zone) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT " ALL - " FROM ns090records WHERE record_name_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?", + " FROM ns091records WHERE record_name_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?", &plugin->iterate_by_name) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT " ALL - " FROM ns090records ORDER BY rvalue LIMIT 1 OFFSET ?", + " FROM ns091records ORDER BY rvalue LIMIT 1 OFFSET ?", &plugin->iterate_all) != SQLITE_OK) || (sq_prepare + (plugin->dbh, + "SELECT " ALL + " FROM ns091records WHERE zone_hash=? AND zone_delegation=?", + &plugin->zone_to_name) != SQLITE_OK) || + (sq_prepare (plugin->dbh, - "DELETE FROM ns090records WHERE zone_hash=?", + "DELETE FROM ns091records WHERE zone_hash=?", &plugin->delete_zone) != SQLITE_OK) ) { LOG_SQLITE (plugin,GNUNET_ERROR_TYPE_ERROR, "precompiling"); @@ -366,12 +353,14 @@ database_shutdown (struct Plugin *plugin) sqlite3_finalize (plugin->remove_records); if (NULL != plugin->iterate_records) sqlite3_finalize (plugin->iterate_records); - if (NULL != plugin->iterate_records) + if (NULL != plugin->iterate_by_zone) sqlite3_finalize (plugin->iterate_by_zone); - if (NULL != plugin->iterate_records) + if (NULL != plugin->iterate_by_name) sqlite3_finalize (plugin->iterate_by_name); - if (NULL != plugin->iterate_records) + if (NULL != plugin->iterate_all) sqlite3_finalize (plugin->iterate_all); + if (NULL != plugin->zone_to_name) + sqlite3_finalize (plugin->zone_to_name); if (NULL != plugin->delete_zone) sqlite3_finalize (plugin->delete_zone); result = sqlite3_close (plugin->dbh); @@ -409,19 +398,18 @@ database_shutdown (struct Plugin *plugin) */ static int namestore_sqlite_remove_records (void *cls, - const GNUNET_HashCode *zone, + const struct GNUNET_CRYPTO_ShortHashCode *zone, const char *name) { struct Plugin *plugin = cls; - GNUNET_HashCode nh; + struct GNUNET_CRYPTO_ShortHashCode nh; size_t name_len; int n; - name_len = strlen (name); - GNUNET_CRYPTO_hash (name, name_len, &nh); + GNUNET_CRYPTO_short_hash (name, name_len, &nh); - if ((SQLITE_OK != sqlite3_bind_blob (plugin->remove_records, 1, zone, sizeof (GNUNET_HashCode), SQLITE_STATIC)) || - (SQLITE_OK != sqlite3_bind_blob (plugin->remove_records, 2, &nh, sizeof (GNUNET_HashCode), SQLITE_STATIC))) + if ((SQLITE_OK != sqlite3_bind_blob (plugin->remove_records, 1, zone, sizeof (struct GNUNET_CRYPTO_ShortHashCode), SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_blob (plugin->remove_records, 2, &nh, sizeof (struct GNUNET_CRYPTO_ShortHashCode), SQLITE_STATIC))) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); @@ -478,22 +466,30 @@ namestore_sqlite_put_records (void *cls, { struct Plugin *plugin = cls; int n; - GNUNET_HashCode zone; - GNUNET_HashCode nh; + struct GNUNET_CRYPTO_ShortHashCode zone; + struct GNUNET_CRYPTO_ShortHashCode zone_delegation; + struct GNUNET_CRYPTO_ShortHashCode nh; size_t name_len; uint64_t rvalue; size_t data_size; - size_t off; unsigned int i; - GNUNET_CRYPTO_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone); + GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone); (void) namestore_sqlite_remove_records (plugin, &zone, name); name_len = strlen (name); - GNUNET_CRYPTO_hash (name, name_len, &nh); + GNUNET_CRYPTO_short_hash (name, name_len, &nh); + memset (&zone_delegation, 0, sizeof (zone_delegation)); + for (i=0;i<rd_count;i++) + if (rd[i].record_type == GNUNET_NAMESTORE_TYPE_PKEY) + { + GNUNET_assert (sizeof (struct GNUNET_CRYPTO_ShortHashCode) == rd[i].data_size); + memcpy (&zone_delegation, + rd[i].data, + sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + break; + } rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); - data_size = rd_count * sizeof (struct DbRecord); - for (i=0;i<rd_count;i++) - data_size += rd[i].data_size; + data_size = GNUNET_NAMESTORE_records_get_size (rd_count, rd); if (data_size > 64 * 65536) { GNUNET_break (0); @@ -501,20 +497,12 @@ namestore_sqlite_put_records (void *cls, } { char data[data_size]; - struct DbRecord *rec; - - rec = (struct DbRecord *) data; - off = rd_count * sizeof (struct DbRecord); - for (i=0;i<rd_count;i++) + + if (data_size != GNUNET_NAMESTORE_records_serialize (rd_count, rd, + data_size, data)) { - rec[i].expiration = GNUNET_TIME_absolute_hton (rd[i].expiration); - rec[i].data_size = htonl ((uint32_t) rd[i].data_size); - rec[i].record_type = htonl (rd[i].record_type); - rec[i].flags = htonl (rd[i].flags); - memcpy (&data[off], - rd[i].data, - rd[i].data_size); - off += rd[i].data_size; + GNUNET_break (0); + return GNUNET_SYSERR; } if ((SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 1, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_text (plugin->put_records, 2, name, -1, SQLITE_STATIC)) || @@ -522,9 +510,10 @@ namestore_sqlite_put_records (void *cls, (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 4, data, data_size, SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_int64 (plugin->put_records, 5, expire.abs_value)) || (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 6, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature), SQLITE_STATIC)) || - (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 7, &zone, sizeof (GNUNET_HashCode), SQLITE_STATIC)) || - (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 8, &nh, sizeof (GNUNET_HashCode), SQLITE_STATIC)) || - (SQLITE_OK != sqlite3_bind_int64 (plugin->put_records, 9, rvalue)) ) + (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 7, &zone_delegation, sizeof (struct GNUNET_CRYPTO_ShortHashCode), SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 8, &zone, sizeof (struct GNUNET_CRYPTO_ShortHashCode), SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 9, &nh, sizeof (struct GNUNET_CRYPTO_ShortHashCode), SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_int64 (plugin->put_records, 10, rvalue)) ) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, @@ -556,6 +545,83 @@ namestore_sqlite_put_records (void *cls, return GNUNET_SYSERR; } } + + +/** + * The given 'sqlite' statement has been prepared to be run. + * It will return a record which should be given to the iterator. + * Runs the statement and parses the returned record. + * + * @param plugin plugin context + * @param stmt to run (and then clean up) + * @param iter iterator to call with the result + * @param iter_cls closure for 'iter' + * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error + */ +static int +get_record_and_call_iterator (struct Plugin *plugin, + sqlite3_stmt *stmt, + GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) +{ + int ret; + int sret; + unsigned int record_count; + size_t data_size; + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key; + const struct GNUNET_CRYPTO_RsaSignature *sig; + struct GNUNET_TIME_Absolute expiration; + const char *data; + const char *name; + + ret = GNUNET_NO; + if (SQLITE_ROW == (sret = sqlite3_step (stmt))) + { + ret = GNUNET_YES; + zone_key = sqlite3_column_blob (stmt, 0); + name = (const char*) sqlite3_column_text (stmt, 1); + record_count = sqlite3_column_int (stmt, 2); + data_size = sqlite3_column_bytes (stmt, 3); + data = sqlite3_column_blob (stmt, 3); + expiration.abs_value = (uint64_t) sqlite3_column_int64 (stmt, 4); + sig = sqlite3_column_blob (stmt, 5); + + if ( (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) != sqlite3_column_bytes (stmt, 0)) || + (sizeof (struct GNUNET_CRYPTO_RsaSignature) != sqlite3_column_bytes (stmt, 5)) ) + { + GNUNET_break (0); + ret = GNUNET_SYSERR; + } + else + { + struct GNUNET_NAMESTORE_RecordData rd[record_count]; + + if (GNUNET_OK != + GNUNET_NAMESTORE_records_deserialize (data_size, data, + record_count, rd)) + { + GNUNET_break (0); + ret = GNUNET_SYSERR; + record_count = 0; + } + else + { + iter (iter_cls, zone_key, expiration, name, + record_count, rd, sig); + } + } + } + else + { + if (SQLITE_DONE != sret) + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step"); + iter (iter_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, NULL, 0, NULL, NULL); + } + if (SQLITE_OK != sqlite3_reset (stmt)) + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + return ret; +} /** @@ -564,7 +630,7 @@ namestore_sqlite_put_records (void *cls, * * @param cls closure (internal context for the plugin) * @param zone hash of public key of the zone, NULL to iterate over all zones - * @param name_hash hash of name, NULL to iterate over all records of the zone + * @param name name as string, NULL to iterate over all records of the zone * @param offset offset in the list of all matching records * @param iter function to call with the result * @param iter_cls closure for iter @@ -572,32 +638,37 @@ namestore_sqlite_put_records (void *cls, */ static int namestore_sqlite_iterate_records (void *cls, - const GNUNET_HashCode *zone, - const GNUNET_HashCode *name_hash, + const struct GNUNET_CRYPTO_ShortHashCode *zone, + const char *name, uint64_t offset, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; + struct GNUNET_CRYPTO_ShortHashCode name_hase; unsigned int boff; - int ret; - int sret; if (NULL == zone) - if (NULL == name_hash) + if (NULL == name) stmt = plugin->iterate_all; else + { + GNUNET_CRYPTO_short_hash (name, strlen(name), &name_hase); stmt = plugin->iterate_by_name; + } else - if (NULL == name_hash) + if (NULL == name) stmt = plugin->iterate_by_zone; else + { + GNUNET_CRYPTO_short_hash (name, strlen(name), &name_hase); stmt = plugin->iterate_records; + } boff = 0; if ( (NULL != zone) && (SQLITE_OK != sqlite3_bind_blob (stmt, ++boff, - zone, sizeof (GNUNET_HashCode), + zone, sizeof (struct GNUNET_CRYPTO_ShortHashCode), SQLITE_STATIC)) ) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, @@ -608,11 +679,12 @@ namestore_sqlite_iterate_records (void *cls, "sqlite3_reset"); return GNUNET_SYSERR; } - if ( (NULL != name_hash) && + if ( (NULL != name) && (SQLITE_OK != sqlite3_bind_blob (stmt, ++boff, - name_hash, sizeof (GNUNET_HashCode), + &name_hase, sizeof (struct GNUNET_CRYPTO_ShortHashCode), SQLITE_STATIC)) ) { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ITERATE NAME HASH: `%8s'", GNUNET_short_h2s(&name_hase)); LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (stmt)) @@ -633,72 +705,49 @@ namestore_sqlite_iterate_records (void *cls, "sqlite3_reset"); return GNUNET_SYSERR; } - ret = GNUNET_NO; - if (SQLITE_ROW == (sret = sqlite3_step (stmt))) - { - unsigned int record_count; - size_t data_size; - const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key; - const struct GNUNET_CRYPTO_RsaSignature *sig; - struct GNUNET_TIME_Absolute expiration; - const char *data; - const char *name; - - ret = GNUNET_YES; - zone_key = sqlite3_column_blob (stmt, 0); - name = (const char*) sqlite3_column_text (stmt, 1); - record_count = sqlite3_column_int (stmt, 2); - data_size = sqlite3_column_bytes (stmt, 3); - data = sqlite3_column_blob (stmt, 3); - expiration.abs_value = (uint64_t) sqlite3_column_int64 (stmt, 4); - sig = sqlite3_column_blob (stmt, 5); - if ( (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) != sqlite3_column_bytes (stmt, 0)) || - (sizeof (struct GNUNET_CRYPTO_RsaSignature) != sqlite3_column_bytes (stmt, 5)) || - (sizeof (struct DbRecord) * record_count > data_size) ) - { - GNUNET_break (0); - ret = GNUNET_SYSERR; - } - else - { - const struct DbRecord *db = (const struct DbRecord*) data; - struct GNUNET_NAMESTORE_RecordData rd[record_count]; - unsigned int i; - size_t off; + return get_record_and_call_iterator (plugin, stmt, iter, iter_cls); +} - off = record_count * sizeof (struct DbRecord); - for (i=0;i<record_count;i++) - { - if (off + ntohl (db[i].data_size) > data_size) - { - GNUNET_break (0); - ret = GNUNET_SYSERR; - record_count = i; - break; - } - rd[i].expiration = GNUNET_TIME_absolute_ntoh (db[i].expiration); - rd[i].data_size = ntohl (db[i].data_size); - rd[i].data = &data[off]; - rd[i].record_type = ntohl (db[i].record_type); - rd[i].flags = ntohl (db[i].flags); - off += rd[i].data_size; - } - iter (iter_cls, zone_key, expiration, name, - record_count, rd, sig); - } - } - else + +/** + * Look for an existing PKEY delegation record for a given public key. + * Returns at most one result to the iterator. + * + * @param cls closure (internal context for the plugin) + * @param zone hash of public key of the zone to look up in, never NULL + * @param value_zone hash of the public key of the target zone (value), never NULL + * @param iter function to call with the result + * @param iter_cls closure for iter + * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error + */ +static int +namestore_sqlite_zone_to_name (void *cls, + const struct GNUNET_CRYPTO_ShortHashCode *zone, + const struct GNUNET_CRYPTO_ShortHashCode *value_zone, + GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) +{ + struct Plugin *plugin = cls; + sqlite3_stmt *stmt; + + stmt = plugin->zone_to_name; + if ( (SQLITE_OK != sqlite3_bind_blob (stmt, 1, + zone, sizeof (struct GNUNET_CRYPTO_ShortHashCode), + SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_blob (stmt, 2, + value_zone, sizeof (struct GNUNET_CRYPTO_ShortHashCode), + SQLITE_STATIC)) ) { - if (SQLITE_DONE != sret) - LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step"); - iter (iter_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, NULL, 0, NULL, NULL); - } - if (SQLITE_OK != sqlite3_reset (stmt)) - LOG_SQLITE (plugin, - GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, - "sqlite3_reset"); - return ret; + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_bind_XXXX"); + if (SQLITE_OK != sqlite3_reset (stmt)) + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + return GNUNET_SYSERR; + } + + return get_record_and_call_iterator (plugin, stmt, iter, iter_cls); } @@ -710,13 +759,13 @@ namestore_sqlite_iterate_records (void *cls, */ static void namestore_sqlite_delete_zone (void *cls, - const GNUNET_HashCode *zone) + const struct GNUNET_CRYPTO_ShortHashCode *zone) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->delete_zone; int n; - if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, zone, sizeof (GNUNET_HashCode), SQLITE_STATIC)) + if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, zone, sizeof (struct GNUNET_CRYPTO_ShortHashCode), SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); @@ -774,6 +823,7 @@ libgnunet_plugin_namestore_sqlite_init (void *cls) api->put_records = &namestore_sqlite_put_records; api->remove_records = &namestore_sqlite_remove_records; api->iterate_records = &namestore_sqlite_iterate_records; + api->zone_to_name = &namestore_sqlite_zone_to_name; api->delete_zone = &namestore_sqlite_delete_zone; LOG (GNUNET_ERROR_TYPE_INFO, _("Sqlite database running\n")); diff --git a/src/namestore/test_hostkey b/src/namestore/test_hostkey Binary files differnew file mode 100644 index 0000000..2ffb55f --- /dev/null +++ b/src/namestore/test_hostkey diff --git a/src/namestore/test_namestore_api.c b/src/namestore/test_namestore_api.c index ebd8be3..039f1b9 100644 --- a/src/namestore/test_namestore_api.c +++ b/src/namestore/test_namestore_api.c @@ -36,7 +36,7 @@ static struct GNUNET_OS_Process *arm; static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; -static GNUNET_HashCode zone; +static struct GNUNET_CRYPTO_ShortHashCode zone; static int res; @@ -66,7 +66,7 @@ stop_arm () if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); GNUNET_OS_process_wait (arm); - GNUNET_OS_process_close (arm); + GNUNET_OS_process_destroy (arm); arm = NULL; } } @@ -142,20 +142,45 @@ void put_cont (void *cls, int32_t success, const char *emsg) GNUNET_NAMESTORE_lookup_record (nsh, &zone, name, 0, &name_lookup_proc, NULL); } +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } + +} + static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { + delete_existing_db(cfg); endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,endbadly, NULL); - privkey = GNUNET_CRYPTO_rsa_key_create_from_file("hostkey"); + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); - GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &zone); + GNUNET_CRYPTO_short_hash (&pubkey, sizeof (pubkey), &zone); struct GNUNET_CRYPTO_RsaSignature signature; + memset (&signature, '\0', sizeof (signature)); struct GNUNET_NAMESTORE_RecordData rd; rd.expiration = GNUNET_TIME_absolute_get(); @@ -172,7 +197,7 @@ run (void *cls, char *const *args, const char *cfgfile, GNUNET_break (NULL != nsh); GNUNET_NAMESTORE_record_put (nsh, &pubkey, name, - GNUNET_TIME_absolute_get_forever(), + GNUNET_TIME_UNIT_FOREVER_ABS, 1, &rd, &signature, put_cont, name); GNUNET_free ((void *)rd.data); diff --git a/src/namestore/test_namestore_api.conf b/src/namestore/test_namestore_api.conf index 1b83e8f..33e07a4 100644 --- a/src/namestore/test_namestore_api.conf +++ b/src/namestore/test_namestore_api.conf @@ -4,12 +4,12 @@ DEFAULTSERVICES = namestore UNIXPATH = /tmp/gnunet-p1-service-arm.sock [namestore] -#PREFIX = valgrind --leak-check=full +#PREFIX = valgrind --leak-check=full --track-origins=yes AUTOSTART = YES UNIXPATH = /tmp/gnunet-service-namestore.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES -# PORT = 2099 +PORT = 2099 HOSTNAME = localhost HOME = $SERVICEHOME CONFIG = $DEFAULTCONFIG @@ -17,9 +17,10 @@ BINARY = gnunet-service-namestore ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; DATABASE = sqlite +ZONEFILE_DIRECTORY = zonefiles [namestore-sqlite] -FILENAME = $SERVICEHOME/namestore/sqlite.db +FILENAME = $SERVICEHOME/namestore/sqlite_test.db [namestore-postgres] CONFIG = connect_timeout=10; dbname=gnunet diff --git a/src/namestore/test_namestore_api_create.c b/src/namestore/test_namestore_api_create.c new file mode 100644 index 0000000..131c934 --- /dev/null +++ b/src/namestore/test_namestore_api_create.c @@ -0,0 +1,478 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file namestore/test_namestore_api.c + * @brief testcase for namestore_api.c + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" +#include "gnunet_signatures.h" + +#define VERBOSE GNUNET_NO + +#define RECORDS 1 +#define TEST_RECORD_TYPE 1234 +#define TEST_RECORD_DATALEN 123 +#define TEST_RECORD_DATA 'a' + +#define TEST_CREATE_RECORD_TYPE 4321 +#define TEST_CREATE_RECORD_DATALEN 255 +#define TEST_CREATE_RECORD_DATA 'b' + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; +struct GNUNET_CRYPTO_RsaSignature *s_signature; +struct GNUNET_CRYPTO_RsaSignature *s_signature_updated; +static struct GNUNET_CRYPTO_ShortHashCode s_zone; +struct GNUNET_NAMESTORE_RecordData *s_first_record; +struct GNUNET_NAMESTORE_RecordData *s_second_record; +static char *s_name; + + + +static int res; + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_destroy (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (NULL != arm) + stop_arm(); + + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + GNUNET_free ((void *) s_first_record->data); + GNUNET_free (s_first_record); + GNUNET_free_non_null (s_second_record); + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (NULL != arm) + stop_arm(); +} + +void name_lookup_second_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *n, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + static int found = GNUNET_NO; + int failed = GNUNET_NO; + int c; + + if (n != NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking returned results\n"); + if (0 != memcmp (zone_key, &pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (0 != strcmp(n, s_name)) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (2 != rd_count) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + for (c = 0; c < rd_count; c++) + { + if ((GNUNET_NO == GNUNET_NAMESTORE_records_cmp(&rd[c], s_first_record)) && + (GNUNET_NO == GNUNET_NAMESTORE_records_cmp(&rd[c], s_second_record))) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + } + + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(zone_key, expire, n, rd_count, rd, signature)) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(&pubkey, expire, n, rd_count, rd, signature)) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + struct GNUNET_NAMESTORE_RecordData rd_new[2]; + rd_new[0] = *s_first_record; + rd_new[1] = *s_second_record; + s_signature_updated = GNUNET_NAMESTORE_create_signature(privkey, expire, s_name, rd_new, 2); + + if (0 != memcmp (s_signature_updated, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature))) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + found = GNUNET_YES; + if (failed == GNUNET_NO) + res = 0; + else + res = 1; + } + else + { + if (found != GNUNET_YES) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to lookup records for name `%s'\n", s_name); + res = 1; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Lookup done for name %s'\n", s_name); + } + GNUNET_SCHEDULER_add_now(&end, NULL); +} + + +void +create_second_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Create second record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + if (success == GNUNET_OK) + { + res = 0; + GNUNET_NAMESTORE_lookup_record (nsh, &s_zone, name, 0, &name_lookup_second_proc, name); + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } + +} + +void name_lookup_initial_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *n, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + char * name = cls; + static int found = GNUNET_NO; + int failed = GNUNET_NO; + int c; + + if (n != NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking returned results\n"); + if (0 != memcmp (zone_key, &pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (0 != strcmp(n, s_name)) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (RECORDS != rd_count) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + for (c = 0; c < RECORDS; c++) + { + if (GNUNET_NO == GNUNET_NAMESTORE_records_cmp(&rd[c], &s_first_record[c])) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + } + + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(&pubkey, expire,n, rd_count, rd, signature)) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (0 != memcmp (s_signature, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature))) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + found = GNUNET_YES; + if (failed == GNUNET_NO) + res = 0; + else + res = 1; + + /* create a second record */ + s_second_record = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_RecordData) + TEST_CREATE_RECORD_DATALEN); + s_second_record->expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + s_second_record->record_type = TEST_CREATE_RECORD_TYPE; + s_second_record->flags = GNUNET_NAMESTORE_RF_AUTHORITY; + s_second_record->data = &s_second_record[1]; + s_second_record->data_size = TEST_CREATE_RECORD_DATALEN; + memset ((char *) s_second_record->data, TEST_CREATE_RECORD_DATA, TEST_CREATE_RECORD_DATALEN); + + GNUNET_NAMESTORE_record_create (nsh, privkey, name, s_second_record, &create_second_cont, name); + + } + else + { + if (found != GNUNET_YES) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to lookup records for name `%s'\n", s_name); + res = 1; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Lookup done for name %s'\n", s_name); + GNUNET_SCHEDULER_add_now (&end, NULL); + } +} + +void +create_first_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Create record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + if (success == GNUNET_OK) + { + res = 0; + /* check if record was created correct */ + GNUNET_NAMESTORE_lookup_record (nsh, &s_zone, name, 0, &name_lookup_initial_proc, name); + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } + +} + +void +put_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + if (success == GNUNET_OK) + { + + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } +} + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + int c; + struct GNUNET_NAMESTORE_RecordData * rd; + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + for (c = 0; c < count; c++) + { + rd[c].expiration = GNUNET_TIME_absolute_get(); + rd[c].record_type = TEST_RECORD_TYPE; + rd[c].data_size = TEST_RECORD_DATALEN; + rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); + memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); + } + + return rd; +} + +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } + +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + delete_existing_db(cfg); + + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,endbadly, NULL); + size_t rd_ser_len; + + /* load privat key */ + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + /* get public key */ + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + + /* create record */ + s_name = "dummy.dummy.gnunet"; + s_first_record = create_record (1); + + rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, s_first_record); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(1, s_first_record, rd_ser_len, rd_ser); + + s_signature = GNUNET_NAMESTORE_create_signature(privkey, s_first_record->expiration, s_name, s_first_record, 1); + + /* create random zone hash */ + GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &s_zone); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name: `%s' Zone: `%s' \n", s_name, GNUNET_short_h2s (&s_zone)); + + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + GNUNET_break (s_first_record != NULL); + GNUNET_break (s_name != NULL); + + /* create initial record */ + GNUNET_NAMESTORE_record_create (nsh, privkey, s_name, s_first_record, &create_first_cont, s_name); +} + +static int +check () +{ + static char *const argv[] = { "test-namestore-api", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-namestore-api", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + GNUNET_free (s_signature); + return ret; +} + +/* end of test_namestore_api.c */ diff --git a/src/namestore/test_namestore_api_create_update.c b/src/namestore/test_namestore_api_create_update.c new file mode 100644 index 0000000..93570e4 --- /dev/null +++ b/src/namestore/test_namestore_api_create_update.c @@ -0,0 +1,517 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file namestore/test_namestore_api.c + * @brief testcase for namestore_api.c for updating an existing record + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" +#include "gnunet_signatures.h" + +#define VERBOSE GNUNET_NO + +#define RECORDS 1 +#define TEST_RECORD_TYPE 1234 +#define TEST_RECORD_DATALEN 123 +#define TEST_RECORD_DATA 'a' + +#define TEST_CREATE_RECORD_TYPE 4321 +#define TEST_CREATE_RECORD_DATALEN 255 +#define TEST_CREATE_RECORD_DATA 'b' + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; +struct GNUNET_CRYPTO_RsaSignature *s_signature; +struct GNUNET_CRYPTO_RsaSignature *s_signature_updated; +static struct GNUNET_CRYPTO_ShortHashCode s_zone; +struct GNUNET_NAMESTORE_RecordData *s_first_record; +struct GNUNET_NAMESTORE_RecordData *s_second_record; +static char *s_name; + + + +static int res; + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_destroy (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (NULL != arm) + stop_arm(); + + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + GNUNET_free ((void *) s_first_record->data); + GNUNET_free (s_first_record); + GNUNET_free_non_null (s_second_record); + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (NULL != arm) + stop_arm(); +} + +void name_lookup_second_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *n, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + static int found = GNUNET_NO; + int failed = GNUNET_NO; + int c; + + if (n != NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking returned results\n"); + if (0 != memcmp (zone_key, &pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (0 != strcmp(n, s_name)) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (2 != rd_count) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + for (c = 0; c < rd_count; c++) + { + if ((GNUNET_NO == GNUNET_NAMESTORE_records_cmp(&rd[c], s_first_record)) && + (GNUNET_NO == GNUNET_NAMESTORE_records_cmp(&rd[c], s_second_record))) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + } + + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(&pubkey, expire, n, rd_count, rd, signature)) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + struct GNUNET_NAMESTORE_RecordData rd_new[2]; + rd_new[0] = *s_first_record; + rd_new[1] = *s_second_record; + s_signature_updated = GNUNET_NAMESTORE_create_signature(privkey, expire, s_name, rd_new, 2); + + if (0 != memcmp (s_signature_updated, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature))) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + found = GNUNET_YES; + if (failed == GNUNET_NO) + res = 0; + else + res = 1; + } + else + { + if (found != GNUNET_YES) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to lookup records for name `%s'\n", s_name); + res = 1; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Lookup done for name %s'\n", s_name); + } + GNUNET_SCHEDULER_add_now(&end, NULL); +} + + +void +create_second_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Create second record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + if (success == GNUNET_OK) + { + res = 0; + GNUNET_NAMESTORE_lookup_record (nsh, &s_zone, name, 0, &name_lookup_second_proc, name); + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } + +} + +void name_lookup_initial_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *n, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + char * name = cls; + static int found = GNUNET_NO; + int failed = GNUNET_NO; + int c; + + if (n != NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking returned results\n"); + if (0 != memcmp (zone_key, &pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (0 != strcmp(n, s_name)) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (RECORDS != rd_count) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + for (c = 0; c < RECORDS; c++) + { + if (GNUNET_NO == GNUNET_NAMESTORE_records_cmp(&rd[c], &s_first_record[c])) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + } + + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(&pubkey, expire, n, rd_count, rd, signature)) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (0 != memcmp (s_signature, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature))) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + found = GNUNET_YES; + if (failed == GNUNET_NO) + res = 0; + else + res = 1; + + /* create a second record */ + s_second_record = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_RecordData) + TEST_CREATE_RECORD_DATALEN); + s_second_record->expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + s_second_record->record_type = TEST_CREATE_RECORD_TYPE; + s_second_record->flags = GNUNET_NAMESTORE_RF_AUTHORITY; + s_second_record->data = &s_second_record[1]; + s_second_record->data_size = TEST_CREATE_RECORD_DATALEN; + memset ((char *) s_second_record->data, TEST_CREATE_RECORD_DATA, TEST_CREATE_RECORD_DATALEN); + + GNUNET_NAMESTORE_record_create (nsh, privkey, name, s_second_record, &create_second_cont, name); + + } + else + { + if (found != GNUNET_YES) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to lookup records for name `%s'\n", s_name); + res = 1; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Lookup done for name %s'\n", s_name); + GNUNET_SCHEDULER_add_now (&end, NULL); + } +} + + +void +create_updated_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating expiration for record `%s': %s `%s'\n", name, ((success == GNUNET_YES) || (success == GNUNET_NO)) ? "SUCCESS" : "FAIL", emsg); + if (success == GNUNET_NO) + { + res = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updated record for name `%s'\n", name); + } + else if (success == GNUNET_OK) + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "FAIL, Create new record for name `%s'\n", name); + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create records for name `%s'\n", name); + } + GNUNET_SCHEDULER_add_now(&end, NULL); +} + +void +create_identical_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating identical record for `%s': %s `%s'\n", name, ((success == GNUNET_YES) || (success == GNUNET_NO)) ? "SUCCESS" : "FAIL", emsg); + if (success == GNUNET_NO) + { + res = 0; + s_first_record->expiration = GNUNET_TIME_absolute_get (); + GNUNET_NAMESTORE_record_create (nsh, privkey, s_name, s_first_record, &create_updated_cont, s_name); + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating identical record for `%s': %s `%s'\n", name, ((success == GNUNET_YES) || (success == GNUNET_NO)) ? "SUCCESS" : "FAIL", emsg); + GNUNET_SCHEDULER_add_now(&end, NULL); + } + +} + +void +create_first_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Create record for `%s': %s `%s'\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL", emsg); + if (success == GNUNET_OK) + { + res = 0; + /* check if record was created correct */ + GNUNET_NAMESTORE_record_create (nsh, privkey, s_name, s_first_record, &create_identical_cont, s_name); + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } + +} + +void +put_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s `%s'\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL", emsg); + if (success == GNUNET_OK) + { + + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } +} + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + int c; + struct GNUNET_NAMESTORE_RecordData * rd; + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + for (c = 0; c < count; c++) + { + rd[c].expiration = GNUNET_TIME_UNIT_ZERO_ABS; + rd[c].record_type = TEST_RECORD_TYPE; + rd[c].data_size = TEST_RECORD_DATALEN; + rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); + memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); + } + + return rd; +} + +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } + +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + delete_existing_db(cfg); + + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,endbadly, NULL); + size_t rd_ser_len; + + /* load privat key */ + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + + GNUNET_assert (privkey != NULL); + /* get public key */ + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + + /* create record */ + s_name = "dummy.dummy.gnunet"; + s_first_record = create_record (1); + + rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, s_first_record); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(1, s_first_record, rd_ser_len, rd_ser); + + s_signature = GNUNET_NAMESTORE_create_signature(privkey, s_first_record->expiration, s_name, s_first_record, 1); + + /* create random zone hash */ + GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &s_zone); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name: `%s' Zone: `%s' \n", s_name, GNUNET_short_h2s (&s_zone)); + + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + GNUNET_break (s_first_record != NULL); + GNUNET_break (s_name != NULL); + + /* create initial record */ + GNUNET_NAMESTORE_record_create (nsh, privkey, s_name, s_first_record, &create_first_cont, s_name); +} + +static int +check () +{ + static char *const argv[] = { "test-namestore-api", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-namestore-api", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + GNUNET_free (s_signature); + return ret; +} + +/* end of test_namestore_api.c */ diff --git a/src/namestore/test_namestore_api_lookup.c b/src/namestore/test_namestore_api_lookup.c new file mode 100644 index 0000000..818e710 --- /dev/null +++ b/src/namestore/test_namestore_api_lookup.c @@ -0,0 +1,317 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file namestore/test_namestore_api.c + * @brief testcase for namestore_api.c + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" +#include "gnunet_signatures.h" + +#define VERBOSE GNUNET_NO + +#define RECORDS 5 +#define TEST_RECORD_TYPE 1234 +#define TEST_RECORD_DATALEN 123 +#define TEST_RECORD_DATA 'a' + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; +struct GNUNET_CRYPTO_RsaSignature *s_signature; +static struct GNUNET_CRYPTO_ShortHashCode s_zone; +struct GNUNET_NAMESTORE_RecordData *s_rd; +static char *s_name; + + + +static int res; + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_destroy (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (NULL != arm) + stop_arm(); + + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + int c; + for (c = 0; c < RECORDS; c++) + GNUNET_free_non_null((void *) s_rd[c].data); + GNUNET_free (s_rd); + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (NULL != arm) + stop_arm(); +} + +void name_lookup_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *n, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + static int found = GNUNET_NO; + int c; + + if (n != NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking returned results\n"); + if (0 != memcmp (zone_key, &pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))) + { + GNUNET_break (0); + } + + if (0 != memcmp (signature, s_signature, sizeof (struct GNUNET_CRYPTO_RsaSignature))) + { + GNUNET_break (0); + } + + if (0 != strcmp(n, s_name)) + { + GNUNET_break (0); + } + + if (RECORDS != rd_count) + { + GNUNET_break (0); + } + + for (c = 0; c < RECORDS; c++) + { + if (GNUNET_NO == GNUNET_NAMESTORE_records_cmp (&rd[c], &s_rd[c])) + { + GNUNET_break (0); + } + } + found = GNUNET_YES; + res = 0; + } + else + { + if (found != GNUNET_YES) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to lookup records for name `%s'\n", s_name); + res = 1; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Lookup done for name %s'\n", s_name); + } + GNUNET_SCHEDULER_add_now(&end, NULL); +} + +void +put_cont (void *cls, int32_t success, const char *emsg) +{ + char * name = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + if (success == GNUNET_OK) + { + res = 0; + GNUNET_NAMESTORE_lookup_record (nsh, &s_zone, name, 0, &name_lookup_proc, NULL); + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } +} + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + int c; + struct GNUNET_NAMESTORE_RecordData * rd; + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + for (c = 0; c < RECORDS; c++) + { + rd[c].expiration = GNUNET_TIME_absolute_get(); + rd[c].record_type = TEST_RECORD_TYPE; + rd[c].data_size = TEST_RECORD_DATALEN; + rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); + memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); + } + + return rd; +} + +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } + +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + delete_existing_db(cfg); + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,endbadly, NULL); + + size_t rd_ser_len; + + /* load privat key from file not included in zonekey dir */ + privkey = GNUNET_CRYPTO_rsa_key_create_from_file("test_hostkey"); + GNUNET_assert (privkey != NULL); + /* get public key */ + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + + /* create record */ + s_name = "dummy.dummy.gnunet"; + s_rd = create_record (RECORDS); + + rd_ser_len = GNUNET_NAMESTORE_records_get_size(RECORDS, s_rd); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(RECORDS, s_rd, rd_ser_len, rd_ser); + + /* sign */ + s_signature = GNUNET_NAMESTORE_create_signature(privkey, s_rd[0].expiration, s_name, s_rd, RECORDS); + + /* create random zone hash */ + GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &s_zone); + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + GNUNET_break (s_rd != NULL); + GNUNET_break (s_name != NULL); + + GNUNET_NAMESTORE_record_put (nsh, &pubkey, s_name, + GNUNET_TIME_UNIT_FOREVER_ABS, + RECORDS, s_rd, s_signature, put_cont, s_name); +} + + +static int +check () +{ + static char *const argv[] = { "test-namestore-api", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-namestore-api", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + GNUNET_free (s_signature); + return ret; +} + +/* end of test_namestore_api.c */ diff --git a/src/namestore/test_namestore_api_lookup_specific_type.c b/src/namestore/test_namestore_api_lookup_specific_type.c new file mode 100644 index 0000000..981e252 --- /dev/null +++ b/src/namestore/test_namestore_api_lookup_specific_type.c @@ -0,0 +1,399 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file namestore/test_namestore_api.c + * @brief testcase for namestore_api.c + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" +#include "gnunet_signatures.h" + +#define VERBOSE GNUNET_NO + +#define RECORDS 5 +#define TEST_RECORD_TYPE 1234 +#define TEST_RECORD_DATALEN 123 +#define TEST_RECORD_DATA 'a' + +#define TEST_RECORD_LOOKUP_TYPE_NOT_EXISTING 11111 +#define TEST_RECORD_LOOKUP_TYPE_EXISTING 22222 + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; +struct GNUNET_CRYPTO_RsaSignature *s_signature; +static struct GNUNET_CRYPTO_ShortHashCode s_zone; +struct GNUNET_NAMESTORE_RecordData *s_rd; +static char *s_name; + + + +static int res; + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_destroy (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (NULL != arm) + stop_arm(); + + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + int c; + for (c = 0; c < RECORDS; c++) + { + GNUNET_free_non_null((void *) s_rd[c].data); + } + GNUNET_free (s_rd); + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (NULL != arm) + stop_arm(); +} + + +void name_lookup_existing_record_type (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *n, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + int failed = GNUNET_NO; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore returned %u records\n", rd_count); + + if ((NULL == n) || (0 != memcmp(zone_key, &pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))) + { + GNUNET_break(0); + failed = GNUNET_YES; + } + if ((NULL == n) || (0 != strcmp(n, s_name))) + { + GNUNET_break(0); + failed = GNUNET_YES; + } + if (1 != rd_count) + { + GNUNET_break(0); + failed = GNUNET_YES; + } + if (NULL == rd) + { + GNUNET_break(0); + failed = GNUNET_YES; + } + if (NULL != signature) + { + GNUNET_break(0); + failed = GNUNET_YES; + } + + if (failed == GNUNET_YES) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore returned invalid response\n"); + res = 1; + } + else + { + res = 0; + } + + GNUNET_SCHEDULER_add_now(&end, NULL); +} + + +void name_lookup_non_existing_record_type (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *n, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + int failed = GNUNET_NO; + /* We expect zone key != NULL, name != NULL, rd_count 0, rd NULL, signature NULL */ + if (NULL == zone_key) + { + GNUNET_break(0); + failed = GNUNET_YES; + } + if (NULL == n) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name %s!\n", n); + GNUNET_break(0); + failed = GNUNET_YES; + } + if (0 != rd_count) + { + GNUNET_break(0); + failed = GNUNET_YES; + } + if (NULL != rd) + { + GNUNET_break(0); + failed = GNUNET_YES; + } + if (NULL != signature) + { + GNUNET_break(0); + failed = GNUNET_YES; + } + + if ((rd_count == 1) && (rd != NULL)) + { + if (GNUNET_NO == GNUNET_NAMESTORE_records_cmp(rd, &rd[RECORDS-1])) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Records are not equal!\n"); + failed = GNUNET_YES; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Records are equal!\n"); + } + } + + if (failed == GNUNET_YES) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore returned invalid response\n"); + res = 1; + + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore returned valid response\n"); + GNUNET_NAMESTORE_lookup_record (nsh, &s_zone, s_name, TEST_RECORD_LOOKUP_TYPE_EXISTING, &name_lookup_existing_record_type, NULL); + res = 0; + } +} + +void +put_cont (void *cls, int32_t success, const char *emsg) +{ + char * name = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + if (success == GNUNET_OK) + { + res = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up non-existing record type %u for name `%s'\n", TEST_RECORD_LOOKUP_TYPE_NOT_EXISTING, name); + GNUNET_NAMESTORE_lookup_record (nsh, &s_zone, name, TEST_RECORD_LOOKUP_TYPE_NOT_EXISTING, &name_lookup_non_existing_record_type, NULL); + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } +} + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + int c; + struct GNUNET_NAMESTORE_RecordData * rd; + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + for (c = 0; c < RECORDS-1; c++) + { + rd[c].expiration = GNUNET_TIME_UNIT_ZERO_ABS; + rd[c].record_type = 1; + rd[c].data_size = TEST_RECORD_DATALEN; + rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); + memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); + } + + rd[c].expiration = GNUNET_TIME_absolute_get(); + rd[c].record_type = TEST_RECORD_LOOKUP_TYPE_EXISTING; + rd[c].data_size = TEST_RECORD_DATALEN; + rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); + memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); + + + return rd; +} + +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } + +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + delete_existing_db(cfg); + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,endbadly, NULL); + + size_t rd_ser_len; + + /* load privat key */ + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey != NULL); + /* get public key */ + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + + /* create record */ + s_name = "dummy.dummy.gnunet"; + s_rd = create_record (RECORDS); + + rd_ser_len = GNUNET_NAMESTORE_records_get_size(RECORDS, s_rd); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(RECORDS, s_rd, rd_ser_len, rd_ser); + + /* sign */ + s_signature = GNUNET_NAMESTORE_create_signature(privkey, s_rd[RECORDS -1].expiration, s_name, s_rd, RECORDS); + + /* create random zone hash */ + GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &s_zone); + + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + GNUNET_break (s_rd != NULL); + GNUNET_break (s_name != NULL); + + GNUNET_NAMESTORE_record_put (nsh, &pubkey, s_name, + GNUNET_TIME_UNIT_FOREVER_ABS, + RECORDS, s_rd, s_signature, put_cont, s_name); + + + +} + +static int +check () +{ + static char *const argv[] = { "test-namestore-api", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-namestore-api", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + GNUNET_free (s_signature); + return ret; +} + +/* end of test_namestore_api.c */ diff --git a/src/namestore/test_namestore_api_put.c b/src/namestore/test_namestore_api_put.c new file mode 100644 index 0000000..9315fd3 --- /dev/null +++ b/src/namestore/test_namestore_api_put.c @@ -0,0 +1,249 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file namestore/test_namestore_api.c + * @brief testcase for namestore_api.c + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" + +#define VERBOSE GNUNET_NO + +#define RECORDS 5 +#define TEST_RECORD_TYPE 1234 +#define TEST_RECORD_DATALEN 123 +#define TEST_RECORD_DATA 'a' + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; + +struct GNUNET_NAMESTORE_RecordData *s_rd; + +static int res; + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_destroy (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (NULL != arm) + stop_arm(); + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (NULL != arm) + stop_arm(); +} + +void +put_cont (void *cls, int32_t success, const char *emsg) +{ + char * name = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + if (success == GNUNET_OK) + res = 0; + else + res = 1; + + GNUNET_SCHEDULER_add_now(&end, NULL); +} + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + int c; + struct GNUNET_NAMESTORE_RecordData * rd; + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + for (c = 0; c < RECORDS; c++) + { + rd[c].expiration = GNUNET_TIME_absolute_get(); + rd[c].record_type = TEST_RECORD_TYPE; + rd[c].data_size = TEST_RECORD_DATALEN; + rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); + memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); + } + return rd; +} + +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + delete_existing_db(cfg); + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,endbadly, NULL); + + /* load privat key */ + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + + GNUNET_assert (privkey != NULL); + /* get public key */ + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + + struct GNUNET_CRYPTO_RsaSignature *signature; + + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + /* create record */ + char * s_name = "dummy.dummy.gnunet"; + s_rd = create_record (RECORDS); + + signature = GNUNET_NAMESTORE_create_signature(privkey, s_rd[0].expiration, s_name, s_rd, RECORDS); + + GNUNET_break (s_rd != NULL); + GNUNET_break (s_name != NULL); + + GNUNET_NAMESTORE_record_put (nsh, &pubkey, s_name, + GNUNET_TIME_UNIT_FOREVER_ABS, + RECORDS, s_rd, signature, put_cont, s_name); + + GNUNET_free (signature); + + int c; + for (c = 0; c < RECORDS; c++) + GNUNET_free_non_null((void *) s_rd[c].data); + GNUNET_free (s_rd); + +} + +static int +check () +{ + static char *const argv[] = { "test-namestore-api", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-namestore-api", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + + return ret; +} + +/* end of test_namestore_api.c */ diff --git a/src/namestore/test_namestore_api_remove.c b/src/namestore/test_namestore_api_remove.c new file mode 100644 index 0000000..57bb4a8 --- /dev/null +++ b/src/namestore/test_namestore_api_remove.c @@ -0,0 +1,366 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file namestore/test_namestore_api.c + * @brief testcase for namestore_api.c + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" +#include "gnunet_signatures.h" + +#define VERBOSE GNUNET_NO + +#define RECORDS 5 +#define TEST_RECORD_TYPE 1234 +#define TEST_RECORD_DATALEN 123 +#define TEST_RECORD_DATA 'a' + +#define TEST_REMOVE_RECORD_TYPE 4321 +#define TEST_REMOVE_RECORD_DATALEN 255 +#define TEST_REMOVE_RECORD_DATA 'b' + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; +struct GNUNET_CRYPTO_RsaSignature *s_signature; +static struct GNUNET_CRYPTO_ShortHashCode s_zone; +struct GNUNET_NAMESTORE_RecordData *s_rd; +static char *s_name; + + + +static int res; + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_destroy (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (NULL != arm) + stop_arm(); + + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + int c; + for (c = 0; c < RECORDS; c++) + GNUNET_free_non_null((void *) s_rd[c].data); + GNUNET_free (s_rd); + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (NULL != arm) + stop_arm(); +} + +void name_lookup_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *n, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + static int found = GNUNET_NO; + int failed = GNUNET_NO; + int c; + + if (n != NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Lookup for name `%s' returned %u records\n", n, rd_count); + if (0 != memcmp (zone_key, &pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (0 != strcmp(n, s_name)) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (RECORDS-1 != rd_count) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + for (c = 0; c < rd_count; c++) + { + if (GNUNET_NO == GNUNET_NAMESTORE_records_cmp (&rd[c], &s_rd[c+1])) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + } + + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(&pubkey, expire, n, rd_count, rd, signature)) + { + GNUNET_break (0); + failed = GNUNET_YES; + } + + if (failed == GNUNET_NO) + res = 0; + else + res = 1; + } + else + { + if (found != GNUNET_YES) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to lookup records for name `%s'\n", s_name); + res = 1; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Lookup done for name %s'\n", s_name); + } + GNUNET_SCHEDULER_add_now(&end, NULL); +} + +void +remove_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Remove record for `%s': %s\n", name, (success == GNUNET_YES) ? "SUCCESS" : "FAIL", emsg); + if (success == GNUNET_OK) + { + res = 0; + GNUNET_NAMESTORE_lookup_record (nsh, &s_zone, name, 0, &name_lookup_proc, name); + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to remove record for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } + +} + +void +put_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + if (success == GNUNET_OK) + { + res = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for `%s'\n", name); + + GNUNET_NAMESTORE_record_remove (nsh, privkey, name, &s_rd[0], &remove_cont, name); + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } +} + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + int c; + struct GNUNET_NAMESTORE_RecordData * rd; + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + rd[0].expiration = GNUNET_TIME_absolute_get(); + rd[0].record_type = 0; + rd[0].data_size = TEST_REMOVE_RECORD_DATALEN; + rd[0].data = GNUNET_malloc(TEST_REMOVE_RECORD_DATALEN); + memset ((char *) rd[0].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); + + for (c = 1; c < RECORDS; c++) + { + rd[c].expiration = GNUNET_TIME_UNIT_ZERO_ABS; + rd[c].record_type = TEST_RECORD_TYPE; + rd[c].data_size = TEST_RECORD_DATALEN; + rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); + memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); + } + + return rd; +} + +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } + +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + delete_existing_db(cfg); + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,endbadly, NULL); + size_t rd_ser_len; + + /* load privat key */ + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey != NULL); + /* get public key */ + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + + /* create record */ + s_name = "dummy.dummy.gnunet"; + s_rd = create_record (RECORDS); + + rd_ser_len = GNUNET_NAMESTORE_records_get_size(RECORDS, s_rd); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(RECORDS, s_rd, rd_ser_len, rd_ser); + + /* sign */ + s_signature = GNUNET_NAMESTORE_create_signature(privkey, s_rd[0].expiration, s_name, s_rd, RECORDS); + + /* create random zone hash */ + GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &s_zone); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name: `%s' Zone: `%s' \n", s_name, GNUNET_short_h2s (&s_zone)); + + + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + GNUNET_break (s_rd != NULL); + GNUNET_break (s_name != NULL); + + GNUNET_NAMESTORE_record_put (nsh, &pubkey, s_name, + GNUNET_TIME_UNIT_FOREVER_ABS, + RECORDS, s_rd, s_signature, put_cont, s_name); + + + +} + +static int +check () +{ + static char *const argv[] = { "test-namestore-api", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-namestore-api", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + GNUNET_free (s_signature); + return ret; +} + +/* end of test_namestore_api.c */ diff --git a/src/namestore/test_namestore_api_remove_not_existing_record.c b/src/namestore/test_namestore_api_remove_not_existing_record.c new file mode 100644 index 0000000..8c32278 --- /dev/null +++ b/src/namestore/test_namestore_api_remove_not_existing_record.c @@ -0,0 +1,299 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file namestore/test_namestore_api.c + * @brief testcase for namestore_api.c + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" +#include "gnunet_signatures.h" + +#define VERBOSE GNUNET_NO + +#define RECORDS 5 +#define TEST_RECORD_TYPE 1234 +#define TEST_RECORD_DATALEN 123 +#define TEST_RECORD_DATA 'a' + +#define TEST_REMOVE_RECORD_TYPE 4321 +#define TEST_REMOVE_RECORD_DATALEN 255 +#define TEST_REMOVE_RECORD_DATA 'b' + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; +struct GNUNET_CRYPTO_RsaSignature *s_signature; +static GNUNET_HashCode s_zone; +struct GNUNET_NAMESTORE_RecordData *s_rd; +static char *s_name; + + + +static int res; + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_destroy (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (NULL != arm) + stop_arm(); + + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + int c; + for (c = 0; c < RECORDS; c++) + GNUNET_free_non_null((void *) s_rd[c].data); + GNUNET_free (s_rd); + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (NULL != arm) + stop_arm(); +} + +void +remove_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Remove record for `%s': %s `%s'\n", name, (success == GNUNET_YES) ? "SUCCESS" : "FAIL", emsg); + if (GNUNET_NO == success) + { + res = 0; + } + else + { + res = 1; + GNUNET_break (0); + } + GNUNET_SCHEDULER_add_now(&end, NULL); +} + +void +put_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + if (success == GNUNET_OK) + { + res = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing non existing record for `%s'\n", name); + + struct GNUNET_NAMESTORE_RecordData rd; + char data[TEST_REMOVE_RECORD_DATALEN]; + rd.expiration = GNUNET_TIME_absolute_get(); + rd.record_type = TEST_REMOVE_RECORD_TYPE; + rd.data_size = TEST_REMOVE_RECORD_DATALEN; + rd.data = &data; + + GNUNET_NAMESTORE_record_remove (nsh, privkey, name, &rd, &remove_cont, name); + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } +} + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + int c; + struct GNUNET_NAMESTORE_RecordData * rd; + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + for (c = 0; c < RECORDS; c++) + { + rd[c].expiration = GNUNET_TIME_absolute_get(); + rd[c].record_type = TEST_RECORD_TYPE; + rd[c].data_size = TEST_RECORD_DATALEN; + rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); + memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); + } + + return rd; +} + +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } + +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + delete_existing_db(cfg); + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,endbadly, NULL); + size_t rd_ser_len; + + /* load privat key */ + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey != NULL); + /* get public key */ + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + + /* create record */ + s_name = "dummy.dummy.gnunet"; + s_rd = create_record (RECORDS); + + rd_ser_len = GNUNET_NAMESTORE_records_get_size(RECORDS, s_rd); + char rd_ser[rd_ser_len]; + GNUNET_NAMESTORE_records_serialize(RECORDS, s_rd, rd_ser_len, rd_ser); + + /* sign */ + s_signature = GNUNET_NAMESTORE_create_signature(privkey, s_rd[0].expiration, s_name, s_rd, RECORDS); + + /* create random zone hash */ + GNUNET_CRYPTO_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &s_zone); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name: `%s' Zone: `%s' \n", s_name, GNUNET_h2s_full(&s_zone)); + + + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + GNUNET_break (s_rd != NULL); + GNUNET_break (s_name != NULL); + + GNUNET_NAMESTORE_record_put (nsh, &pubkey, s_name, + GNUNET_TIME_UNIT_FOREVER_ABS, + RECORDS, s_rd, s_signature, put_cont, s_name); + + +} + +static int +check () +{ + static char *const argv[] = { "test-namestore-api", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-namestore-api", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + GNUNET_free (s_signature); + return ret; +} + +/* end of test_namestore_api.c */ diff --git a/src/namestore/test_namestore_api_sign_verify.c b/src/namestore/test_namestore_api_sign_verify.c new file mode 100644 index 0000000..17bfb1e --- /dev/null +++ b/src/namestore/test_namestore_api_sign_verify.c @@ -0,0 +1,150 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file namestore/test_namestore_api_sign_verify.c + * @brief testcase for signing and verifying + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" +#include "gnunet_signatures.h" + +#define VERBOSE GNUNET_NO + +#define RECORDS 5 +#define TEST_RECORD_TYPE 1234 +#define TEST_RECORD_DATALEN 123 +#define TEST_RECORD_DATA 'a' + +#define TEST_REMOVE_RECORD_TYPE 4321 +#define TEST_REMOVE_RECORD_DATALEN 255 +#define TEST_REMOVE_RECORD_DATA 'b' + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; +struct GNUNET_CRYPTO_RsaSignature s_signature; +struct GNUNET_NAMESTORE_RecordData *s_rd; +static char *s_name; + +static int res; + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + int c; + struct GNUNET_NAMESTORE_RecordData * rd; + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + for (c = 0; c < RECORDS; c++) + { + rd[c].expiration = GNUNET_TIME_absolute_get(); + rd[c].record_type = TEST_RECORD_TYPE; + rd[c].data_size = TEST_RECORD_DATALEN; + rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); + memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); + } + + return rd; +} + + + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_CRYPTO_RsaSignature * signature; + + /* load privat key */ + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey != NULL); + struct GNUNET_TIME_Absolute expire = GNUNET_TIME_absolute_get(); + /* get public key */ + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + + int res_c; + int res_w; + + /* create record */ + s_name = "dummy.dummy.gnunet"; + s_rd = create_record (RECORDS); + + signature = GNUNET_NAMESTORE_create_signature (privkey, expire, s_name, s_rd, RECORDS); + GNUNET_assert (signature != NULL); + + res_c = GNUNET_NAMESTORE_verify_signature(&pubkey, expire, s_name, RECORDS, s_rd, signature); + GNUNET_break (res == GNUNET_OK); + + GNUNET_free (signature); + + signature = GNUNET_NAMESTORE_create_signature (privkey, expire, s_name, s_rd, RECORDS); + GNUNET_break (signature != NULL); + + GNUNET_log_skip(1, GNUNET_NO); + res_w = GNUNET_NAMESTORE_verify_signature(&pubkey, expire, s_name, RECORDS - 1, s_rd, signature); + GNUNET_break (res_w == GNUNET_SYSERR); + + GNUNET_free (signature); + + if ((res_c == GNUNET_OK) && (res_w == GNUNET_SYSERR)) + res = 0; + else + res = 1; + +} + +static int +check () +{ + static char *const argv[] = { "test-namestore-api", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-namestore-api", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + + return ret; +} + +/* end of test_namestore_api_sign_verify.c */ diff --git a/src/namestore/test_namestore_api_zone_iteration.c b/src/namestore/test_namestore_api_zone_iteration.c index c0ef8c8..0665541 100644 --- a/src/namestore/test_namestore_api_zone_iteration.c +++ b/src/namestore/test_namestore_api_zone_iteration.c @@ -19,11 +19,12 @@ */ /** * @file namestore/test_namestore_api_zone_iteration.c - * @brief testcase for namestore_api.c zone iteration functionality + * @brief testcase for zone iteration functionality: iterate of a specific zone */ #include "platform.h" #include "gnunet_common.h" #include "gnunet_namestore_service.h" +#include "namestore.h" #define VERBOSE GNUNET_NO @@ -39,8 +40,25 @@ static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; static GNUNET_HashCode zone; +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey2; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey2; +static GNUNET_HashCode zone2; + static struct GNUNET_NAMESTORE_ZoneIterator *zi; static int res; +static int returned_records; + +struct GNUNET_CRYPTO_RsaSignature *sig_1; +char * s_name_1; +struct GNUNET_NAMESTORE_RecordData *s_rd_1; + +struct GNUNET_CRYPTO_RsaSignature *sig_2; +char * s_name_2; +struct GNUNET_NAMESTORE_RecordData *s_rd_2; + +struct GNUNET_CRYPTO_RsaSignature *sig_3; +char * s_name_3; +struct GNUNET_NAMESTORE_RecordData *s_rd_3; static void start_arm (const char *cfgname) @@ -63,7 +81,7 @@ stop_arm () if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); GNUNET_OS_process_wait (arm); - GNUNET_OS_process_close (arm); + GNUNET_OS_process_destroy (arm); arm = NULL; } } @@ -87,10 +105,37 @@ endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); nsh = NULL; + GNUNET_free_non_null(sig_1); + GNUNET_free_non_null(sig_2); + GNUNET_free_non_null(sig_3); + GNUNET_free_non_null(s_name_1); + GNUNET_free_non_null(s_name_2); + GNUNET_free_non_null(s_name_3); + + if (s_rd_1 != NULL) + { + GNUNET_free ((void *)s_rd_1->data); + GNUNET_free (s_rd_1); + } + if (s_rd_2 != NULL) + { + GNUNET_free ((void *)s_rd_2->data); + GNUNET_free (s_rd_2); + } + if (s_rd_3 != NULL) + { + GNUNET_free ((void *)s_rd_3->data); + GNUNET_free (s_rd_3); + } + if (privkey != NULL) GNUNET_CRYPTO_rsa_key_free (privkey); privkey = NULL; + if (privkey2 != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey2); + privkey2 = NULL; + if (NULL != arm) stop_arm(); @@ -113,11 +158,36 @@ end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) endbadly_task = GNUNET_SCHEDULER_NO_TASK; } - if (privkey != NULL) GNUNET_CRYPTO_rsa_key_free (privkey); privkey = NULL; + if (privkey2 != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey2); + privkey2 = NULL; + + GNUNET_free (sig_1); + GNUNET_free (sig_2); + GNUNET_free (sig_3); + GNUNET_free (s_name_1); + GNUNET_free (s_name_2); + GNUNET_free (s_name_3); + if (s_rd_1 != NULL) + { + GNUNET_free ((void *)s_rd_1->data); + GNUNET_free (s_rd_1); + } + if (s_rd_2 != NULL) + { + GNUNET_free ((void *)s_rd_2->data); + GNUNET_free (s_rd_2); + } + if (s_rd_3 != NULL) + { + GNUNET_free ((void *)s_rd_3->data); + GNUNET_free (s_rd_3); + } + if (nsh != NULL) GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); nsh = NULL; @@ -125,19 +195,6 @@ end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (NULL != arm) stop_arm(); - - res = 0; -} - -static void -stop_iteration (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - stopiteration_task = GNUNET_SCHEDULER_NO_TASK; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping iteration for zone `%s'\n", GNUNET_h2s (&zone)); - GNUNET_NAMESTORE_zone_iteration_stop (zi); - - GNUNET_SCHEDULER_add_now (&end, NULL); } void zone_proc (void *cls, @@ -148,22 +205,226 @@ void zone_proc (void *cls, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for zone `%s'\n", GNUNET_h2s (&zone)); + int failed = GNUNET_NO; + if ((zone_key == NULL) && (name == NULL)) + { + GNUNET_break (3 == returned_records); + if (3 == returned_records) + res = 0; + else + res = 1; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received last result, iteration done after receing %u results\n",returned_records ); + GNUNET_SCHEDULER_add_now (&end, NULL); + } + else + { + /* verify signature returned from name store */ + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature (zone_key, expire, name, rd_count, rd, signature)) + { + GNUNET_HashCode zone_key_hash; + GNUNET_CRYPTO_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_key_hash); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Verifying signature for `%s' in zone `%s' with %u records and expiration %llu failed\n", name, GNUNET_h2s(&zone_key_hash), rd_count, expire.abs_value); + + failed = GNUNET_YES; + GNUNET_break (0); + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing results name %s \n", name); + if (0 == strcmp (name, s_name_1)) + { + if (rd_count == 1) + { + if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_1)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else + { + failed = GNUNET_YES; + GNUNET_break (0); + } + if (0 != memcmp (signature, sig_1, sizeof (struct GNUNET_CRYPTO_RsaSignature))) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else if (0 == strcmp (name, s_name_2)) + { + if (rd_count == 1) + { + if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_2)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else + { + failed = GNUNET_YES; + GNUNET_break (0); + } + if (0 != memcmp (signature, sig_2, sizeof (struct GNUNET_CRYPTO_RsaSignature))) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else if (0 == strcmp (name, s_name_3)) + { + if (rd_count == 1) + { + if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_3)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else + { + failed = GNUNET_YES; + GNUNET_break (0); + } + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(zone_key, expire, name, rd_count, rd, signature)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + + if (0 != memcmp (signature, sig_3, sizeof (struct GNUNET_CRYPTO_RsaSignature))) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing result failed: got name `%s'\n", name); + res = 1; + GNUNET_break (0); + GNUNET_SCHEDULER_add_now (&end, NULL); + } + + if (failed == GNUNET_NO) + { + returned_records ++; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to send the next result\n"); + GNUNET_NAMESTORE_zone_iterator_next (zi); + } + else + { + GNUNET_break (0); + GNUNET_SCHEDULER_add_now (&end, NULL); + } + } +} + +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } - stopiteration_task = GNUNET_SCHEDULER_add_now (&stop_iteration, NULL); +} + +void +put_cont (void *cls, int32_t success, const char *emsg) +{ + static int c = 0; + + if (success == GNUNET_OK) + { + c++; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records\n"); + GNUNET_break (0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + } + + if (c == 3) + { + res = 1; + returned_records = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All records created, starting iteration over all zones \n"); + zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, + NULL, + GNUNET_NAMESTORE_RF_NONE, + GNUNET_NAMESTORE_RF_NONE, + zone_proc, + &zone); + if (zi == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); + GNUNET_break (0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + } + } +} + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + int c; + struct GNUNET_NAMESTORE_RecordData * rd; + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + for (c = 0; c < count; c++) + { + rd[c].expiration = GNUNET_TIME_absolute_get(); + rd[c].record_type = 1111; + rd[c].data_size = 50; + rd[c].data = GNUNET_malloc(50); + memset ((char *) rd[c].data, 'a', 50); + } + return rd; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { + delete_existing_db(cfg); endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,&endbadly, NULL); - privkey = GNUNET_CRYPTO_rsa_key_create_from_file("hostkey"); + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + GNUNET_CRYPTO_hash(&pubkey, sizeof (pubkey), &zone); + + + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey2 = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + + GNUNET_assert (privkey2 != NULL); + GNUNET_CRYPTO_rsa_key_get_public(privkey2, &pubkey2); + GNUNET_CRYPTO_hash(&pubkey2, sizeof (pubkey), &zone2); - GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &zone); start_arm (cfgfile); GNUNET_assert (arm != NULL); @@ -171,18 +432,27 @@ run (void *cls, char *const *args, const char *cfgfile, nsh = GNUNET_NAMESTORE_connect (cfg); GNUNET_break (NULL != nsh); - zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, - &zone, - GNUNET_NAMESTORE_RF_NONE, - GNUNET_NAMESTORE_RF_NONE, - zone_proc, - &zone); - if (zi == NULL) - { - GNUNET_break (0); - GNUNET_SCHEDULER_cancel (endbadly_task); - endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); - } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); + + GNUNET_asprintf(&s_name_1, "dummy1"); + s_rd_1 = create_record(1); + sig_1 = GNUNET_NAMESTORE_create_signature(privkey, s_rd_1->expiration, s_name_1, s_rd_1, 1); + GNUNET_NAMESTORE_record_create(nsh, privkey, s_name_1, s_rd_1, &put_cont, NULL); + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n"); + GNUNET_asprintf(&s_name_2, "dummy2"); + s_rd_2 = create_record(1); + + sig_2 = GNUNET_NAMESTORE_create_signature(privkey, s_rd_2->expiration, s_name_2, s_rd_2, 1); + GNUNET_NAMESTORE_record_create(nsh, privkey, s_name_2, s_rd_2, &put_cont, NULL); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 3\n"); + /* name in different zone */ + GNUNET_asprintf(&s_name_3, "dummy3"); + s_rd_3 = create_record(1); + sig_3 = GNUNET_NAMESTORE_create_signature(privkey2, s_rd_3->expiration, s_name_3, s_rd_3, 1); + GNUNET_NAMESTORE_record_put (nsh, &pubkey2, s_name_3, GNUNET_TIME_UNIT_FOREVER_ABS, 1, s_rd_3, sig_3, &put_cont, NULL); } static int diff --git a/src/namestore/test_namestore_api_zone_iteration_specific_zone.c b/src/namestore/test_namestore_api_zone_iteration_specific_zone.c new file mode 100644 index 0000000..b21c860 --- /dev/null +++ b/src/namestore/test_namestore_api_zone_iteration_specific_zone.c @@ -0,0 +1,451 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file namestore/test_namestore_api_zone_iteration_specific_zone.c + * @brief testcase for zone iteration functionality: iterate of a specific zone + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" + +#define VERBOSE GNUNET_NO + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static GNUNET_SCHEDULER_TaskIdentifier stopiteration_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; +static struct GNUNET_CRYPTO_ShortHashCode zone; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey2; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey2; +static struct GNUNET_CRYPTO_ShortHashCode zone2; + +static struct GNUNET_NAMESTORE_ZoneIterator *zi; +static int res; +static int returned_records; + +struct GNUNET_CRYPTO_RsaSignature *sig_1; +char * s_name_1; +struct GNUNET_NAMESTORE_RecordData *s_rd_1; + +struct GNUNET_CRYPTO_RsaSignature *sig_2; +char * s_name_2; +struct GNUNET_NAMESTORE_RecordData *s_rd_2; + +struct GNUNET_CRYPTO_RsaSignature *sig_3; +char * s_name_3; +struct GNUNET_NAMESTORE_RecordData *s_rd_3; + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_destroy (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (stopiteration_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (stopiteration_task); + stopiteration_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + GNUNET_free_non_null(sig_1); + GNUNET_free_non_null(sig_2); + GNUNET_free_non_null(sig_3); + GNUNET_free_non_null(s_name_1); + GNUNET_free_non_null(s_name_2); + GNUNET_free_non_null(s_name_3); + + if (s_rd_1 != NULL) + { + GNUNET_free ((void *)s_rd_1->data); + GNUNET_free (s_rd_1); + } + if (s_rd_2 != NULL) + { + GNUNET_free ((void *)s_rd_2->data); + GNUNET_free (s_rd_2); + } + if (s_rd_3 != NULL) + { + GNUNET_free ((void *)s_rd_3->data); + GNUNET_free (s_rd_3); + } + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (privkey2 != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey2); + privkey2 = NULL; + + if (NULL != arm) + stop_arm(); + + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (stopiteration_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (stopiteration_task); + stopiteration_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (privkey2 != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey2); + privkey2 = NULL; + + GNUNET_free (sig_1); + GNUNET_free (sig_2); + GNUNET_free (sig_3); + GNUNET_free (s_name_1); + GNUNET_free (s_name_2); + GNUNET_free (s_name_3); + if (s_rd_1 != NULL) + { + GNUNET_free ((void *)s_rd_1->data); + GNUNET_free (s_rd_1); + } + if (s_rd_2 != NULL) + { + GNUNET_free ((void *)s_rd_2->data); + GNUNET_free (s_rd_2); + } + if (s_rd_3 != NULL) + { + GNUNET_free ((void *)s_rd_3->data); + GNUNET_free (s_rd_3); + } + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + + if (NULL != arm) + stop_arm(); +} + +void zone_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + int failed = GNUNET_NO; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for zone `%s'\n", GNUNET_short_h2s (&zone)); + if ((zone_key == NULL) && (name == NULL)) + { + GNUNET_break (2 == returned_records); + if (2 == returned_records) + res = 0; + else + res = 1; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received last result, iteration done after %u records\n", returned_records); + GNUNET_SCHEDULER_add_now (&end, NULL); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing results name %s \n", name); + if (0 == strcmp (name, s_name_1)) + { + if (rd_count == 1) + { + if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_1)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else + { + failed = GNUNET_YES; + GNUNET_break (0); + } + if (0 != memcmp (signature, sig_1, sizeof (struct GNUNET_CRYPTO_RsaSignature))) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else if (0 == strcmp (name, s_name_2)) + { + if (rd_count == 1) + { + if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_2)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else + { + failed = GNUNET_YES; + GNUNET_break (0); + } + if (0 != memcmp (signature, sig_2, sizeof (struct GNUNET_CRYPTO_RsaSignature))) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing result failed: got name `%s'\n", name); + res = 1; + GNUNET_break (0); + GNUNET_SCHEDULER_add_now (&end, NULL); + } + + if (failed == GNUNET_NO) + { + returned_records ++; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to send the next result\n"); + GNUNET_NAMESTORE_zone_iterator_next (zi); + } + else + { + GNUNET_break (0); + GNUNET_SCHEDULER_add_now (&end, NULL); + } + } +} + +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } + +} + +void +put_cont (void *cls, int32_t success, const char *emsg) +{ + static int c = 0; + + if (success == GNUNET_OK) + { + c++; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records\n"); + GNUNET_break (0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + } + + if (c == 3) + { + res = 1; + returned_records = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All records created, starting iteration over zone `%s'\n", + GNUNET_short_h2s(&zone)); + zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, + &zone, + GNUNET_NAMESTORE_RF_NONE, + GNUNET_NAMESTORE_RF_NONE, + zone_proc, + &zone); + if (zi == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); + GNUNET_break (0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + } + } +} + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + int c; + struct GNUNET_NAMESTORE_RecordData * rd; + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + for (c = 0; c < count; c++) + { + rd[c].expiration = GNUNET_TIME_absolute_get(); + rd[c].record_type = 1111; + rd[c].data_size = 50; + rd[c].data = GNUNET_malloc(50); + memset ((char *) rd[c].data, 'a', 50); + } + return rd; +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + delete_existing_db(cfg); + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,&endbadly, NULL); + + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey != NULL); + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + GNUNET_CRYPTO_short_hash (&pubkey, sizeof (pubkey), &zone); + + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey2 = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey2 != NULL); + GNUNET_CRYPTO_rsa_key_get_public(privkey2, &pubkey2); + GNUNET_CRYPTO_short_hash (&pubkey2, sizeof (pubkey), &zone2); + + + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); + + GNUNET_asprintf(&s_name_1, "dummy1"); + s_rd_1 = create_record(1); + sig_1 = GNUNET_NAMESTORE_create_signature(privkey, s_rd_1[0].expiration ,s_name_1, s_rd_1, 1); + GNUNET_NAMESTORE_record_create(nsh, privkey, s_name_1, s_rd_1, &put_cont, NULL); + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n"); + GNUNET_asprintf(&s_name_2, "dummy2"); + s_rd_2 = create_record(1); + + sig_2 = GNUNET_NAMESTORE_create_signature(privkey, s_rd_2[0].expiration, s_name_2, s_rd_2, 1); + GNUNET_NAMESTORE_record_create(nsh, privkey, s_name_2, s_rd_2, &put_cont, NULL); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 3\n"); + /* name in different zone */ + GNUNET_asprintf(&s_name_3, "dummy3"); + s_rd_3 = create_record(1); + sig_3 = GNUNET_NAMESTORE_create_signature(privkey, s_rd_3[0].expiration, s_name_3, s_rd_3, 1); + GNUNET_NAMESTORE_record_put (nsh, &pubkey2, s_name_3, GNUNET_TIME_UNIT_FOREVER_ABS, 1, s_rd_3, sig_3, &put_cont, NULL); +} + +static int +check () +{ + static char *const argv[] = { "test_namestore_api_zone_iteration", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test_namestore_api_zone_iteration", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + + return ret; +} + +/* end of test_namestore_api_zone_iteration_specific_zone.c */ diff --git a/src/namestore/test_namestore_api_zone_iteration_stop.c b/src/namestore/test_namestore_api_zone_iteration_stop.c new file mode 100644 index 0000000..9f62c73 --- /dev/null +++ b/src/namestore/test_namestore_api_zone_iteration_stop.c @@ -0,0 +1,501 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file namestore/test_namestore_api_zone_iteration.c + * @brief testcase for zone iteration functionality: iterate of a specific zone + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" + +#define VERBOSE GNUNET_NO + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static GNUNET_SCHEDULER_TaskIdentifier stopiteration_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; +static GNUNET_HashCode zone; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey2; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey2; +static GNUNET_HashCode zone2; + +static struct GNUNET_NAMESTORE_ZoneIterator *zi; +static int res; +static int returned_records; + +struct GNUNET_CRYPTO_RsaSignature *sig_1; +char * s_name_1; +struct GNUNET_NAMESTORE_RecordData *s_rd_1; + +struct GNUNET_CRYPTO_RsaSignature *sig_2; +char * s_name_2; +struct GNUNET_NAMESTORE_RecordData *s_rd_2; + +struct GNUNET_CRYPTO_RsaSignature *sig_3; +char * s_name_3; +struct GNUNET_NAMESTORE_RecordData *s_rd_3; + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_destroy (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (stopiteration_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (stopiteration_task); + stopiteration_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + GNUNET_free_non_null(sig_1); + GNUNET_free_non_null(sig_2); + GNUNET_free_non_null(sig_3); + GNUNET_free_non_null(s_name_1); + GNUNET_free_non_null(s_name_2); + GNUNET_free_non_null(s_name_3); + + if (s_rd_1 != NULL) + { + GNUNET_free ((void *)s_rd_1->data); + GNUNET_free (s_rd_1); + } + if (s_rd_2 != NULL) + { + GNUNET_free ((void *)s_rd_2->data); + GNUNET_free (s_rd_2); + } + if (s_rd_3 != NULL) + { + GNUNET_free ((void *)s_rd_3->data); + GNUNET_free (s_rd_3); + } + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (privkey2 != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey2); + privkey2 = NULL; + + if (NULL != arm) + stop_arm(); + + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (stopiteration_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (stopiteration_task); + stopiteration_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (privkey2 != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey2); + privkey2 = NULL; + + GNUNET_free (sig_1); + GNUNET_free (sig_2); + GNUNET_free (sig_3); + GNUNET_free (s_name_1); + GNUNET_free (s_name_2); + GNUNET_free (s_name_3); + if (s_rd_1 != NULL) + { + GNUNET_free ((void *)s_rd_1->data); + GNUNET_free (s_rd_1); + } + if (s_rd_2 != NULL) + { + GNUNET_free ((void *)s_rd_2->data); + GNUNET_free (s_rd_2); + } + if (s_rd_3 != NULL) + { + GNUNET_free ((void *)s_rd_3->data); + GNUNET_free (s_rd_3); + } + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (NULL != arm) + stop_arm(); + if (returned_records == 1) + res = 0; + else + res = 1; + +} + +void zone_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + int failed = GNUNET_NO; + + if ((zone_key == NULL) && (name == NULL)) + { + GNUNET_break (3 == returned_records); + if (3 == returned_records) + res = 0; + else + res = 1; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received last result, iteration done after receing %u results\n",returned_records ); + GNUNET_SCHEDULER_add_now (&end, NULL); + } + else + { + + /* verify signature returned from name store */ + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(zone_key, expire, name, rd_count, rd, signature)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing results name %s \n", name); + if (0 == strcmp (name, s_name_1)) + { /* name_1 */ + if (rd_count == 1) + { + if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_1)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else + { + failed = GNUNET_YES; + GNUNET_break (0); + } + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(&pubkey, expire, s_name_1, 1, s_rd_1, signature)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else if (0 == strcmp (name, s_name_2)) + { /* name_2 */ + if (rd_count == 1) + { + if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_2)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else + { + failed = GNUNET_YES; + GNUNET_break (0); + } + + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(&pubkey, expire, s_name_2, 1, s_rd_2, signature)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else if (0 == strcmp (name, s_name_3)) + { /* name_3 */ + if (rd_count == 1) + { + if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_3)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else + { + failed = GNUNET_YES; + GNUNET_break (0); + } + if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(&pubkey2, expire, s_name_3, 1, s_rd_3, signature)) + { + failed = GNUNET_YES; + GNUNET_break (0); + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing result failed: got name `%s'\n", name); + res = 1; + GNUNET_break (0); + GNUNET_SCHEDULER_add_now (&end, NULL); + } + + if (failed == GNUNET_NO) + { + returned_records ++; + + if (1 == returned_records) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping zone iteration after %u received record \n",returned_records ); + GNUNET_NAMESTORE_zone_iteration_stop (zi); + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3), &end , NULL); + return; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to send the next result\n"); + GNUNET_NAMESTORE_zone_iterator_next (zi); + } + } + else + { + GNUNET_break (0); + GNUNET_SCHEDULER_add_now (&end, NULL); + } + } +} + +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } + +} + +void +put_cont (void *cls, int32_t success, const char *emsg) +{ + static int c = 0; + + if (success == GNUNET_OK) + { + c++; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records\n"); + GNUNET_break (0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + } + + if (c == 3) + { + res = 1; + returned_records = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All records created, starting iteration over all zones \n"); + zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, + NULL, + GNUNET_NAMESTORE_RF_NONE, + GNUNET_NAMESTORE_RF_NONE, + zone_proc, + &zone); + if (zi == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); + GNUNET_break (0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + } + } +} + +static struct GNUNET_NAMESTORE_RecordData * +create_record (int count) +{ + int c; + struct GNUNET_NAMESTORE_RecordData * rd; + rd = GNUNET_malloc (count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + for (c = 0; c < count; c++) + { + rd[c].expiration = GNUNET_TIME_absolute_get(); + rd[c].record_type = 1111; + rd[c].data_size = 50; + rd[c].data = GNUNET_malloc(50); + memset ((char *) rd[c].data, 'a', 50); + } + return rd; +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + delete_existing_db(cfg); + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,&endbadly, NULL); + + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey != NULL); + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + GNUNET_CRYPTO_hash(&pubkey, sizeof (pubkey), &zone); + + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey2 = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey2 != NULL); + GNUNET_CRYPTO_rsa_key_get_public(privkey2, &pubkey2); + GNUNET_CRYPTO_hash(&pubkey2, sizeof (pubkey), &zone2); + + + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); + + GNUNET_asprintf(&s_name_1, "dummy1"); + s_rd_1 = create_record(1); + sig_1 = GNUNET_NAMESTORE_create_signature(privkey, s_rd_1[0].expiration, s_name_1, s_rd_1, 1); + GNUNET_NAMESTORE_record_create(nsh, privkey, s_name_1, s_rd_1, &put_cont, NULL); + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n"); + GNUNET_asprintf(&s_name_2, "dummy2"); + s_rd_2 = create_record(1); + + sig_2 = GNUNET_NAMESTORE_create_signature(privkey, s_rd_2[0].expiration, s_name_2, s_rd_2, 1); + GNUNET_NAMESTORE_record_create(nsh, privkey, s_name_2, s_rd_2, &put_cont, NULL); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 3\n"); + /* name in different zone */ + GNUNET_asprintf(&s_name_3, "dummy3"); + s_rd_3 = create_record(1); + sig_3 = GNUNET_NAMESTORE_create_signature(privkey2, s_rd_3[0].expiration, s_name_3, s_rd_3, 1); + GNUNET_NAMESTORE_record_put (nsh, &pubkey2, s_name_3, GNUNET_TIME_UNIT_FOREVER_ABS, 1, s_rd_3, sig_3, &put_cont, NULL); +} + +static int +check () +{ + static char *const argv[] = { "test_namestore_api_zone_iteration", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test_namestore_api_zone_iteration", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + + return ret; +} + +/* end of test_namestore_api_zone_iteration.c */ diff --git a/src/namestore/test_namestore_api_zone_to_name.c b/src/namestore/test_namestore_api_zone_to_name.c new file mode 100644 index 0000000..6efbaf5 --- /dev/null +++ b/src/namestore/test_namestore_api_zone_to_name.c @@ -0,0 +1,288 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file namestore/test_namestore_api_zone_to_name.c + * @brief testcase for zone to name translation + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" +#include "gnunet_signatures.h" + +#define VERBOSE GNUNET_NO + +#define RECORDS 5 +#define TEST_RECORD_TYPE 1234 +#define TEST_RECORD_DATALEN 123 +#define TEST_RECORD_DATA 'a' + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; + +struct GNUNET_TIME_Absolute expire; + +static struct GNUNET_CRYPTO_ShortHashCode s_zone; +static struct GNUNET_CRYPTO_ShortHashCode s_zone_value; + +char * s_name; + +struct GNUNET_NAMESTORE_RecordData *s_rd; +struct GNUNET_CRYPTO_RsaSignature *s_signature; + +static int res; + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_destroy (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (NULL != arm) + stop_arm(); + + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (NULL != arm) + stop_arm(); +} + +void zone_to_name_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *n, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + int fail = GNUNET_NO; + + if ((zone_key == NULL) && (n == NULL) && (rd_count == 0) && (rd == NULL) && (signature == NULL)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No result found\n"); + res = 1; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result found: `%s'\n", n); + if ((n == NULL) || (0 != strcmp(n, s_name))) + { + fail = GNUNET_YES; + GNUNET_break (0); + } + if (rd_count != 1) + { + fail = GNUNET_YES; + GNUNET_break (0); + } + if ((zone_key == NULL) || (0 != memcmp (zone_key, &pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))) + { + fail = GNUNET_YES; + GNUNET_break (0); + } + if (fail == GNUNET_NO) + res = 0; + else + res = 1; + } + GNUNET_SCHEDULER_add_now(&end, NULL); +} + + +void +delete_existing_db (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *afsdir; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_file_test (afsdir)) + if (GNUNET_OK == GNUNET_DISK_directory_remove(afsdir)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted existing database `%s' \n", afsdir); + GNUNET_free (afsdir); + } + +} + + +void +put_cont (void *cls, int32_t success, const char *emsg) +{ + char *name = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + if (success == GNUNET_OK) + { + res = 0; + + /* create initial record */ + GNUNET_NAMESTORE_zone_to_name (nsh, &s_zone, &s_zone_value, zone_to_name_proc, NULL); + + } + else + { + res = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to put records for name `%s'\n", name); + GNUNET_SCHEDULER_add_now(&end, NULL); + } +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + delete_existing_db(cfg); + + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,endbadly, NULL); + GNUNET_asprintf(&s_name, "dummy"); + + + /* load privat key */ + char *hostkey_file; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_rsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey != NULL); + /* get public key */ + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + + /* zone hash */ + GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &s_zone); + GNUNET_CRYPTO_short_hash (s_name, strlen (s_name) + 1, &s_zone_value); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using PKEY `%s' \n", GNUNET_short_h2s (&s_zone_value)); + + struct GNUNET_NAMESTORE_RecordData rd; + rd.expiration = GNUNET_TIME_absolute_get(); + rd.record_type = GNUNET_NAMESTORE_TYPE_PKEY; + rd.data_size = sizeof (struct GNUNET_CRYPTO_ShortHashCode); + rd.data = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + memcpy ((char *) rd.data, &s_zone_value, sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + expire = GNUNET_TIME_absolute_get (); + s_signature = GNUNET_NAMESTORE_create_signature(privkey, rd.expiration, s_name, &rd, 1); + GNUNET_NAMESTORE_record_put(nsh, &pubkey, s_name, expire, 1, &rd, s_signature, put_cont, NULL); + + GNUNET_free ((void *) rd.data); +} + +static int +check () +{ + static char *const argv[] = { "test-namestore-api", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-namestore-api", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + return ret; +} + +/* end of test_namestore_api.c */ diff --git a/src/namestore/test_namestore_record_serialization.c b/src/namestore/test_namestore_record_serialization.c index 5ea345b..5e95253 100644 --- a/src/namestore/test_namestore_record_serialization.c +++ b/src/namestore/test_namestore_record_serialization.c @@ -36,15 +36,12 @@ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { - char * dest = NULL; size_t len; int c; - int elem = 0; int rd_count = 3; size_t data_len; struct GNUNET_NAMESTORE_RecordData src[rd_count]; - struct GNUNET_NAMESTORE_RecordData *dst = NULL; memset(src, '\0', rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); @@ -61,25 +58,27 @@ run (void *cls, char *const *args, const char *cfgfile, } res = 0; - len = GNUNET_NAMESTORE_records_serialize (&dest, rd_count, src); + len = GNUNET_NAMESTORE_records_get_size(rd_count, src); + char rd_ser[len]; + GNUNET_assert (len == GNUNET_NAMESTORE_records_serialize(rd_count, src, len, rd_ser)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Serialized data len: %u\n",len); - GNUNET_assert (dest != NULL); + GNUNET_assert (rd_ser != NULL); - elem = GNUNET_NAMESTORE_records_deserialize(&dst, dest, len); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deserialized elements: %u\n",elem); + struct GNUNET_NAMESTORE_RecordData dst[rd_count]; + GNUNET_assert (GNUNET_OK == GNUNET_NAMESTORE_records_deserialize (len, rd_ser, rd_count, dst)); - GNUNET_assert (elem == rd_count); GNUNET_assert (dst != NULL); - for (c = 0; c < elem; c++) + for (c = 0; c < rd_count; c++) { if (src[c].data_size != dst[c].data_size) { GNUNET_break (0); res = 1; } - if (GNUNET_TIME_absolute_get_difference(src[c].expiration, dst[c].expiration).rel_value != GNUNET_TIME_relative_get_zero().rel_value) + if (0 != GNUNET_TIME_absolute_get_difference(src[c].expiration, dst[c].expiration).rel_value) { GNUNET_break (0); res = 1; @@ -115,12 +114,12 @@ run (void *cls, char *const *args, const char *cfgfile, } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Element [%i]: EQUAL\n", c); - /* clean up */ - GNUNET_free((char *) dst[c].data); - GNUNET_free((char *) src[c].data); } - GNUNET_free (dest); - GNUNET_free (dst); + + for (c = 0; c < rd_count; c++) + { + GNUNET_free ((void *)src[c].data); + } } static int diff --git a/src/namestore/test_plugin_namestore.c b/src/namestore/test_plugin_namestore.c index 0b0008f..3e93d73 100644 --- a/src/namestore/test_plugin_namestore.c +++ b/src/namestore/test_plugin_namestore.c @@ -176,7 +176,7 @@ run (void *cls, char *const *args, const char *cfgfile, { struct GNUNET_NAMESTORE_PluginFunctions *nsp; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key; - GNUNET_HashCode zone; + struct GNUNET_CRYPTO_ShortHashCode zone; ok = 0; nsp = load_plugin (cfg); @@ -187,13 +187,16 @@ run (void *cls, char *const *args, const char *cfgfile, "Failed to initialize namestore. Database likely not setup, skipping test.\n"); return; } + put_record (nsp, 1); + get_record (nsp, 1); memset (&zone_key, 1, sizeof (zone_key)); - GNUNET_CRYPTO_hash (&zone_key, sizeof (zone_key), &zone); + GNUNET_CRYPTO_short_hash (&zone_key, sizeof (zone_key), &zone); nsp->delete_zone (nsp->cls, &zone); unload_plugin (nsp); + } @@ -235,8 +238,6 @@ main (int argc, char *argv[]) GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_plugin_namestore_%s.conf", plugin_name); - if (pos != plugin_name) - pos[0] = '.'; GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv, "test-plugin-namestore", "nohelp", options, &run, NULL); if (ok != 0) diff --git a/src/namestore/hostkey b/src/namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey Binary files differindex eac1d1e..eac1d1e 100644 --- a/src/namestore/hostkey +++ b/src/namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey diff --git a/src/namestore/zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey b/src/namestore/zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey Binary files differnew file mode 100644 index 0000000..871fc90 --- /dev/null +++ b/src/namestore/zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey |