diff options
Diffstat (limited to 'src/gns')
52 files changed, 15293 insertions, 5194 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index 10b9ff3..d4fcb6b 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am @@ -6,37 +6,202 @@ endif SUBDIRS = . $(NSS_SUBDIR) +EXTRA_DIST = \ + test_gns_defaults.conf \ + test_gns_simple_lookup.conf \ + test_gns_dht_default.conf \ + gns-helper-service-w32.conf \ + gnunet-gns-proxy-setup-ca \ + zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey \ + zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey \ + zonefiles/test_zonekey + if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols + DO_W32_HELPER = gnunet-gns-helper-service-w32 + DO_W32_NSP = libw32nsp.la + DO_W32_NSPTOOLS = w32nsp-install w32nsp-uninstall w32nsp-resolve + DO_W32_HS_CONF = gns-helper-service-w32.conf +else + USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 endif -pkgcfgdir= $(pkgdatadir)/config.d/ +pkgcfgdir = $(pkgdatadir)/config.d/ + +libexecdir= $(pkglibdir)/libexec/ plugindir = $(libdir)/gnunet pkgcfg_DATA = \ - gns.conf + gns.conf \ + $(DO_W32_HS_CONF) lib_LTLIBRARIES = \ - libgnunetgns.la + $(DO_W32_NSP) \ + libgnunetgns.la \ + libgnunetgns_common.la + if HAVE_MHD DO_FCFSD=gnunet-gns-fcfsd +if HAVE_GNUTLS DO_PROXY=gnunet-gns-proxy endif +endif + +libexec_PROGRAMS = \ + gnunet-service-gns $(DO_FCFSD) \ + $(DO_PROXY) \ + $(DO_W32_HELPER) \ + gnunet-dns2gns bin_PROGRAMS = \ - gnunet-service-gns \ - $(DO_FCFSD) \ - $(DO_PROXY) \ - gnunet-gns + $(DO_W32_NSPTOOLS) \ + gnunet-gns + +bin_SCRIPTS = gnunet-gns-proxy-setup-ca + +plugin_LTLIBRARIES = \ + libgnunet_plugin_block_gns.la + +gnunet_gns_SOURCES = \ + gnunet-gns.c +gnunet_gns_LDADD = \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(GN_LIBINTL) +gnunet_gns_DEPENDENCIES = \ + libgnunetgns.la + +gnunet_dns2gns_SOURCES = \ + gnunet-dns2gns.c +gnunet_dns2gns_LDADD = \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/dns/libgnunetdnsparser.la \ + $(top_builddir)/src/dns/libgnunetdnsstub.la \ + $(GN_LIBINTL) +gnunet_dns2gns_DEPENDENCIES = \ + libgnunetgns.la + +gnunet_gns_proxy_SOURCES = \ + gnunet-gns-proxy.c gns_proxy_proto.h +gnunet_gns_proxy_LDADD = -lmicrohttpd -lcurl -lgnutls \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) +gnunet_gns_proxy_DEPENDENCIES = \ + libgnunetgns.la + +gnunet_gns_helper_service_w32_SOURCES = \ + gnunet-gns-helper-service-w32.c +gnunet_gns_helper_service_w32_LDADD = \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) +gnunet_gns_helper_service_w32_DEPENDENCIES = \ + libgnunetgns.la + +w32nsp_install_SOURCES = \ + w32nsp-install.c +w32nsp_install_LDADD = -lws2_32 + +w32nsp_uninstall_SOURCES = \ + w32nsp-uninstall.c +w32nsp_uninstall_LDADD = -lws2_32 + +w32nsp_resolve_SOURCES = \ + w32nsp-resolve.c +w32nsp_resolve_LDADD = -lws2_32 + +gnunet_service_gns_SOURCES = \ + gnunet-service-gns.c \ + gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \ + gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h +gnunet_service_gns_LDADD = \ + -lm \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetgns_common.la \ + $(top_builddir)/src/dns/libgnunetdns.la \ + $(top_builddir)/src/dns/libgnunetdnsparser.la \ + $(top_builddir)/src/dht/libgnunetdht.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(USE_VPN) \ + $(GN_LIBINTL) +gnunet_service_gns_DEPENDENCIES = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetgns_common.la \ + $(top_builddir)/src/dns/libgnunetdns.la \ + $(top_builddir)/src/dns/libgnunetdnsparser.la \ + $(top_builddir)/src/dht/libgnunetdht.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(USE_VPN) + + + +gnunet_gns_fcfsd_SOURCES = \ + gnunet-gns-fcfsd.c +gnunet_gns_fcfsd_LDADD = -lmicrohttpd \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(GN_LIBINTL) +gnunet_gns_fcfsd_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +libw32nsp_la_SOURCES = \ + w32nsp.c +libw32nsp_la_LIBADD = \ + -lole32 -lws2_32 +libw32nsp_la_LDFLAGS = \ + -export-symbols $(top_srcdir)/src/gns/w32nsp.def \ + $(GN_LIB_LDFLAGS) + +libgnunetgns_la_SOURCES = \ + gns_api.c gns.h +libgnunetgns_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +libgnunetgns_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) +libgnunetgns_la_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + + +libgnunetgns_common_la_SOURCES = \ + gns_common.c gns_common.h +libgnunetgns_common_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) +libgnunetgns_common_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la +libgnunetgns_common_la_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la + + +libgnunet_plugin_block_gns_la_SOURCES = \ + plugin_block_gns.c +libgnunet_plugin_block_gns_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/block/libgnunetblock.la \ + $(top_builddir)/src/gns/libgnunetgns_common.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +libgnunet_plugin_block_gns_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) +libgnunet_plugin_block_gns_la_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetgns_common.la \ + $(top_builddir)/src/block/libgnunetblock.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la -#noinst_PROGRAMS = \ -# gnunet-gns-lookup check_PROGRAMS = \ test_gns_simple_shorten \ @@ -44,11 +209,22 @@ check_PROGRAMS = \ test_gns_simple_lookup \ test_gns_simple_delegated_lookup \ test_gns_simple_mx_lookup \ + test_gns_simple_srv_lookup \ test_gns_simple_zkey_lookup \ test_gns_dht_delegated_lookup \ test_gns_pseu_shorten \ test_gns_max_queries \ - test_gns_dht_threepeer + test_gns_cname_lookup \ + test_gns_ns_lookup \ + test_gns_revocation \ + test_gns_dht_three_peers + #test_gns_proxy + +if ENABLE_TEST_RUN +if LINUX +TESTS = $(check_PROGRAMS) +endif +endif # test_gns_simple_lookup @@ -56,21 +232,33 @@ check_PROGRAMS = \ # test_gns_dht_delegated_lookup -plugin_LTLIBRARIES = \ - libgnunet_plugin_block_gns.la - -test_gns_dht_threepeer_SOURCES = \ - test_gns_dht_threepeer.c -test_gns_dht_threepeer_LDADD = \ +#test_gns_proxy_SOURCES = \ +# test_gns_proxy.c +#test_gns_proxy_LDADD = -lmicrohttpd @LIBCURL@ \ +# $(top_builddir)/src/util/libgnunetutil.la \ +# $(top_builddir)/src/namestore/libgnunetnamestore.la \ +# $(top_builddir)/src/gns/libgnunetgns.la \ +# $(top_builddir)/src/testing/libgnunettesting.la +#test_gns_proxy_DEPENDENCIES = \ +# $(top_builddir)/src/util/libgnunetutil.la \ +# $(top_builddir)/src/namestore/libgnunetnamestore.la \ +# libgnunetgns.la \ +# $(top_builddir)/src/testing/libgnunettesting.la + +test_gns_dht_three_peers_SOURCES = \ + test_gns_dht_three_peers.c +test_gns_dht_three_peers_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gns/libgnunetgns.la \ - $(top_builddir)/src/testing/libgnunettesting.la -test_gns_dht_threepeer_DEPENDENCIES = \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/testbed/libgnunettestbed.la +test_gns_dht_three_peers_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ - $(top_builddir)/src/testing/libgnunettesting.la + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/testbed/libgnunettestbed.la test_gns_simple_lookup_SOURCES = \ test_gns_simple_lookup.c @@ -82,7 +270,7 @@ test_gns_simple_lookup_LDADD = \ test_gns_simple_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_simple_delegated_lookup_SOURCES = \ @@ -95,7 +283,7 @@ test_gns_simple_delegated_lookup_LDADD = \ test_gns_simple_delegated_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_simple_mx_lookup_SOURCES = \ @@ -108,8 +296,21 @@ test_gns_simple_mx_lookup_LDADD = \ test_gns_simple_mx_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la + +test_gns_simple_srv_lookup_SOURCES = \ + test_gns_simple_srv_lookup.c +test_gns_simple_srv_lookup_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la +test_gns_simple_srv_lookup_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la test_gns_simple_zkey_lookup_SOURCES = \ test_gns_simple_zkey_lookup.c @@ -121,7 +322,7 @@ test_gns_simple_zkey_lookup_LDADD = \ test_gns_simple_zkey_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_dht_delegated_lookup_SOURCES = \ @@ -136,7 +337,7 @@ test_gns_dht_delegated_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_simple_shorten_SOURCES = \ @@ -149,7 +350,7 @@ test_gns_simple_shorten_LDADD = \ test_gns_simple_shorten_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_simple_get_authority_SOURCES = \ @@ -162,7 +363,7 @@ test_gns_simple_get_authority_LDADD = \ test_gns_simple_get_authority_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la @@ -178,7 +379,7 @@ test_gns_pseu_shorten_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la @@ -192,83 +393,51 @@ test_gns_max_queries_LDADD = \ test_gns_max_queries_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la -gnunet_gns_SOURCES = \ - gnunet-gns.c -gnunet_gns_LDADD = \ - $(top_builddir)/src/gns/libgnunetgns.la \ +test_gns_cname_lookup_SOURCES = \ + test_gns_cname_lookup.c +test_gns_cname_lookup_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(GN_LIBINTL) -gnunet_gns_DEPENDENCIES = \ - libgnunetgns.la - -gnunet_gns_proxy_SOURCES = \ - gnunet-gns-proxy.c gns_proxy_proto.h -gnunet_gns_proxy_LDADD = -lmicrohttpd \ $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la +test_gns_cname_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) -gnunet_gns_proxy_DEPENDENCIES = \ - libgnunetgns.la + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la -gnunet_service_gns_SOURCES = \ - gnunet-service-gns.c \ - gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \ - gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h -gnunet_service_gns_LDADD = \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ + +test_gns_ns_lookup_SOURCES = \ + test_gns_ns_lookup.c +test_gns_ns_lookup_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/dns/libgnunetdns.la \ - $(top_builddir)/src/dns/libgnunetdnsparser.la \ - $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(GN_LIBINTL) -gnunet_service_gns_DEPENDENCIES = \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la +test_gns_ns_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/dns/libgnunetdns.la \ - $(top_builddir)/src/dns/libgnunetdnsparser.la \ - $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la -gnunet_gns_fcfsd_SOURCES = \ - gnunet-gns-fcfsd.c -gnunet_gns_fcfsd_LDADD = -lmicrohttpd \ +test_gns_revocation_SOURCES = \ + test_gns_revocation.c +test_gns_revocation_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(GN_LIBINTL) -gnunet_gns_fcfsd_DEPENDENCIES = \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la +test_gns_revocation_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la -libgnunetgns_la_SOURCES = \ - gns_api.c gns.h -libgnunetgns_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ - $(top_builddir)/src/namestore/libgnunetnamestore.la -libgnunetgns_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) -libgnunetgns_la_DEPENDENCIES = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la - -libgnunet_plugin_block_gns_la_SOURCES = \ - plugin_block_gns.c -libgnunet_plugin_block_gns_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/block/libgnunetblock.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la -libgnunet_plugin_block_gns_la_LDFLAGS = \ - $(GN_PLUGIN_LDFLAGS) -libgnunet_plugin_block_gns_la_DEPENDENCIES = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/block/libgnunetblock.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la #Build stub api #libgnunetnamestore_la_SOURCES = \ @@ -280,14 +449,5 @@ libgnunet_plugin_block_gns_la_DEPENDENCIES = \ #libgnunetnamestore_la_DEPENDENCIES = \ # $(top_builddir)/src/util/libgnunetutil.la -if ENABLE_TEST_RUN -if LINUX -TESTS = $(check_PROGRAMS) -endif -endif -EXTRA_DIST = \ - test_gns_defaults.conf \ - test_gns_simple_lookup.conf \ - test_gns_dht_default.conf diff --git a/src/gns/Makefile.in b/src/gns/Makefile.in index 5bdd92a..819f891 100644 --- a/src/gns/Makefile.in +++ b/src/gns/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -17,7 +17,25 @@ + VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -37,31 +55,35 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -bin_PROGRAMS = gnunet-service-gns$(EXEEXT) $(am__EXEEXT_1) \ - $(am__EXEEXT_2) gnunet-gns$(EXEEXT) +libexec_PROGRAMS = gnunet-service-gns$(EXEEXT) $(am__EXEEXT_2) \ + $(am__EXEEXT_3) $(am__EXEEXT_4) gnunet-dns2gns$(EXEEXT) +bin_PROGRAMS = $(am__EXEEXT_1) gnunet-gns$(EXEEXT) check_PROGRAMS = test_gns_simple_shorten$(EXEEXT) \ test_gns_simple_get_authority$(EXEEXT) \ test_gns_simple_lookup$(EXEEXT) \ test_gns_simple_delegated_lookup$(EXEEXT) \ test_gns_simple_mx_lookup$(EXEEXT) \ + test_gns_simple_srv_lookup$(EXEEXT) \ test_gns_simple_zkey_lookup$(EXEEXT) \ test_gns_dht_delegated_lookup$(EXEEXT) \ test_gns_pseu_shorten$(EXEEXT) test_gns_max_queries$(EXEEXT) \ - test_gns_dht_threepeer$(EXEEXT) + test_gns_cname_lookup$(EXEEXT) test_gns_ns_lookup$(EXEEXT) \ + test_gns_revocation$(EXEEXT) test_gns_dht_three_peers$(EXEEXT) subdir = src/gns DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/gns.conf.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/argz.m4 \ - $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libcurl.m4 \ - $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/libunistring.m4 $(top_srcdir)/m4/ltdl.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glib-2.0.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libcurl.m4 $(top_srcdir)/m4/libgcrypt.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ + $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -91,14 +113,21 @@ am__nobase_list = $(am__nobase_strip_setup); \ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ + "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am_libgnunet_plugin_block_gns_la_OBJECTS = plugin_block_gns.lo libgnunet_plugin_block_gns_la_OBJECTS = \ $(am_libgnunet_plugin_block_gns_la_OBJECTS) -AM_V_lt = $(am__v_lt_$(V)) -am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent libgnunet_plugin_block_gns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ @@ -110,30 +139,61 @@ libgnunetgns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetgns_la_LDFLAGS) $(LDFLAGS) \ -o $@ -@HAVE_MHD_TRUE@am__EXEEXT_1 = gnunet-gns-fcfsd$(EXEEXT) -@HAVE_MHD_TRUE@am__EXEEXT_2 = gnunet-gns-proxy$(EXEEXT) -PROGRAMS = $(bin_PROGRAMS) +am_libgnunetgns_common_la_OBJECTS = gns_common.lo +libgnunetgns_common_la_OBJECTS = $(am_libgnunetgns_common_la_OBJECTS) +libgnunetgns_common_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libgnunetgns_common_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +libw32nsp_la_DEPENDENCIES = +am_libw32nsp_la_OBJECTS = w32nsp.lo +libw32nsp_la_OBJECTS = $(am_libw32nsp_la_OBJECTS) +libw32nsp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libw32nsp_la_LDFLAGS) $(LDFLAGS) -o $@ +@MINGW_TRUE@am_libw32nsp_la_rpath = -rpath $(libdir) +@MINGW_TRUE@am__EXEEXT_1 = w32nsp-install$(EXEEXT) \ +@MINGW_TRUE@ w32nsp-uninstall$(EXEEXT) w32nsp-resolve$(EXEEXT) +@HAVE_MHD_TRUE@am__EXEEXT_2 = gnunet-gns-fcfsd$(EXEEXT) +@HAVE_GNUTLS_TRUE@@HAVE_MHD_TRUE@am__EXEEXT_3 = \ +@HAVE_GNUTLS_TRUE@@HAVE_MHD_TRUE@ gnunet-gns-proxy$(EXEEXT) +@MINGW_TRUE@am__EXEEXT_4 = gnunet-gns-helper-service-w32$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) +am_gnunet_dns2gns_OBJECTS = gnunet-dns2gns.$(OBJEXT) +gnunet_dns2gns_OBJECTS = $(am_gnunet_dns2gns_OBJECTS) +am__DEPENDENCIES_1 = am_gnunet_gns_OBJECTS = gnunet-gns.$(OBJEXT) gnunet_gns_OBJECTS = $(am_gnunet_gns_OBJECTS) -am__DEPENDENCIES_1 = am_gnunet_gns_fcfsd_OBJECTS = gnunet-gns-fcfsd.$(OBJEXT) gnunet_gns_fcfsd_OBJECTS = $(am_gnunet_gns_fcfsd_OBJECTS) +am_gnunet_gns_helper_service_w32_OBJECTS = \ + gnunet-gns-helper-service-w32.$(OBJEXT) +gnunet_gns_helper_service_w32_OBJECTS = \ + $(am_gnunet_gns_helper_service_w32_OBJECTS) am_gnunet_gns_proxy_OBJECTS = gnunet-gns-proxy.$(OBJEXT) gnunet_gns_proxy_OBJECTS = $(am_gnunet_gns_proxy_OBJECTS) am_gnunet_service_gns_OBJECTS = gnunet-service-gns.$(OBJEXT) \ gnunet-service-gns_resolver.$(OBJEXT) \ gnunet-service-gns_interceptor.$(OBJEXT) gnunet_service_gns_OBJECTS = $(am_gnunet_service_gns_OBJECTS) +am_test_gns_cname_lookup_OBJECTS = test_gns_cname_lookup.$(OBJEXT) +test_gns_cname_lookup_OBJECTS = $(am_test_gns_cname_lookup_OBJECTS) am_test_gns_dht_delegated_lookup_OBJECTS = \ test_gns_dht_delegated_lookup.$(OBJEXT) test_gns_dht_delegated_lookup_OBJECTS = \ $(am_test_gns_dht_delegated_lookup_OBJECTS) -am_test_gns_dht_threepeer_OBJECTS = test_gns_dht_threepeer.$(OBJEXT) -test_gns_dht_threepeer_OBJECTS = $(am_test_gns_dht_threepeer_OBJECTS) +am_test_gns_dht_three_peers_OBJECTS = \ + test_gns_dht_three_peers.$(OBJEXT) +test_gns_dht_three_peers_OBJECTS = \ + $(am_test_gns_dht_three_peers_OBJECTS) am_test_gns_max_queries_OBJECTS = test_gns_max_queries.$(OBJEXT) test_gns_max_queries_OBJECTS = $(am_test_gns_max_queries_OBJECTS) +am_test_gns_ns_lookup_OBJECTS = test_gns_ns_lookup.$(OBJEXT) +test_gns_ns_lookup_OBJECTS = $(am_test_gns_ns_lookup_OBJECTS) am_test_gns_pseu_shorten_OBJECTS = test_gns_pseu_shorten.$(OBJEXT) test_gns_pseu_shorten_OBJECTS = $(am_test_gns_pseu_shorten_OBJECTS) +am_test_gns_revocation_OBJECTS = test_gns_revocation.$(OBJEXT) +test_gns_revocation_OBJECTS = $(am_test_gns_revocation_OBJECTS) am_test_gns_simple_delegated_lookup_OBJECTS = \ test_gns_simple_delegated_lookup.$(OBJEXT) test_gns_simple_delegated_lookup_OBJECTS = \ @@ -152,10 +212,24 @@ am_test_gns_simple_shorten_OBJECTS = \ test_gns_simple_shorten.$(OBJEXT) test_gns_simple_shorten_OBJECTS = \ $(am_test_gns_simple_shorten_OBJECTS) +am_test_gns_simple_srv_lookup_OBJECTS = \ + test_gns_simple_srv_lookup.$(OBJEXT) +test_gns_simple_srv_lookup_OBJECTS = \ + $(am_test_gns_simple_srv_lookup_OBJECTS) am_test_gns_simple_zkey_lookup_OBJECTS = \ test_gns_simple_zkey_lookup.$(OBJEXT) test_gns_simple_zkey_lookup_OBJECTS = \ $(am_test_gns_simple_zkey_lookup_OBJECTS) +am_w32nsp_install_OBJECTS = w32nsp-install.$(OBJEXT) +w32nsp_install_OBJECTS = $(am_w32nsp_install_OBJECTS) +w32nsp_install_DEPENDENCIES = +am_w32nsp_resolve_OBJECTS = w32nsp-resolve.$(OBJEXT) +w32nsp_resolve_OBJECTS = $(am_w32nsp_resolve_OBJECTS) +w32nsp_resolve_DEPENDENCIES = +am_w32nsp_uninstall_OBJECTS = w32nsp-uninstall.$(OBJEXT) +w32nsp_uninstall_OBJECTS = $(am_w32nsp_uninstall_OBJECTS) +w32nsp_uninstall_DEPENDENCIES = +SCRIPTS = $(bin_SCRIPTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -166,50 +240,64 @@ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_$(V)) -am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_$(V)) -am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libgnunet_plugin_block_gns_la_SOURCES) \ - $(libgnunetgns_la_SOURCES) $(gnunet_gns_SOURCES) \ - $(gnunet_gns_fcfsd_SOURCES) $(gnunet_gns_proxy_SOURCES) \ - $(gnunet_service_gns_SOURCES) \ + $(libgnunetgns_la_SOURCES) $(libgnunetgns_common_la_SOURCES) \ + $(libw32nsp_la_SOURCES) $(gnunet_dns2gns_SOURCES) \ + $(gnunet_gns_SOURCES) $(gnunet_gns_fcfsd_SOURCES) \ + $(gnunet_gns_helper_service_w32_SOURCES) \ + $(gnunet_gns_proxy_SOURCES) $(gnunet_service_gns_SOURCES) \ + $(test_gns_cname_lookup_SOURCES) \ $(test_gns_dht_delegated_lookup_SOURCES) \ - $(test_gns_dht_threepeer_SOURCES) \ - $(test_gns_max_queries_SOURCES) \ + $(test_gns_dht_three_peers_SOURCES) \ + $(test_gns_max_queries_SOURCES) $(test_gns_ns_lookup_SOURCES) \ $(test_gns_pseu_shorten_SOURCES) \ + $(test_gns_revocation_SOURCES) \ $(test_gns_simple_delegated_lookup_SOURCES) \ $(test_gns_simple_get_authority_SOURCES) \ $(test_gns_simple_lookup_SOURCES) \ $(test_gns_simple_mx_lookup_SOURCES) \ $(test_gns_simple_shorten_SOURCES) \ - $(test_gns_simple_zkey_lookup_SOURCES) + $(test_gns_simple_srv_lookup_SOURCES) \ + $(test_gns_simple_zkey_lookup_SOURCES) \ + $(w32nsp_install_SOURCES) $(w32nsp_resolve_SOURCES) \ + $(w32nsp_uninstall_SOURCES) DIST_SOURCES = $(libgnunet_plugin_block_gns_la_SOURCES) \ - $(libgnunetgns_la_SOURCES) $(gnunet_gns_SOURCES) \ - $(gnunet_gns_fcfsd_SOURCES) $(gnunet_gns_proxy_SOURCES) \ - $(gnunet_service_gns_SOURCES) \ + $(libgnunetgns_la_SOURCES) $(libgnunetgns_common_la_SOURCES) \ + $(libw32nsp_la_SOURCES) $(gnunet_dns2gns_SOURCES) \ + $(gnunet_gns_SOURCES) $(gnunet_gns_fcfsd_SOURCES) \ + $(gnunet_gns_helper_service_w32_SOURCES) \ + $(gnunet_gns_proxy_SOURCES) $(gnunet_service_gns_SOURCES) \ + $(test_gns_cname_lookup_SOURCES) \ $(test_gns_dht_delegated_lookup_SOURCES) \ - $(test_gns_dht_threepeer_SOURCES) \ - $(test_gns_max_queries_SOURCES) \ + $(test_gns_dht_three_peers_SOURCES) \ + $(test_gns_max_queries_SOURCES) $(test_gns_ns_lookup_SOURCES) \ $(test_gns_pseu_shorten_SOURCES) \ + $(test_gns_revocation_SOURCES) \ $(test_gns_simple_delegated_lookup_SOURCES) \ $(test_gns_simple_get_authority_SOURCES) \ $(test_gns_simple_lookup_SOURCES) \ $(test_gns_simple_mx_lookup_SOURCES) \ $(test_gns_simple_shorten_SOURCES) \ - $(test_gns_simple_zkey_lookup_SOURCES) + $(test_gns_simple_srv_lookup_SOURCES) \ + $(test_gns_simple_zkey_lookup_SOURCES) \ + $(w32nsp_install_SOURCES) $(w32nsp_resolve_SOURCES) \ + $(w32nsp_uninstall_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ @@ -217,6 +305,11 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac DATA = $(pkgcfg_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive @@ -289,6 +382,10 @@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ @@ -299,6 +396,7 @@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GN_USER_HOME_DIR = @GN_USER_HOME_DIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ GREP = @GREP@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INCLTDL = @INCLTDL@ @@ -321,6 +419,8 @@ LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBGTOP_CFLAGS = @LIBGTOP_CFLAGS@ +LIBGTOP_LIBS = @LIBGTOP_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBLTDL = @LIBLTDL@ @@ -342,6 +442,7 @@ LT_CONFIG_H = @LT_CONFIG_H@ LT_DLLOADERS = @LT_DLLOADERS@ LT_DLPREOPEN = @LT_DLPREOPEN@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ @@ -351,6 +452,7 @@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ +NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ @@ -366,6 +468,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ @@ -397,6 +500,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ @@ -419,6 +523,7 @@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -429,10 +534,9 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ -libexecdir = @libexecdir@ +libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ ltdl_LIBOBJS = @ltdl_LIBOBJS@ ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@ mandir = @mandir@ @@ -450,6 +554,7 @@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ +svnversioncommand = @svnversioncommand@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ @@ -463,39 +568,227 @@ top_srcdir = @top_srcdir@ INCLUDES = -I$(top_srcdir)/src/include @HAVE_GLIBCNSS_TRUE@NSS_SUBDIR = nss SUBDIRS = . $(NSS_SUBDIR) +EXTRA_DIST = \ + test_gns_defaults.conf \ + test_gns_simple_lookup.conf \ + test_gns_dht_default.conf \ + gns-helper-service-w32.conf \ + gnunet-gns-proxy-setup-ca \ + zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey \ + zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey \ + zonefiles/test_zonekey + @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols +@MINGW_TRUE@DO_W32_HELPER = gnunet-gns-helper-service-w32 +@MINGW_TRUE@DO_W32_NSP = libw32nsp.la +@MINGW_TRUE@DO_W32_NSPTOOLS = w32nsp-install w32nsp-uninstall w32nsp-resolve +@MINGW_TRUE@DO_W32_HS_CONF = gns-helper-service-w32.conf +@MINGW_FALSE@USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 pkgcfgdir = $(pkgdatadir)/config.d/ plugindir = $(libdir)/gnunet pkgcfg_DATA = \ - gns.conf + gns.conf \ + $(DO_W32_HS_CONF) lib_LTLIBRARIES = \ - libgnunetgns.la + $(DO_W32_NSP) \ + libgnunetgns.la \ + libgnunetgns_common.la @HAVE_MHD_TRUE@DO_FCFSD = gnunet-gns-fcfsd -@HAVE_MHD_TRUE@DO_PROXY = gnunet-gns-proxy - -# test_gns_simple_lookup -# test_gns_simple_delegated_lookup -# test_gns_dht_delegated_lookup +@HAVE_GNUTLS_TRUE@@HAVE_MHD_TRUE@DO_PROXY = gnunet-gns-proxy +bin_SCRIPTS = gnunet-gns-proxy-setup-ca plugin_LTLIBRARIES = \ libgnunet_plugin_block_gns.la -test_gns_dht_threepeer_SOURCES = \ - test_gns_dht_threepeer.c +gnunet_gns_SOURCES = \ + gnunet-gns.c -test_gns_dht_threepeer_LDADD = \ +gnunet_gns_LDADD = \ + $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(GN_LIBINTL) + +gnunet_gns_DEPENDENCIES = \ + libgnunetgns.la + +gnunet_dns2gns_SOURCES = \ + gnunet-dns2gns.c + +gnunet_dns2gns_LDADD = \ $(top_builddir)/src/gns/libgnunetgns.la \ - $(top_builddir)/src/testing/libgnunettesting.la + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/dns/libgnunetdnsparser.la \ + $(top_builddir)/src/dns/libgnunetdnsstub.la \ + $(GN_LIBINTL) + +gnunet_dns2gns_DEPENDENCIES = \ + libgnunetgns.la -test_gns_dht_threepeer_DEPENDENCIES = \ +gnunet_gns_proxy_SOURCES = \ + gnunet-gns-proxy.c gns_proxy_proto.h + +gnunet_gns_proxy_LDADD = -lmicrohttpd -lcurl -lgnutls \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) + +gnunet_gns_proxy_DEPENDENCIES = \ + libgnunetgns.la + +gnunet_gns_helper_service_w32_SOURCES = \ + gnunet-gns-helper-service-w32.c + +gnunet_gns_helper_service_w32_LDADD = \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) + +gnunet_gns_helper_service_w32_DEPENDENCIES = \ + libgnunetgns.la + +w32nsp_install_SOURCES = \ + w32nsp-install.c + +w32nsp_install_LDADD = -lws2_32 +w32nsp_uninstall_SOURCES = \ + w32nsp-uninstall.c + +w32nsp_uninstall_LDADD = -lws2_32 +w32nsp_resolve_SOURCES = \ + w32nsp-resolve.c + +w32nsp_resolve_LDADD = -lws2_32 +gnunet_service_gns_SOURCES = \ + gnunet-service-gns.c \ + gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \ + gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h + +gnunet_service_gns_LDADD = \ + -lm \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetgns_common.la \ + $(top_builddir)/src/dns/libgnunetdns.la \ + $(top_builddir)/src/dns/libgnunetdnsparser.la \ + $(top_builddir)/src/dht/libgnunetdht.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(USE_VPN) \ + $(GN_LIBINTL) + +gnunet_service_gns_DEPENDENCIES = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetgns_common.la \ + $(top_builddir)/src/dns/libgnunetdns.la \ + $(top_builddir)/src/dns/libgnunetdnsparser.la \ + $(top_builddir)/src/dht/libgnunetdht.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(USE_VPN) + +gnunet_gns_fcfsd_SOURCES = \ + gnunet-gns-fcfsd.c + +gnunet_gns_fcfsd_LDADD = -lmicrohttpd \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(GN_LIBINTL) + +gnunet_gns_fcfsd_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +libw32nsp_la_SOURCES = \ + w32nsp.c + +libw32nsp_la_LIBADD = \ + -lole32 -lws2_32 + +libw32nsp_la_LDFLAGS = \ + -export-symbols $(top_srcdir)/src/gns/w32nsp.def \ + $(GN_LIB_LDFLAGS) + +libgnunetgns_la_SOURCES = \ + gns_api.c gns.h + +libgnunetgns_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +libgnunetgns_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) + +libgnunetgns_la_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +libgnunetgns_common_la_SOURCES = \ + gns_common.c gns_common.h + +libgnunetgns_common_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) + +libgnunetgns_common_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la + +libgnunetgns_common_la_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la + +libgnunet_plugin_block_gns_la_SOURCES = \ + plugin_block_gns.c + +libgnunet_plugin_block_gns_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/block/libgnunetblock.la \ + $(top_builddir)/src/gns/libgnunetgns_common.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +libgnunet_plugin_block_gns_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + +libgnunet_plugin_block_gns_la_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetgns_common.la \ + $(top_builddir)/src/block/libgnunetblock.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +@ENABLE_TEST_RUN_TRUE@@LINUX_TRUE@TESTS = $(check_PROGRAMS) + +# test_gns_simple_lookup +# test_gns_simple_delegated_lookup +# test_gns_dht_delegated_lookup + +#test_gns_proxy_SOURCES = \ +# test_gns_proxy.c +#test_gns_proxy_LDADD = -lmicrohttpd @LIBCURL@ \ +# $(top_builddir)/src/util/libgnunetutil.la \ +# $(top_builddir)/src/namestore/libgnunetnamestore.la \ +# $(top_builddir)/src/gns/libgnunetgns.la \ +# $(top_builddir)/src/testing/libgnunettesting.la +#test_gns_proxy_DEPENDENCIES = \ +# $(top_builddir)/src/util/libgnunetutil.la \ +# $(top_builddir)/src/namestore/libgnunetnamestore.la \ +# libgnunetgns.la \ +# $(top_builddir)/src/testing/libgnunettesting.la +test_gns_dht_three_peers_SOURCES = \ + test_gns_dht_three_peers.c + +test_gns_dht_three_peers_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gns/libgnunetgns.la \ - $(top_builddir)/src/testing/libgnunettesting.la + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/testbed/libgnunettestbed.la + +test_gns_dht_three_peers_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/testbed/libgnunettestbed.la test_gns_simple_lookup_SOURCES = \ test_gns_simple_lookup.c @@ -509,7 +802,7 @@ test_gns_simple_lookup_LDADD = \ test_gns_simple_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_simple_delegated_lookup_SOURCES = \ @@ -524,7 +817,7 @@ test_gns_simple_delegated_lookup_LDADD = \ test_gns_simple_delegated_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_simple_mx_lookup_SOURCES = \ @@ -539,9 +832,24 @@ test_gns_simple_mx_lookup_LDADD = \ test_gns_simple_mx_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la + +test_gns_simple_srv_lookup_SOURCES = \ + test_gns_simple_srv_lookup.c + +test_gns_simple_srv_lookup_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la +test_gns_simple_srv_lookup_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la + test_gns_simple_zkey_lookup_SOURCES = \ test_gns_simple_zkey_lookup.c @@ -554,7 +862,7 @@ test_gns_simple_zkey_lookup_LDADD = \ test_gns_simple_zkey_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_dht_delegated_lookup_SOURCES = \ @@ -571,7 +879,7 @@ test_gns_dht_delegated_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_simple_shorten_SOURCES = \ @@ -586,7 +894,7 @@ test_gns_simple_shorten_LDADD = \ test_gns_simple_shorten_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_simple_get_authority_SOURCES = \ @@ -601,7 +909,7 @@ test_gns_simple_get_authority_LDADD = \ test_gns_simple_get_authority_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_pseu_shorten_SOURCES = \ @@ -618,7 +926,7 @@ test_gns_pseu_shorten_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la test_gns_max_queries_SOURCES = \ @@ -633,111 +941,53 @@ test_gns_max_queries_LDADD = \ test_gns_max_queries_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ + libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la -gnunet_gns_SOURCES = \ - gnunet-gns.c +test_gns_cname_lookup_SOURCES = \ + test_gns_cname_lookup.c -gnunet_gns_LDADD = \ - $(top_builddir)/src/gns/libgnunetgns.la \ +test_gns_cname_lookup_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(GN_LIBINTL) - -gnunet_gns_DEPENDENCIES = \ - libgnunetgns.la - -gnunet_gns_proxy_SOURCES = \ - gnunet-gns-proxy.c gns_proxy_proto.h - -gnunet_gns_proxy_LDADD = -lmicrohttpd \ $(top_builddir)/src/gns/libgnunetgns.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) - -gnunet_gns_proxy_DEPENDENCIES = \ - libgnunetgns.la - -gnunet_service_gns_SOURCES = \ - gnunet-service-gns.c \ - gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \ - gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h - -gnunet_service_gns_LDADD = \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/dns/libgnunetdns.la \ - $(top_builddir)/src/dns/libgnunetdnsparser.la \ - $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(GN_LIBINTL) + $(top_builddir)/src/testing/libgnunettesting.la -gnunet_service_gns_DEPENDENCIES = \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ +test_gns_cname_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/dns/libgnunetdns.la \ - $(top_builddir)/src/dns/libgnunetdnsparser.la \ - $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la -gnunet_gns_fcfsd_SOURCES = \ - gnunet-gns-fcfsd.c +test_gns_ns_lookup_SOURCES = \ + test_gns_ns_lookup.c -gnunet_gns_fcfsd_LDADD = -lmicrohttpd \ +test_gns_ns_lookup_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(GN_LIBINTL) + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la -gnunet_gns_fcfsd_DEPENDENCIES = \ +test_gns_ns_lookup_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la - -libgnunetgns_la_SOURCES = \ - gns_api.c gns.h - -libgnunetgns_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ - $(top_builddir)/src/namestore/libgnunetnamestore.la - -libgnunetgns_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) - -libgnunetgns_la_DEPENDENCIES = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la -libgnunet_plugin_block_gns_la_SOURCES = \ - plugin_block_gns.c +test_gns_revocation_SOURCES = \ + test_gns_revocation.c -libgnunet_plugin_block_gns_la_LIBADD = \ +test_gns_revocation_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/block/libgnunetblock.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la - -libgnunet_plugin_block_gns_la_LDFLAGS = \ - $(GN_PLUGIN_LDFLAGS) + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la -libgnunet_plugin_block_gns_la_DEPENDENCIES = \ +test_gns_revocation_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/block/libgnunetblock.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la - - -#Build stub api -#libgnunetnamestore_la_SOURCES = \ -# namestore_stub_api.c -#libgnunetnamestore_la_LIBADD = \ -# $(top_builddir)/src/util/libgnunetutil.la $(XLIB) -#libgnunetnamestore_la_LDFLAGS = \ -# $(GN_LIB_LDFLAGS) -#libgnunetnamestore_la_DEPENDENCIES = \ -# $(top_builddir)/src/util/libgnunetutil.la -@ENABLE_TEST_RUN_TRUE@@LINUX_TRUE@TESTS = $(check_PROGRAMS) -EXTRA_DIST = \ - test_gns_defaults.conf \ - test_gns_simple_lookup.conf \ - test_gns_dht_default.conf + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + libgnunetgns.la \ + $(top_builddir)/src/testing/libgnunettesting.la all: all-recursive @@ -777,7 +1027,6 @@ gns.conf: $(top_builddir)/config.status $(srcdir)/gns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ @@ -785,6 +1034,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } @@ -808,7 +1059,6 @@ clean-libLTLIBRARIES: done install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ @@ -816,6 +1066,8 @@ install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } @@ -837,14 +1089,21 @@ clean-pluginLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libgnunet_plugin_block_gns.la: $(libgnunet_plugin_block_gns_la_OBJECTS) $(libgnunet_plugin_block_gns_la_DEPENDENCIES) +libgnunet_plugin_block_gns.la: $(libgnunet_plugin_block_gns_la_OBJECTS) $(libgnunet_plugin_block_gns_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_block_gns_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_block_gns_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_block_gns_la_OBJECTS) $(libgnunet_plugin_block_gns_la_LIBADD) $(LIBS) -libgnunetgns.la: $(libgnunetgns_la_OBJECTS) $(libgnunetgns_la_DEPENDENCIES) +libgnunetgns.la: $(libgnunetgns_la_OBJECTS) $(libgnunetgns_la_DEPENDENCIES) $(EXTRA_libgnunetgns_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetgns_la_LINK) -rpath $(libdir) $(libgnunetgns_la_OBJECTS) $(libgnunetgns_la_LIBADD) $(LIBS) +libgnunetgns_common.la: $(libgnunetgns_common_la_OBJECTS) $(libgnunetgns_common_la_DEPENDENCIES) $(EXTRA_libgnunetgns_common_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgnunetgns_common_la_LINK) -rpath $(libdir) $(libgnunetgns_common_la_OBJECTS) $(libgnunetgns_common_la_LIBADD) $(LIBS) +libw32nsp.la: $(libw32nsp_la_OBJECTS) $(libw32nsp_la_DEPENDENCIES) $(EXTRA_libw32nsp_la_DEPENDENCIES) + $(AM_V_CCLD)$(libw32nsp_la_LINK) $(am_libw32nsp_la_rpath) $(libw32nsp_la_OBJECTS) $(libw32nsp_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) - test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ @@ -893,48 +1152,156 @@ clean-checkPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list -gnunet-gns$(EXEEXT): $(gnunet_gns_OBJECTS) $(gnunet_gns_DEPENDENCIES) +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +gnunet-dns2gns$(EXEEXT): $(gnunet_dns2gns_OBJECTS) $(gnunet_dns2gns_DEPENDENCIES) $(EXTRA_gnunet_dns2gns_DEPENDENCIES) + @rm -f gnunet-dns2gns$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gnunet_dns2gns_OBJECTS) $(gnunet_dns2gns_LDADD) $(LIBS) +gnunet-gns$(EXEEXT): $(gnunet_gns_OBJECTS) $(gnunet_gns_DEPENDENCIES) $(EXTRA_gnunet_gns_DEPENDENCIES) @rm -f gnunet-gns$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_gns_OBJECTS) $(gnunet_gns_LDADD) $(LIBS) -gnunet-gns-fcfsd$(EXEEXT): $(gnunet_gns_fcfsd_OBJECTS) $(gnunet_gns_fcfsd_DEPENDENCIES) +gnunet-gns-fcfsd$(EXEEXT): $(gnunet_gns_fcfsd_OBJECTS) $(gnunet_gns_fcfsd_DEPENDENCIES) $(EXTRA_gnunet_gns_fcfsd_DEPENDENCIES) @rm -f gnunet-gns-fcfsd$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_gns_fcfsd_OBJECTS) $(gnunet_gns_fcfsd_LDADD) $(LIBS) -gnunet-gns-proxy$(EXEEXT): $(gnunet_gns_proxy_OBJECTS) $(gnunet_gns_proxy_DEPENDENCIES) +gnunet-gns-helper-service-w32$(EXEEXT): $(gnunet_gns_helper_service_w32_OBJECTS) $(gnunet_gns_helper_service_w32_DEPENDENCIES) $(EXTRA_gnunet_gns_helper_service_w32_DEPENDENCIES) + @rm -f gnunet-gns-helper-service-w32$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gnunet_gns_helper_service_w32_OBJECTS) $(gnunet_gns_helper_service_w32_LDADD) $(LIBS) +gnunet-gns-proxy$(EXEEXT): $(gnunet_gns_proxy_OBJECTS) $(gnunet_gns_proxy_DEPENDENCIES) $(EXTRA_gnunet_gns_proxy_DEPENDENCIES) @rm -f gnunet-gns-proxy$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_gns_proxy_OBJECTS) $(gnunet_gns_proxy_LDADD) $(LIBS) -gnunet-service-gns$(EXEEXT): $(gnunet_service_gns_OBJECTS) $(gnunet_service_gns_DEPENDENCIES) +gnunet-service-gns$(EXEEXT): $(gnunet_service_gns_OBJECTS) $(gnunet_service_gns_DEPENDENCIES) $(EXTRA_gnunet_service_gns_DEPENDENCIES) @rm -f gnunet-service-gns$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_gns_OBJECTS) $(gnunet_service_gns_LDADD) $(LIBS) -test_gns_dht_delegated_lookup$(EXEEXT): $(test_gns_dht_delegated_lookup_OBJECTS) $(test_gns_dht_delegated_lookup_DEPENDENCIES) +test_gns_cname_lookup$(EXEEXT): $(test_gns_cname_lookup_OBJECTS) $(test_gns_cname_lookup_DEPENDENCIES) $(EXTRA_test_gns_cname_lookup_DEPENDENCIES) + @rm -f test_gns_cname_lookup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_gns_cname_lookup_OBJECTS) $(test_gns_cname_lookup_LDADD) $(LIBS) +test_gns_dht_delegated_lookup$(EXEEXT): $(test_gns_dht_delegated_lookup_OBJECTS) $(test_gns_dht_delegated_lookup_DEPENDENCIES) $(EXTRA_test_gns_dht_delegated_lookup_DEPENDENCIES) @rm -f test_gns_dht_delegated_lookup$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gns_dht_delegated_lookup_OBJECTS) $(test_gns_dht_delegated_lookup_LDADD) $(LIBS) -test_gns_dht_threepeer$(EXEEXT): $(test_gns_dht_threepeer_OBJECTS) $(test_gns_dht_threepeer_DEPENDENCIES) - @rm -f test_gns_dht_threepeer$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_gns_dht_threepeer_OBJECTS) $(test_gns_dht_threepeer_LDADD) $(LIBS) -test_gns_max_queries$(EXEEXT): $(test_gns_max_queries_OBJECTS) $(test_gns_max_queries_DEPENDENCIES) +test_gns_dht_three_peers$(EXEEXT): $(test_gns_dht_three_peers_OBJECTS) $(test_gns_dht_three_peers_DEPENDENCIES) $(EXTRA_test_gns_dht_three_peers_DEPENDENCIES) + @rm -f test_gns_dht_three_peers$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_gns_dht_three_peers_OBJECTS) $(test_gns_dht_three_peers_LDADD) $(LIBS) +test_gns_max_queries$(EXEEXT): $(test_gns_max_queries_OBJECTS) $(test_gns_max_queries_DEPENDENCIES) $(EXTRA_test_gns_max_queries_DEPENDENCIES) @rm -f test_gns_max_queries$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gns_max_queries_OBJECTS) $(test_gns_max_queries_LDADD) $(LIBS) -test_gns_pseu_shorten$(EXEEXT): $(test_gns_pseu_shorten_OBJECTS) $(test_gns_pseu_shorten_DEPENDENCIES) +test_gns_ns_lookup$(EXEEXT): $(test_gns_ns_lookup_OBJECTS) $(test_gns_ns_lookup_DEPENDENCIES) $(EXTRA_test_gns_ns_lookup_DEPENDENCIES) + @rm -f test_gns_ns_lookup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_gns_ns_lookup_OBJECTS) $(test_gns_ns_lookup_LDADD) $(LIBS) +test_gns_pseu_shorten$(EXEEXT): $(test_gns_pseu_shorten_OBJECTS) $(test_gns_pseu_shorten_DEPENDENCIES) $(EXTRA_test_gns_pseu_shorten_DEPENDENCIES) @rm -f test_gns_pseu_shorten$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gns_pseu_shorten_OBJECTS) $(test_gns_pseu_shorten_LDADD) $(LIBS) -test_gns_simple_delegated_lookup$(EXEEXT): $(test_gns_simple_delegated_lookup_OBJECTS) $(test_gns_simple_delegated_lookup_DEPENDENCIES) +test_gns_revocation$(EXEEXT): $(test_gns_revocation_OBJECTS) $(test_gns_revocation_DEPENDENCIES) $(EXTRA_test_gns_revocation_DEPENDENCIES) + @rm -f test_gns_revocation$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_gns_revocation_OBJECTS) $(test_gns_revocation_LDADD) $(LIBS) +test_gns_simple_delegated_lookup$(EXEEXT): $(test_gns_simple_delegated_lookup_OBJECTS) $(test_gns_simple_delegated_lookup_DEPENDENCIES) $(EXTRA_test_gns_simple_delegated_lookup_DEPENDENCIES) @rm -f test_gns_simple_delegated_lookup$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gns_simple_delegated_lookup_OBJECTS) $(test_gns_simple_delegated_lookup_LDADD) $(LIBS) -test_gns_simple_get_authority$(EXEEXT): $(test_gns_simple_get_authority_OBJECTS) $(test_gns_simple_get_authority_DEPENDENCIES) +test_gns_simple_get_authority$(EXEEXT): $(test_gns_simple_get_authority_OBJECTS) $(test_gns_simple_get_authority_DEPENDENCIES) $(EXTRA_test_gns_simple_get_authority_DEPENDENCIES) @rm -f test_gns_simple_get_authority$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gns_simple_get_authority_OBJECTS) $(test_gns_simple_get_authority_LDADD) $(LIBS) -test_gns_simple_lookup$(EXEEXT): $(test_gns_simple_lookup_OBJECTS) $(test_gns_simple_lookup_DEPENDENCIES) +test_gns_simple_lookup$(EXEEXT): $(test_gns_simple_lookup_OBJECTS) $(test_gns_simple_lookup_DEPENDENCIES) $(EXTRA_test_gns_simple_lookup_DEPENDENCIES) @rm -f test_gns_simple_lookup$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gns_simple_lookup_OBJECTS) $(test_gns_simple_lookup_LDADD) $(LIBS) -test_gns_simple_mx_lookup$(EXEEXT): $(test_gns_simple_mx_lookup_OBJECTS) $(test_gns_simple_mx_lookup_DEPENDENCIES) +test_gns_simple_mx_lookup$(EXEEXT): $(test_gns_simple_mx_lookup_OBJECTS) $(test_gns_simple_mx_lookup_DEPENDENCIES) $(EXTRA_test_gns_simple_mx_lookup_DEPENDENCIES) @rm -f test_gns_simple_mx_lookup$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gns_simple_mx_lookup_OBJECTS) $(test_gns_simple_mx_lookup_LDADD) $(LIBS) -test_gns_simple_shorten$(EXEEXT): $(test_gns_simple_shorten_OBJECTS) $(test_gns_simple_shorten_DEPENDENCIES) +test_gns_simple_shorten$(EXEEXT): $(test_gns_simple_shorten_OBJECTS) $(test_gns_simple_shorten_DEPENDENCIES) $(EXTRA_test_gns_simple_shorten_DEPENDENCIES) @rm -f test_gns_simple_shorten$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gns_simple_shorten_OBJECTS) $(test_gns_simple_shorten_LDADD) $(LIBS) -test_gns_simple_zkey_lookup$(EXEEXT): $(test_gns_simple_zkey_lookup_OBJECTS) $(test_gns_simple_zkey_lookup_DEPENDENCIES) +test_gns_simple_srv_lookup$(EXEEXT): $(test_gns_simple_srv_lookup_OBJECTS) $(test_gns_simple_srv_lookup_DEPENDENCIES) $(EXTRA_test_gns_simple_srv_lookup_DEPENDENCIES) + @rm -f test_gns_simple_srv_lookup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_gns_simple_srv_lookup_OBJECTS) $(test_gns_simple_srv_lookup_LDADD) $(LIBS) +test_gns_simple_zkey_lookup$(EXEEXT): $(test_gns_simple_zkey_lookup_OBJECTS) $(test_gns_simple_zkey_lookup_DEPENDENCIES) $(EXTRA_test_gns_simple_zkey_lookup_DEPENDENCIES) @rm -f test_gns_simple_zkey_lookup$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gns_simple_zkey_lookup_OBJECTS) $(test_gns_simple_zkey_lookup_LDADD) $(LIBS) +w32nsp-install$(EXEEXT): $(w32nsp_install_OBJECTS) $(w32nsp_install_DEPENDENCIES) $(EXTRA_w32nsp_install_DEPENDENCIES) + @rm -f w32nsp-install$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(w32nsp_install_OBJECTS) $(w32nsp_install_LDADD) $(LIBS) +w32nsp-resolve$(EXEEXT): $(w32nsp_resolve_OBJECTS) $(w32nsp_resolve_DEPENDENCIES) $(EXTRA_w32nsp_resolve_DEPENDENCIES) + @rm -f w32nsp-resolve$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(w32nsp_resolve_OBJECTS) $(w32nsp_resolve_LDADD) $(LIBS) +w32nsp-uninstall$(EXEEXT): $(w32nsp_uninstall_OBJECTS) $(w32nsp_uninstall_DEPENDENCIES) $(EXTRA_w32nsp_uninstall_DEPENDENCIES) + @rm -f w32nsp-uninstall$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(w32nsp_uninstall_OBJECTS) $(w32nsp_uninstall_LDADD) $(LIBS) +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -943,47 +1310,55 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gns_api.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gns_common.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-dns2gns.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-gns-fcfsd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-gns-helper-service-w32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-gns-proxy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-gns.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-gns.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-gns_interceptor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-gns_resolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_block_gns.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_cname_lookup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_dht_delegated_lookup.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_dht_threepeer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_dht_three_peers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_max_queries.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_ns_lookup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_pseu_shorten.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_revocation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_delegated_lookup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_get_authority.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_lookup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_mx_lookup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_shorten.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_srv_lookup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_zkey_lookup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32nsp-install.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32nsp-resolve.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32nsp-uninstall.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32nsp.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo @@ -992,8 +1367,11 @@ 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=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ @@ -1007,9 +1385,7 @@ 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 + dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. @@ -1227,14 +1603,15 @@ check-TESTS: $(TESTS) fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ - echo "$$grn$$dashes"; \ + col="$$grn"; \ else \ - echo "$$red$$dashes"; \ + col="$$red"; \ fi; \ - echo "$$banner"; \ - test -z "$$skipped" || echo "$$skipped"; \ - test -z "$$report" || echo "$$report"; \ - echo "$$dashes$$std"; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi @@ -1270,13 +1647,10 @@ distdir: $(DISTFILES) done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ - test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ @@ -1300,12 +1674,12 @@ check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-recursive -all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)"; do \ + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive @@ -1318,10 +1692,15 @@ install-am: all-am installcheck: installcheck-recursive install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: @@ -1336,8 +1715,8 @@ maintainer-clean-generic: clean: clean-recursive clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ - clean-libLTLIBRARIES clean-libtool clean-pluginLTLIBRARIES \ - mostlyclean-am + clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ + clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) @@ -1363,7 +1742,8 @@ install-dvi: install-dvi-recursive install-dvi-am: -install-exec-am: install-binPROGRAMS install-libLTLIBRARIES +install-exec-am: install-binPROGRAMS install-binSCRIPTS \ + install-libLTLIBRARIES install-libexecPROGRAMS install-html: install-html-recursive @@ -1403,7 +1783,8 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ +uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ + uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \ @@ -1412,13 +1793,14 @@ uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-TESTS check-am clean clean-binPROGRAMS \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ - clean-libtool clean-pluginLTLIBRARIES ctags ctags-recursive \ - 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 \ + clean-libexecPROGRAMS clean-libtool clean-pluginLTLIBRARIES \ + ctags ctags-recursive 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-binSCRIPTS 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-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ @@ -1426,9 +1808,21 @@ uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am uninstall-binPROGRAMS \ - uninstall-libLTLIBRARIES uninstall-pkgcfgDATA \ + uninstall-binSCRIPTS uninstall-libLTLIBRARIES \ + uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES + #test_gns_proxy + +#Build stub api +#libgnunetnamestore_la_SOURCES = \ +# namestore_stub_api.c +#libgnunetnamestore_la_LIBADD = \ +# $(top_builddir)/src/util/libgnunetutil.la $(XLIB) +#libgnunetnamestore_la_LDFLAGS = \ +# $(GN_LIB_LDFLAGS) +#libgnunetnamestore_la_DEPENDENCIES = \ +# $(top_builddir)/src/util/libgnunetutil.la # 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/gns/gns-helper-service-w32.conf b/src/gns/gns-helper-service-w32.conf new file mode 100644 index 0000000..4865217 --- /dev/null +++ b/src/gns/gns-helper-service-w32.conf @@ -0,0 +1,4 @@ +[gns-helper-service-w32] +AUTOSTART = YES +BINARY = gnunet-gns-helper-service-w32 +PORT = 5353 diff --git a/src/gns/gns.conf.in b/src/gns/gns.conf.in index 80fb8c8..a6075f3 100644 --- a/src/gns/gns.conf.in +++ b/src/gns/gns.conf.in @@ -2,23 +2,72 @@ AUTOSTART = YES HOSTNAME = localhost HOME = $SERVICEHOME -CONFIG = $DEFAULTCONFIG BINARY = gnunet-service-gns UNIXPATH = /tmp/gnunet-service-gns.sock +@UNIXONLY@PORT = 2102 + +# Where to store the key for the Master zone ZONEKEY = $SERVICEHOME/gns/zonekey.zkey + +# Where to store the key for the Private zone +PRIVATE_ZONEKEY = $SERVICEHOME/gns/zonekey_priv.zkey + +# Where to store the key for the Shorten zone +SHORTEN_ZONEKEY = $SERVICEHOME/gns/zonekey_short.zkey + +# Should we hijack DNS queries using the Linux firewall? +# (this only works on GNU/Linux systems) HIJACK_DNS = NO + +# Automatically import PKEYs we learn into the shorten zone? AUTO_IMPORT_PKEY = YES + +# When we automatically import PKEYs into shorten zone, require confirmation +# before they become active? (Not useful right now as the GUI to confirm +# doesn't exist) AUTO_IMPORT_CONFIRMATION_REQ = NO + +# How many queries is GADS allowed to perform in the background at the same time? MAX_PARALLEL_BACKGROUND_QUERIES = 25 -DEFAULT_LOOKUP_TIMEOUT = 10 -RECORD_PUT_INTERVAL = 60 -ZONE_PUT_INTERVAL = 900 + +# When do queries fail with timeout? +DEFAULT_LOOKUP_TIMEOUT = 10 s + +# How frequently do we try to publish our full zone? +ZONE_PUBLISH_TIME_WINDOW = 4 h + +# PREFIX = valgrind --leak-check=full --track-origins=yes + +[gns-proxy] +BINARY = gnunet-gns-proxy +AUTOSTART = NO + +# Where is the certificate for the GNS proxy stored? +PROXY_CACERT = $SERVICEHOME/gns/gnsCAcert.pem +PROXY_UNIXPATH = /tmp/gnunet-gns-proxy.sock + [fcfsd] +# Name of the fcfs binary (for ARM) +BINARY = gnunet-gns-fcfsd +AUTOSTART = NO + +# On what port does the FCFS daemon listen for HTTP clients? HTTPPORT = 18080 + +# Where is the zone key for the FCFS zone stored? ZONEKEY = $SERVICEHOME/fcfsd/zonekey.zkey + +# For ARM, not very useful. FIXME: Dead option? HOSTNAME = localhost + +# FIXME: Dead option? HOME = $SERVICEHOME -CONFIG = $DEFAULTCONFIG -BINARY = gnunet-gns-fcfsd + +[dns2gns] +BINARY = gnunet-dns2gns +AUTOSTART = NO + +# -d: DNS resolver to use, -s: suffix to use, -f: fcfs suffix to use +OPTIONS = -d 8.8.8.8 diff --git a/src/gns/gns.h b/src/gns/gns.h index 408b686..e5d48fa 100644 --- a/src/gns/gns.h +++ b/src/gns/gns.h @@ -17,9 +17,6 @@ Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include "gnunet_gns_service.h" - /** * @file gns/gns.h * @brief IPC messages between GNS API and GNS service @@ -28,12 +25,23 @@ #ifndef GNS_H #define GNS_H -#define GNUNET_GNS_TLD "gnunet" +#include "gnunet_gns_service.h" + +/** + * Name of the GADS TLD. + */ +#define GNUNET_GNS_TLD "gads" + +/** + * Name of the zone key TLD. + */ #define GNUNET_GNS_TLD_ZKEY "zkey" -#define GNUNET_GNS_DHT_MAX_UPDATE_INTERVAL 3600 -#define MAX_DNS_LABEL_LENGTH 63 -#define MAX_DNS_NAME_LENGTH 253 +/** + * TLD name used to indicate relative names. + */ +#define GNUNET_GNS_TLD_PLUS "+" + GNUNET_NETWORK_STRUCT_BEGIN @@ -43,7 +51,7 @@ GNUNET_NETWORK_STRUCT_BEGIN struct GNUNET_GNS_ClientLookupMessage { /** - * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_LOOKUP + * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_LOOKUP */ struct GNUNET_MessageHeader header; @@ -53,19 +61,31 @@ struct GNUNET_GNS_ClientLookupMessage uint32_t id GNUNET_PACKED; /** + * If use_default_zone is empty this zone is used for lookup + */ + struct GNUNET_CRYPTO_ShortHashCode zone; + + /** + * Only check cached results + */ + uint32_t only_cached GNUNET_PACKED; + + /** * Should we look up in the default zone? */ uint32_t use_default_zone GNUNET_PACKED; /** - * If use_default_zone is empty this zone is used for lookup + * Is a shorten key attached? */ - struct GNUNET_CRYPTO_ShortHashCode zone; + uint32_t have_key GNUNET_PACKED; /** * the type of record to look up */ - enum GNUNET_GNS_RecordType type; + /* enum GNUNET_GNS_RecordType */ uint32_t type; + + /* Followed by the key for shorten (optional) see have_key */ /* Followed by the name to look up */ }; @@ -91,18 +111,18 @@ struct GNUNET_GNS_ClientLookupResultMessage */ uint32_t rd_count; - // FIXME: what format has a GNS_Record? /* followed by rd_count GNUNET_NAMESTORE_RecordData structs*/ }; + /** * Message from client to GNS service to shorten names. */ struct GNUNET_GNS_ClientShortenMessage { /** - * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_SHORTEN + * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_SHORTEN */ struct GNUNET_MessageHeader header; @@ -112,15 +132,25 @@ struct GNUNET_GNS_ClientShortenMessage uint32_t id GNUNET_PACKED; /** - * Should we look up in the default zone? + * If use_default_zone is empty this zone is used for lookup */ - uint32_t use_default_zone GNUNET_PACKED; + struct GNUNET_CRYPTO_ShortHashCode zone; /** - * If use_default_zone is empty this zone is used for lookup + * Shorten zone */ - struct GNUNET_CRYPTO_ShortHashCode zone; + struct GNUNET_CRYPTO_ShortHashCode shorten_zone; + /** + * Private zone + */ + struct GNUNET_CRYPTO_ShortHashCode private_zone; + + /** + * Should we look up in the default zone? + */ + uint32_t use_default_zone GNUNET_PACKED; + /* Followed by the name to shorten up */ }; @@ -131,7 +161,7 @@ struct GNUNET_GNS_ClientShortenMessage struct GNUNET_GNS_ClientShortenResultMessage { /** - * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_SHORTEN_RESULT + * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_SHORTEN_RESULT */ struct GNUNET_MessageHeader header; @@ -144,13 +174,14 @@ struct GNUNET_GNS_ClientShortenResultMessage }; + /** * Message from client to GNS service to lookup an authority of a name. */ struct GNUNET_GNS_ClientGetAuthMessage { /** - * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_GET_AUTH + * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_GET_AUTH */ struct GNUNET_MessageHeader header; @@ -169,7 +200,7 @@ struct GNUNET_GNS_ClientGetAuthMessage struct GNUNET_GNS_ClientGetAuthResultMessage { /** - * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_GET_AUTH_RESULT + * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_GET_AUTH_RESULT */ struct GNUNET_MessageHeader header; @@ -181,6 +212,7 @@ struct GNUNET_GNS_ClientGetAuthResultMessage /* followed by the authority part of the name or '\0' for no result*/ }; + GNUNET_NETWORK_STRUCT_END #endif diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c index a92280f..1e3cb01 100644 --- a/src/gns/gns_api.c +++ b/src/gns/gns_api.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 @@ -17,14 +17,12 @@ Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - /** - * * @file gns/gns_api.c * @brief library to access the GNS service * @author Martin Schanzenbach + * @author Christian Grothoff */ - #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" @@ -35,47 +33,119 @@ #include "gns.h" #include "gnunet_gns_service.h" -/* TODO into gnunet_protocols */ -#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP 23 -#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT 24 -#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN 25 -#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT 26 -#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH 27 -#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT 28 /** - * A QueueEntry. + * Handle to a lookup request */ -struct GNUNET_GNS_QueueEntry +struct GNUNET_GNS_LookupRequest { + /** * DLL */ - struct GNUNET_GNS_QueueEntry *next; + struct GNUNET_GNS_LookupRequest *next; /** * DLL */ - struct GNUNET_GNS_QueueEntry *prev; + struct GNUNET_GNS_LookupRequest *prev; + + /** + * handle to gns + */ + struct GNUNET_GNS_Handle *gns_handle; + + /** + * processor to call on lookup result + */ + GNUNET_GNS_LookupResultProcessor lookup_proc; - /* request id */ + /** + * processor closure + */ + void *proc_cls; + + /** + * request id + */ uint32_t r_id; + +}; + + +/** + * Handle to a shorten request + */ +struct GNUNET_GNS_ShortenRequest +{ + /** + * DLL + */ + struct GNUNET_GNS_ShortenRequest *next; - /* handle to gns */ + /** + * DLL + */ + struct GNUNET_GNS_ShortenRequest *prev; + + /** + * handle to gns + */ struct GNUNET_GNS_Handle *gns_handle; - /* processor to call on shorten result */ + /** + * processor to call on shorten result + */ GNUNET_GNS_ShortenResultProcessor shorten_proc; - /* processor to call on lookup result */ - GNUNET_GNS_LookupResultProcessor lookup_proc; + /** + * processor closure + */ + void *proc_cls; - /* processor to call on authority lookup result */ + /** + * request id + */ + uint32_t r_id; + +}; + + +/** + * Handle to GetAuthorityRequest + */ +struct GNUNET_GNS_GetAuthRequest +{ + /** + * DLL + */ + struct GNUNET_GNS_GetAuthRequest *next; + + /** + * DLL + */ + struct GNUNET_GNS_GetAuthRequest *prev; + + /** + * handle to gns + */ + struct GNUNET_GNS_Handle *gns_handle; + + /** + * processor to call on authority lookup result + */ GNUNET_GNS_GetAuthResultProcessor auth_proc; - /* processor closure */ + /** + * processor closure + */ void *proc_cls; + /** + * request id + */ + uint32_t r_id; + }; @@ -99,6 +169,18 @@ struct PendingMessage */ size_t size; + /** + * request id + */ + uint32_t r_id; + + /** + * This message has been transmitted. GNUNET_NO if the message is + * in the "pending" DLL, GNUNET_YES if it has been transmitted to + * the service via the current client connection. + */ + int transmitted; + }; @@ -123,8 +205,6 @@ struct GNUNET_GNS_Handle */ struct GNUNET_CLIENT_TransmitHandle *th; - uint32_t r_id; - /** * Head of linked list of shorten messages we would like to transmit. */ @@ -138,49 +218,56 @@ struct GNUNET_GNS_Handle /** * Head of linked list of shorten messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *shorten_head; + struct GNUNET_GNS_ShortenRequest *shorten_head; /** * Tail of linked list of shorten messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *shorten_tail; + struct GNUNET_GNS_ShortenRequest *shorten_tail; /** * Head of linked list of lookup messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *lookup_head; + struct GNUNET_GNS_LookupRequest *lookup_head; /** * Tail of linked list of lookup messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *lookup_tail; + struct GNUNET_GNS_LookupRequest *lookup_tail; /** * Head of linked list of authority lookup messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *get_auth_head; + struct GNUNET_GNS_GetAuthRequest *get_auth_head; /** * Tail of linked list of authority lookup messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *get_auth_tail; + struct GNUNET_GNS_GetAuthRequest *get_auth_tail; /** * Reconnect task */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; + + /** + * How long do we wait until we try to reconnect? + */ + struct GNUNET_TIME_Relative reconnect_backoff; /** + * Request Id generator. Incremented by one for each request. + */ + uint32_t r_id_gen; + + /** * Did we start our receive loop yet? */ int in_receive; - /** - * Reconnect necessary - */ - int reconnect; }; + /** * Try to send messages from list of messages to send * @param handle GNS_Handle @@ -192,18 +279,20 @@ process_pending_messages (struct GNUNET_GNS_Handle *handle); /** * Reconnect to GNS service. * - * @param h the handle to the namestore service + * @param handle the handle to the GNS service */ static void -reconnect (struct GNUNET_GNS_Handle *h) +reconnect (struct GNUNET_GNS_Handle *handle) { - GNUNET_assert (NULL == h->client); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Trying to connect to GNS...\n"); - h->client = GNUNET_CLIENT_connect ("gns", h->cfg); - GNUNET_assert (NULL != h->client); + GNUNET_assert (NULL == handle->client); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying to connect to GNS\n"); + handle->client = GNUNET_CLIENT_connect ("gns", handle->cfg); + GNUNET_assert (NULL != handle->client); + process_pending_messages (handle); } + /** * Reconnect to GNS * @@ -213,35 +302,78 @@ reconnect (struct GNUNET_GNS_Handle *h) static void reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct GNUNET_GNS_Handle *h = cls; + struct GNUNET_GNS_Handle *handle = cls; - h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; - reconnect (h); + handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + reconnect (handle); } /** * Disconnect from service and then reconnect. * - * @param h our handle + * @param handle our handle */ static void -force_reconnect (struct GNUNET_GNS_Handle *h) +force_reconnect (struct GNUNET_GNS_Handle *handle) { - h->reconnect = GNUNET_NO; - GNUNET_CLIENT_disconnect (h->client); - h->client = NULL; - h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, + struct GNUNET_GNS_ShortenRequest *st; + struct GNUNET_GNS_LookupRequest *lh; + struct GNUNET_GNS_GetAuthRequest *ga; + struct PendingMessage *p; + + GNUNET_CLIENT_disconnect (handle->client); + handle->client = NULL; + handle->in_receive = GNUNET_NO; + for (st = handle->shorten_head; NULL != st; st = st->next) + { + p = (struct PendingMessage *) &st[1]; + if (GNUNET_NO == p->transmitted) + continue; + p->transmitted = GNUNET_NO; + GNUNET_CONTAINER_DLL_insert (handle->pending_head, + handle->pending_tail, + p); + } + for (lh = handle->lookup_head; NULL != lh; lh = lh->next) + { + p = (struct PendingMessage *) &lh[1]; + if (GNUNET_NO == p->transmitted) + continue; + p->transmitted = GNUNET_NO; + GNUNET_CONTAINER_DLL_insert (handle->pending_head, + handle->pending_tail, + p); + } + for (ga = handle->get_auth_head; NULL != ga; ga = ga->next) + { + p = (struct PendingMessage *) &ga[1]; + if (GNUNET_NO == p->transmitted) + continue; + p->transmitted = GNUNET_NO; + GNUNET_CONTAINER_DLL_insert (handle->pending_head, + handle->pending_tail, + p); + } + handle->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff); + handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff, &reconnect_task, - h); + handle); } + /** * Transmit the next pending message, called by notify_transmit_ready + * + * @param cls the closure + * @param size size of pending data + * @param buf buffer with pending data + * @return size data transmitted */ static size_t transmit_pending (void *cls, size_t size, void *buf); + /** * Handler for messages received from the GNS service * @@ -251,93 +383,92 @@ transmit_pending (void *cls, size_t size, void *buf); static void process_message (void *cls, const struct GNUNET_MessageHeader *msg); + /** * Try to send messages from list of messages to send + * + * @param handle the GNS handle */ static void process_pending_messages (struct GNUNET_GNS_Handle *handle) { - struct PendingMessage *p; + struct PendingMessage *p = handle->pending_head; - if (handle->client == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "process_pending_messages called, but client is null\n"); - return; - } - - if (handle->th != NULL) - return; - - if (NULL == (p = handle->pending_head)) - return; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Trying to transmit %d bytes...\n", p->size); + if (NULL == handle->client) + return; /* wait for reconnect */ + if (NULL != handle->th) + return; /* transmission request already pending */ + while ((NULL != p) && (p->transmitted == GNUNET_YES)) + p = p->next; + if (NULL == p) + return; /* no messages pending */ + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying to transmit %u bytes\n", + (unsigned int) p->size); handle->th = GNUNET_CLIENT_notify_transmit_ready (handle->client, p->size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_pending, handle); - if (NULL != handle->th) - return; - - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "notify_transmit_ready returned NULL!\n"); + GNUNET_break (NULL != handle->th); } /** * Transmit the next pending message, called by notify_transmit_ready + * + * @param cls the closure + * @param size size of pending data + * @param buf buffer with pending data + * @return size data transmitted */ static size_t transmit_pending (void *cls, size_t size, void *buf) { struct GNUNET_GNS_Handle *handle = cls; + char *cbuf = buf; struct PendingMessage *p; size_t tsize; - char *cbuf; handle->th = NULL; - - if ((size == 0) || (buf == NULL)) + if ((0 == size) || (NULL == buf)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmission to GNS service failed!\n"); - force_reconnect(handle); + "Transmission to GNS service failed!\n"); + force_reconnect (handle); return 0; - } - - tsize = 0; - cbuf = buf; - + } if (NULL == (p = handle->pending_head)) return 0; + tsize = 0; while ((NULL != (p = handle->pending_head)) && (p->size <= size)) { memcpy (&cbuf[tsize], &p[1], p->size); tsize += p->size; size -= p->size; - GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, p); + p->transmitted = GNUNET_YES; + GNUNET_CONTAINER_DLL_remove (handle->pending_head, + handle->pending_tail, + p); if (GNUNET_YES != handle->in_receive) { GNUNET_CLIENT_receive (handle->client, &process_message, handle, GNUNET_TIME_UNIT_FOREVER_REL); handle->in_receive = GNUNET_YES; } - GNUNET_free(p); } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending %d bytes\n", tsize); - - process_pending_messages(handle); + "Sending %u bytes\n", + (unsigned int) tsize); + process_pending_messages (handle); return tsize; } + /** * Process a given reply that might match the given * request. @@ -346,34 +477,43 @@ transmit_pending (void *cls, size_t size, void *buf) * @param msg the shorten msg received */ static void -process_shorten_reply (struct GNUNET_GNS_QueueEntry *qe, +process_shorten_reply (struct GNUNET_GNS_ShortenRequest *qe, const struct GNUNET_GNS_ClientShortenResultMessage *msg) { - struct GNUNET_GNS_Handle *h = qe->gns_handle; + struct GNUNET_GNS_Handle *handle = qe->gns_handle; + struct PendingMessage *p = (struct PendingMessage *)&qe[1]; const char *short_name; - - GNUNET_CONTAINER_DLL_remove(h->shorten_head, h->shorten_tail, qe); - - short_name = (char*)(&msg[1]); - - if (ntohs (((struct GNUNET_MessageHeader*)msg)->size) < - sizeof (struct GNUNET_GNS_ClientShortenResultMessage)) + size_t mlen; + + if (GNUNET_YES != p->transmitted) { + /* service send reply to query we never managed to send!? */ GNUNET_break (0); - force_reconnect (h); - GNUNET_free(qe); + force_reconnect (handle); return; } - + mlen = ntohs (msg->header.size); + if (ntohs (msg->header.size) == sizeof (struct GNUNET_GNS_ClientShortenResultMessage)) + { + /* service reports resolution failed */ + short_name = NULL; + } + else + { + short_name = (const char *) &msg[1]; + if ('\0' != short_name[mlen - sizeof (struct GNUNET_GNS_ClientShortenResultMessage) - 1]) + { + GNUNET_break (0); + force_reconnect (handle); + return; + } + } + GNUNET_CONTAINER_DLL_remove (handle->shorten_head, handle->shorten_tail, qe); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received shortened reply `%s' from GNS service\n", short_name); - - GNUNET_CLIENT_receive (h->client, &process_message, h, - GNUNET_TIME_UNIT_FOREVER_REL); - qe->shorten_proc(qe->proc_cls, short_name); - GNUNET_free(qe); - + qe->shorten_proc (qe->proc_cls, short_name); + GNUNET_free (qe); } @@ -385,35 +525,45 @@ process_shorten_reply (struct GNUNET_GNS_QueueEntry *qe, * @param msg the message to process */ static void -process_get_auth_reply (struct GNUNET_GNS_QueueEntry *qe, +process_get_auth_reply (struct GNUNET_GNS_GetAuthRequest *qe, const struct GNUNET_GNS_ClientGetAuthResultMessage *msg) { - struct GNUNET_GNS_Handle *h = qe->gns_handle; + struct GNUNET_GNS_Handle *handle = qe->gns_handle; + struct PendingMessage *p = (struct PendingMessage *)&qe[1]; const char *auth_name; + size_t mlen; - GNUNET_CONTAINER_DLL_remove(h->get_auth_head, h->get_auth_tail, qe); - - auth_name = (char*)(&msg[1]); - - if (ntohs (((struct GNUNET_MessageHeader*)msg)->size) < - sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage)) + if (GNUNET_YES != p->transmitted) { - GNUNET_free(qe); + /* service send reply to query we never managed to send!? */ GNUNET_break (0); - force_reconnect (h); + force_reconnect (handle); return; } - + mlen = ntohs (msg->header.size); + if (mlen == sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage)) + { + auth_name = NULL; + } + else + { + auth_name = (const char*) &msg[1]; + if ('\0' != auth_name[mlen - sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage) - 1]) + { + GNUNET_break (0); + force_reconnect (handle); + return; + } + } + GNUNET_CONTAINER_DLL_remove (handle->get_auth_head, handle->get_auth_tail, qe); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received GET_AUTH reply `%s' from GNS service\n", auth_name); - - GNUNET_CLIENT_receive (h->client, &process_message, h, - GNUNET_TIME_UNIT_FOREVER_REL); - qe->auth_proc(qe->proc_cls, auth_name); - GNUNET_free(qe); - + qe->auth_proc (qe->proc_cls, auth_name); + GNUNET_free (qe); } + + /** * Process a given reply to the lookup request * @@ -421,48 +571,45 @@ process_get_auth_reply (struct GNUNET_GNS_QueueEntry *qe, * @param msg the lookup message received */ static void -process_lookup_reply (struct GNUNET_GNS_QueueEntry *qe, +process_lookup_reply (struct GNUNET_GNS_LookupRequest *qe, const struct GNUNET_GNS_ClientLookupResultMessage *msg) { - struct GNUNET_GNS_Handle *h = qe->gns_handle; - int rd_count = ntohl(msg->rd_count); - size_t len = ntohs (((struct GNUNET_MessageHeader*)msg)->size); + struct GNUNET_GNS_Handle *handle = qe->gns_handle; + struct PendingMessage *p = (struct PendingMessage *) &qe[1]; + uint32_t rd_count = ntohl (msg->rd_count); struct GNUNET_NAMESTORE_RecordData rd[rd_count]; + size_t mlen; - GNUNET_CONTAINER_DLL_remove(h->lookup_head, h->lookup_tail, qe); - - if (len < sizeof (struct GNUNET_GNS_ClientLookupResultMessage)) + if (GNUNET_YES != p->transmitted) { - GNUNET_free(qe); + /* service send reply to query we never managed to send!? */ GNUNET_break (0); - force_reconnect (h); + force_reconnect (handle); return; } - - len -= sizeof(struct GNUNET_GNS_ClientLookupResultMessage); - - GNUNET_CLIENT_receive (h->client, &process_message, h, - GNUNET_TIME_UNIT_FOREVER_REL); - if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (len, - (char*)&msg[1], + mlen = ntohs (msg->header.size); + mlen -= sizeof (struct GNUNET_GNS_ClientLookupResultMessage); + if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (mlen, + (const char*) &msg[1], rd_count, rd)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to serialize lookup reply from GNS service!\n"); - qe->lookup_proc(qe->proc_cls, 0, NULL); + _("Failed to serialize lookup reply from GNS service!\n")); + qe->lookup_proc (qe->proc_cls, 0, NULL); } else - { - + { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received lookup reply from GNS service (count=%d)\n", - ntohl(msg->rd_count)); - qe->lookup_proc(qe->proc_cls, rd_count, rd); + "Received lookup reply from GNS service (%u records)\n", + (unsigned int) rd_count); + qe->lookup_proc (qe->proc_cls, rd_count, rd); } - GNUNET_free(qe); + GNUNET_CONTAINER_DLL_remove (handle->lookup_head, handle->lookup_tail, qe); + GNUNET_free (qe); } + /** * Handler for messages received from the GNS service * @@ -473,109 +620,82 @@ static void process_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_GNS_Handle *handle = cls; - struct GNUNET_GNS_QueueEntry *qe; + struct GNUNET_GNS_LookupRequest *lr; + struct GNUNET_GNS_ShortenRequest *sr; + struct GNUNET_GNS_GetAuthRequest *gar; const struct GNUNET_GNS_ClientLookupResultMessage *lookup_msg; const struct GNUNET_GNS_ClientShortenResultMessage *shorten_msg; const struct GNUNET_GNS_ClientGetAuthResultMessage *get_auth_msg; - uint16_t type; uint32_t r_id; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got message\n"); - if (msg == NULL) + if (NULL == msg) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Error receiving data from GNS service, reconnecting\n"); force_reconnect (handle); return; } - - type = ntohs (msg->type); - - if (type == GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT) + switch (ntohs (msg->type)) { + case GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got lookup msg\n"); - lookup_msg = (const struct GNUNET_GNS_ClientLookupResultMessage *) msg; - r_id = ntohl (lookup_msg->id); - - if (r_id > handle->r_id) + "Got LOOKUP_RESULT msg\n"); + if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientLookupResultMessage)) { - /** no request found */ - GNUNET_break_op (0); - GNUNET_CLIENT_receive (handle->client, &process_message, handle, - GNUNET_TIME_UNIT_FOREVER_REL); + GNUNET_break (0); + force_reconnect (handle); return; } - - for (qe = handle->lookup_head; qe != NULL; qe = qe->next) - { - if (qe->r_id == r_id) - break; - } - if (qe) - process_lookup_reply(qe, lookup_msg); - - return; - - } - else if (type == GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT) - { + lookup_msg = (const struct GNUNET_GNS_ClientLookupResultMessage *) msg; + r_id = ntohl (lookup_msg->id); + for (lr = handle->lookup_head; NULL != lr; lr = lr->next) + if (lr->r_id == r_id) + { + process_lookup_reply(lr, lookup_msg); + break; + } + break; + case GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got SHORTEN_RESULT msg\n"); - shorten_msg = (struct GNUNET_GNS_ClientShortenResultMessage *) msg; - - r_id = ntohl (shorten_msg->id); - - if (r_id > handle->r_id) + if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientShortenResultMessage)) { - /** no request found */ - GNUNET_break_op (0); - GNUNET_CLIENT_receive (handle->client, &process_message, handle, - GNUNET_TIME_UNIT_FOREVER_REL); + GNUNET_break (0); + force_reconnect (handle); return; } - - for (qe = handle->shorten_head; qe != NULL; qe = qe->next) - { - if (qe->r_id == r_id) - break; - } - if (qe) - process_shorten_reply(qe, shorten_msg); - return; - } - else if (type == GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT) - { + shorten_msg = (const struct GNUNET_GNS_ClientShortenResultMessage *) msg; + r_id = ntohl (shorten_msg->id); + for (sr = handle->shorten_head; NULL != sr; sr = sr->next) + if (sr->r_id == r_id) + { + process_shorten_reply (sr, shorten_msg); + break; + } + break; + case GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got GET_AUTH_RESULT msg\n"); - get_auth_msg = (struct GNUNET_GNS_ClientGetAuthResultMessage *) msg; - - r_id = ntohl (get_auth_msg->id); - - if (r_id > handle->r_id) + if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage)) { - /** no request found */ - GNUNET_break_op (0); - GNUNET_CLIENT_receive (handle->client, &process_message, handle, - GNUNET_TIME_UNIT_FOREVER_REL); + GNUNET_break (0); + force_reconnect (handle); return; } - - for (qe = handle->get_auth_head; qe != NULL; qe = qe->next) - { - if (qe->r_id == r_id) - break; - } - if (qe) - process_get_auth_reply(qe, get_auth_msg); + get_auth_msg = (const struct GNUNET_GNS_ClientGetAuthResultMessage *) msg; + r_id = ntohl (get_auth_msg->id); + for (gar = handle->get_auth_head; NULL != gar; gar = gar->next) + if (gar->r_id == r_id) + { + process_get_auth_reply (gar, get_auth_msg); + break; + } + break; + default: + GNUNET_break (0); + force_reconnect (handle); return; } - - - if (GNUNET_YES == handle->reconnect) - force_reconnect (handle); - + GNUNET_CLIENT_receive (handle->client, &process_message, handle, + GNUNET_TIME_UNIT_FOREVER_REL); } @@ -591,13 +711,8 @@ GNUNET_GNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) struct GNUNET_GNS_Handle *handle; handle = GNUNET_malloc (sizeof (struct GNUNET_GNS_Handle)); - handle->reconnect = GNUNET_NO; handle->cfg = cfg; reconnect (handle); - //handle->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, handle); - handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; - handle->r_id = 0; - handle->in_receive = GNUNET_NO; return handle; } @@ -616,24 +731,79 @@ GNUNET_GNS_disconnect (struct GNUNET_GNS_Handle *handle) GNUNET_SCHEDULER_cancel (handle->reconnect_task); handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } - GNUNET_free(handle); - /* disco from GNS */ + GNUNET_assert (NULL == handle->lookup_head); + GNUNET_assert (NULL == handle->shorten_head); + GNUNET_assert (NULL == handle->get_auth_head); + GNUNET_free (handle); } -/* - * Helper function to generate request ids - * - * @param h handle - * @return a new id + +/** + * Cancel pending lookup request + * + * @param lr the lookup request to cancel */ -static uint32_t -get_request_id (struct GNUNET_GNS_Handle *h) +void +GNUNET_GNS_cancel_lookup_request (struct GNUNET_GNS_LookupRequest *lr) { - uint32_t r_id = h->r_id; - h->r_id++; - return r_id; + struct PendingMessage *p = (struct PendingMessage*) &lr[1]; + + GNUNET_assert (NULL != lr->gns_handle); + if (GNUNET_NO == p->transmitted) + GNUNET_CONTAINER_DLL_remove (lr->gns_handle->pending_head, + lr->gns_handle->pending_tail, + p); + GNUNET_CONTAINER_DLL_remove (lr->gns_handle->lookup_head, + lr->gns_handle->lookup_tail, + lr); + GNUNET_free (lr); } + +/** + * Cancel pending shorten request + * + * @param sr the lookup request to cancel + */ +void +GNUNET_GNS_cancel_shorten_request (struct GNUNET_GNS_ShortenRequest *sr) +{ + struct PendingMessage *p = (struct PendingMessage*) &sr[1]; + + GNUNET_assert (NULL != sr->gns_handle); + if (GNUNET_NO == p->transmitted) + GNUNET_CONTAINER_DLL_remove (sr->gns_handle->pending_head, + sr->gns_handle->pending_tail, + p); + GNUNET_CONTAINER_DLL_remove (sr->gns_handle->shorten_head, + sr->gns_handle->shorten_tail, + sr); + GNUNET_free (sr); +} + + +/** + * Cancel pending get auth request + * + * @param gar the lookup request to cancel + */ +void +GNUNET_GNS_cancel_get_auth_request (struct GNUNET_GNS_GetAuthRequest *gar) +{ + struct PendingMessage *p = (struct PendingMessage*) &gar[1]; + + GNUNET_assert (NULL != gar->gns_handle); + if (GNUNET_NO == p->transmitted) + GNUNET_CONTAINER_DLL_remove (gar->gns_handle->pending_head, + gar->gns_handle->pending_tail, + p); + GNUNET_CONTAINER_DLL_remove (gar->gns_handle->get_auth_head, + gar->gns_handle->get_auth_tail, + gar); + GNUNET_free (gar); +} + + /** * Perform an asynchronous Lookup operation on the GNS. * @@ -641,179 +811,235 @@ get_request_id (struct GNUNET_GNS_Handle *h) * @param name the name to look up * @param zone the zone to start the resolution in * @param type the record type to look up + * @param only_cached GNUNET_YES to only check locally not DHT for performance + * @param shorten_key the private key of the shorten zone (can be NULL) * @param proc processor to call on result * @param proc_cls closure for processor - * @return handle to the get + * @return handle to the get request */ -struct GNUNET_GNS_QueueEntry * +struct GNUNET_GNS_LookupRequest* GNUNET_GNS_lookup_zone (struct GNUNET_GNS_Handle *handle, - const char * name, - struct GNUNET_CRYPTO_ShortHashCode *zone, - enum GNUNET_GNS_RecordType type, - GNUNET_GNS_LookupResultProcessor proc, - void *proc_cls) + const char *name, + struct GNUNET_CRYPTO_ShortHashCode *zone, + enum GNUNET_GNS_RecordType type, + int only_cached, + struct GNUNET_CRYPTO_RsaPrivateKey *shorten_key, + GNUNET_GNS_LookupResultProcessor proc, + void *proc_cls) { /* IPC to shorten gns names, return shorten_handle */ struct GNUNET_GNS_ClientLookupMessage *lookup_msg; - struct GNUNET_GNS_QueueEntry *qe; + struct GNUNET_GNS_LookupRequest *lr; size_t msize; struct PendingMessage *pending; + struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *pkey_enc; + size_t key_len; + char* pkey_tmp; if (NULL == name) { + GNUNET_break (0); return NULL; + } + if (NULL != shorten_key) + { + pkey_enc = GNUNET_CRYPTO_rsa_encode_key (shorten_key); + GNUNET_assert (pkey_enc != NULL); + key_len = ntohs (pkey_enc->len); } - - msize = sizeof (struct GNUNET_GNS_ClientLookupMessage) + strlen(name) + 1; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to lookup %s in GNS\n", name); - - qe = GNUNET_malloc(sizeof (struct GNUNET_GNS_QueueEntry)); - qe->gns_handle = handle; - qe->lookup_proc = proc; - qe->proc_cls = proc_cls; - qe->r_id = get_request_id(handle); - GNUNET_CONTAINER_DLL_insert_tail(handle->lookup_head, - handle->lookup_tail, qe); - - pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); - memset(pending, 0, (sizeof (struct PendingMessage) + msize)); - + else + { + pkey_enc = NULL; + key_len = 0; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying to lookup `%s' in GNS\n", + name); + msize = sizeof (struct GNUNET_GNS_ClientLookupMessage) + + key_len + strlen (name) + 1; + if (msize > UINT16_MAX) + { + GNUNET_break (0); + GNUNET_free (pkey_enc); + return NULL; + } + lr = GNUNET_malloc (sizeof (struct GNUNET_GNS_LookupRequest) + + sizeof (struct PendingMessage) + msize); + lr->gns_handle = handle; + lr->lookup_proc = proc; + lr->proc_cls = proc_cls; + lr->r_id = handle->r_id_gen++; + pending = (struct PendingMessage *)&lr[1]; pending->size = msize; + pending->r_id = lr->r_id; + GNUNET_CONTAINER_DLL_insert_tail (handle->lookup_head, + handle->lookup_tail, lr); lookup_msg = (struct GNUNET_GNS_ClientLookupMessage *) &pending[1]; lookup_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_LOOKUP); lookup_msg->header.size = htons (msize); - lookup_msg->id = htonl(qe->r_id); - + lookup_msg->id = htonl (lr->r_id); + lookup_msg->only_cached = htonl (only_cached); if (NULL != zone) { - lookup_msg->use_default_zone = htonl(0); - memcpy(&lookup_msg->zone, zone, sizeof(struct GNUNET_CRYPTO_ShortHashCode)); + lookup_msg->use_default_zone = htonl (GNUNET_NO); + memcpy (&lookup_msg->zone, zone, sizeof (struct GNUNET_CRYPTO_ShortHashCode)); } else { - lookup_msg->use_default_zone = htonl(1); - memset(&lookup_msg->zone, 0, sizeof(struct GNUNET_CRYPTO_ShortHashCode)); + lookup_msg->use_default_zone = htonl (GNUNET_YES); + memset (&lookup_msg->zone, 0, sizeof(struct GNUNET_CRYPTO_ShortHashCode)); + } + lookup_msg->type = htonl (type); + pkey_tmp = (char *) &lookup_msg[1]; + if (pkey_enc != NULL) + { + lookup_msg->have_key = htonl (GNUNET_YES); + memcpy (pkey_tmp, pkey_enc, key_len); } + else + lookup_msg->have_key = htonl (GNUNET_NO); + GNUNET_free_non_null (pkey_enc); + memcpy (&pkey_tmp[key_len], name, strlen (name) + 1); - lookup_msg->type = htonl(type); - - memcpy(&lookup_msg[1], name, strlen(name)); - - GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail, - pending); - + GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, + handle->pending_tail, + pending); process_pending_messages (handle); - return qe; + return lr; } + /** * Perform an asynchronous Lookup operation on the GNS. * * @param handle handle to the GNS service * @param name the name to look up * @param type the record type to look up + * @param only_cached GNUNET_YES to only check locally not DHT for performance + * @param shorten_key the private key of the shorten zone (can be NULL) * @param proc processor to call on result * @param proc_cls closure for processor - * @return handle to the get + * @return handle to the lookup request */ -struct GNUNET_GNS_QueueEntry * +struct GNUNET_GNS_LookupRequest * GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle, - const char * name, + const char *name, enum GNUNET_GNS_RecordType type, + int only_cached, + struct GNUNET_CRYPTO_RsaPrivateKey *shorten_key, GNUNET_GNS_LookupResultProcessor proc, void *proc_cls) { - return GNUNET_GNS_lookup_zone (handle, name, NULL, type, proc, proc_cls); + return GNUNET_GNS_lookup_zone (handle, name, + NULL, + type, only_cached, + shorten_key, + proc, proc_cls); } + /** * Perform a name shortening operation on the GNS. * * @param handle handle to the GNS service * @param name the name to look up + * @param private_zone the public zone of the private zone + * @param shorten_zone the public zone of the shorten zone * @param zone the zone to start the resolution in * @param proc function to call on result * @param proc_cls closure for processor * @return handle to the operation */ -struct GNUNET_GNS_QueueEntry * +struct GNUNET_GNS_ShortenRequest* GNUNET_GNS_shorten_zone (struct GNUNET_GNS_Handle *handle, - const char * name, - struct GNUNET_CRYPTO_ShortHashCode *zone, - GNUNET_GNS_ShortenResultProcessor proc, - void *proc_cls) + const char *name, + struct GNUNET_CRYPTO_ShortHashCode *private_zone, + struct GNUNET_CRYPTO_ShortHashCode *shorten_zone, + struct GNUNET_CRYPTO_ShortHashCode *zone, + GNUNET_GNS_ShortenResultProcessor proc, + void *proc_cls) { /* IPC to shorten gns names, return shorten_handle */ struct GNUNET_GNS_ClientShortenMessage *shorten_msg; - struct GNUNET_GNS_QueueEntry *qe; + struct GNUNET_GNS_ShortenRequest *sr; size_t msize; struct PendingMessage *pending; if (NULL == name) { + GNUNET_break (0); return NULL; } - - msize = sizeof (struct GNUNET_GNS_ClientShortenMessage) + strlen(name) + 1; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to shorten %s in GNS\n", name); - - qe = GNUNET_malloc(sizeof (struct GNUNET_GNS_QueueEntry)); - qe->gns_handle = handle; - qe->shorten_proc = proc; - qe->proc_cls = proc_cls; - qe->r_id = get_request_id(handle); - GNUNET_CONTAINER_DLL_insert_tail(handle->shorten_head, - handle->shorten_tail, qe); - - pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); - memset(pending, 0, (sizeof (struct PendingMessage) + msize)); - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to shorten `%s' in GNS\n", name); + msize = sizeof (struct GNUNET_GNS_ClientShortenMessage) + strlen (name) + 1; + if (msize > UINT16_MAX) + { + GNUNET_break (0); + return NULL; + } + sr = GNUNET_malloc (sizeof (struct GNUNET_GNS_ShortenRequest) + + sizeof (struct PendingMessage) + msize); + sr->gns_handle = handle; + sr->shorten_proc = proc; + sr->proc_cls = proc_cls; + sr->r_id = handle->r_id_gen++; + GNUNET_CONTAINER_DLL_insert_tail (handle->shorten_head, + handle->shorten_tail, sr); + pending = (struct PendingMessage *)&sr[1]; pending->size = msize; + pending->r_id = sr->r_id; shorten_msg = (struct GNUNET_GNS_ClientShortenMessage *) &pending[1]; shorten_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_SHORTEN); - shorten_msg->header.size = htons (msize); - shorten_msg->id = htonl(qe->r_id); - + shorten_msg->header.size = htons ((uint16_t) msize); + shorten_msg->id = htonl (sr->r_id); + shorten_msg->private_zone = *private_zone; + shorten_msg->shorten_zone = *shorten_zone; if (NULL != zone) { - shorten_msg->use_default_zone = htonl(0); - memcpy(&shorten_msg->zone, zone, - sizeof(struct GNUNET_CRYPTO_ShortHashCode)); + shorten_msg->use_default_zone = htonl (GNUNET_NO); + memcpy (&shorten_msg->zone, zone, + sizeof (struct GNUNET_CRYPTO_ShortHashCode)); } else { - shorten_msg->use_default_zone = htonl(1); - memset(&shorten_msg->zone, 0, sizeof(struct GNUNET_CRYPTO_ShortHashCode)); - } - - memcpy(&shorten_msg[1], name, strlen(name)); - + shorten_msg->use_default_zone = htonl (GNUNET_YES); + memset (&shorten_msg->zone, 0, sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + } + memcpy (&shorten_msg[1], name, strlen (name) + 1); GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail, - pending); - + pending); process_pending_messages (handle); - return qe; + return sr; } + /** * Perform a name shortening operation on the GNS. * * @param handle handle to the GNS service * @param name the name to look up + * @param private_zone the public zone of the private zone + * @param shorten_zone the public zone of the shorten zone * @param proc function to call on result * @param proc_cls closure for processor * @return handle to the operation */ -struct GNUNET_GNS_QueueEntry * +struct GNUNET_GNS_ShortenRequest* GNUNET_GNS_shorten (struct GNUNET_GNS_Handle *handle, - const char * name, + const char *name, + struct GNUNET_CRYPTO_ShortHashCode *private_zone, + struct GNUNET_CRYPTO_ShortHashCode *shorten_zone, GNUNET_GNS_ShortenResultProcessor proc, void *proc_cls) { - return GNUNET_GNS_shorten_zone (handle, name, NULL, proc, proc_cls); + return GNUNET_GNS_shorten_zone (handle, name, + private_zone, shorten_zone, + NULL, proc, proc_cls); } + + /** * Perform an authority lookup for a given name. * @@ -823,51 +1049,52 @@ GNUNET_GNS_shorten (struct GNUNET_GNS_Handle *handle, * @param proc_cls closure for processor * @return handle to the operation */ -struct GNUNET_GNS_QueueEntry * +struct GNUNET_GNS_GetAuthRequest* GNUNET_GNS_get_authority (struct GNUNET_GNS_Handle *handle, - const char * name, - GNUNET_GNS_GetAuthResultProcessor proc, - void *proc_cls) + const char *name, + GNUNET_GNS_GetAuthResultProcessor proc, + void *proc_cls) { struct GNUNET_GNS_ClientGetAuthMessage *get_auth_msg; - struct GNUNET_GNS_QueueEntry *qe; + struct GNUNET_GNS_GetAuthRequest *gar; size_t msize; struct PendingMessage *pending; if (NULL == name) { + GNUNET_break (0); return NULL; } - - msize = sizeof (struct GNUNET_GNS_ClientGetAuthMessage) + strlen(name) + 1; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to look up authority for %s in GNS\n", name); - - qe = GNUNET_malloc(sizeof (struct GNUNET_GNS_QueueEntry)); - qe->gns_handle = handle; - qe->auth_proc = proc; - qe->proc_cls = proc_cls; - qe->r_id = get_request_id(handle); - GNUNET_CONTAINER_DLL_insert_tail(handle->get_auth_head, - handle->get_auth_tail, qe); - - pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); - memset(pending, 0, (sizeof (struct PendingMessage) + msize)); - + msize = sizeof (struct GNUNET_GNS_ClientGetAuthMessage) + strlen (name) + 1; + if (msize > UINT16_MAX) + { + GNUNET_break (0); + return NULL; + } + gar = GNUNET_malloc (sizeof (struct GNUNET_GNS_GetAuthRequest) + + sizeof (struct PendingMessage) + msize); + gar->gns_handle = handle; + gar->auth_proc = proc; + gar->proc_cls = proc_cls; + gar->r_id = handle->r_id_gen++; + GNUNET_CONTAINER_DLL_insert_tail (handle->get_auth_head, + handle->get_auth_tail, gar); + + pending = (struct PendingMessage *) &gar[1]; pending->size = msize; - + pending->r_id = gar->r_id; get_auth_msg = (struct GNUNET_GNS_ClientGetAuthMessage *) &pending[1]; get_auth_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_GET_AUTH); get_auth_msg->header.size = htons (msize); - get_auth_msg->id = htonl(qe->r_id); - - memcpy(&get_auth_msg[1], name, strlen(name)); - - GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail, - pending); - + get_auth_msg->id = htonl (gar->r_id); + memcpy (&get_auth_msg[1], name, strlen (name) + 1); + GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, + handle->pending_tail, + pending); process_pending_messages (handle); - return qe; + return gar; } diff --git a/src/gns/gns_common.c b/src/gns/gns_common.c new file mode 100644 index 0000000..88b365d --- /dev/null +++ b/src/gns/gns_common.c @@ -0,0 +1,79 @@ +/* + 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 gns/gns_common.c + * @brief helper functions shared between GNS service and block plugin + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gns_common.h" + + +/** + * Compute the DHT key for a name in a zone. + * DHT key is H(name) xor H(pubkey). + * + * @param name name of the record + * @param zone GADS zone + * @param key where to store the DHT key for records under this name in the given zone + */ +void +GNUNET_GNS_get_key_for_record (const char *name, + const struct GNUNET_CRYPTO_ShortHashCode *zone, + struct GNUNET_HashCode *key) +{ + struct GNUNET_CRYPTO_ShortHashCode name_hash; + struct GNUNET_HashCode name_hash_double; + struct GNUNET_HashCode zone_hash_double; + + GNUNET_CRYPTO_short_hash (name, + strlen (name), + &name_hash); + GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double); + GNUNET_CRYPTO_short_hash_double (zone, &zone_hash_double); + GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, key); +} + + +/** + * Compute the zone identifier from a given DHT key and record name. + * + * @param name name of the record + * @param key DHT key of the record + * @param zone set to the corresponding zone hash + */ +void +GNUNET_GNS_get_zone_from_key (const char *name, + const struct GNUNET_HashCode *key, + struct GNUNET_CRYPTO_ShortHashCode *zone) +{ + struct GNUNET_CRYPTO_ShortHashCode name_hash; + struct GNUNET_HashCode name_hash_double; + struct GNUNET_HashCode zone_hash_double; + + GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash); + GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double); + GNUNET_CRYPTO_hash_xor(key, &name_hash_double, &zone_hash_double); + GNUNET_CRYPTO_short_hash_from_truncation (&zone_hash_double, zone); +} + + +/* end of gns_common.c */ diff --git a/src/gns/gns_common.h b/src/gns/gns_common.h new file mode 100644 index 0000000..5b4a116 --- /dev/null +++ b/src/gns/gns_common.h @@ -0,0 +1,58 @@ +/* + 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 gns/gns_common.h + * @brief helper functions shared between GNS service and block plugin + * @author Martin Schanzenbach + */ +#ifndef GNS_COMMON_H +#define GNS_COMMON_H + +#include "gnunet_util_lib.h" + +/** + * Compute the DHT key for a name in a zone. + * + * @param name name of the record + * @param zone GADS zone + * @param key where to store the DHT key for records under this name in the given zone + */ +void +GNUNET_GNS_get_key_for_record (const char *name, + const struct GNUNET_CRYPTO_ShortHashCode *zone, + struct GNUNET_HashCode *key); + + +/** + * Compute the zone identifier from a given DHT key and record name. + * + * @param name name of the record + * @param key DHT key of the record + * @param zone set to the corresponding zone hash + */ +void +GNUNET_GNS_get_zone_from_key (const char *name, + const struct GNUNET_HashCode *key, + struct GNUNET_CRYPTO_ShortHashCode *zone); + + + +#endif diff --git a/src/gns/gnunet-dns2gns.c b/src/gns/gnunet-dns2gns.c new file mode 100644 index 0000000..8350103 --- /dev/null +++ b/src/gns/gnunet-dns2gns.c @@ -0,0 +1,708 @@ +/* + 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-dns2gns.c + * @brief DNS server that translates DNS requests to GNS + * @author Christian Grothoff + */ +#include "platform.h" +#include <gnunet_util_lib.h> +#include <gnunet_dnsparser_lib.h> +#include <gnunet_gns_service.h> +#include <gnunet_dnsstub_lib.h> +#include "gns.h" + +/** + * Timeout for DNS requests. + */ +#define TIMEOUT GNUNET_TIME_UNIT_MINUTES + +/** + * Default suffix + */ +#define DNS_SUFFIX ".zkey.eu" + +/** + * FCFS suffix + */ +#define FCFS_SUFFIX "fcfs.zkey.eu" + +/** + * Data kept per request. + */ +struct Request +{ + /** + * Socket to use for sending the reply. + */ + struct GNUNET_NETWORK_Handle *lsock; + + /** + * Destination address to use. + */ + const void *addr; + + /** + * Initially, this is the DNS request, it will then be + * converted to the DNS response. + */ + struct GNUNET_DNSPARSER_Packet *packet; + + /** + * Our GNS request handle. + */ + struct GNUNET_GNS_LookupRequest *lookup; + + /** + * Our DNS request handle + */ + struct GNUNET_DNSSTUB_RequestSocket *dns_lookup; + + /** + * Task run on timeout or shutdown to clean up without + * response. + */ + GNUNET_SCHEDULER_TaskIdentifier timeout_task; + + /** + * Number of bytes in 'addr'. + */ + size_t addr_len; + +}; + + +/** + * Handle to GNS resolver. + */ +struct GNUNET_GNS_Handle *gns; + +/** + * Stub resolver + */ +struct GNUNET_DNSSTUB_Context *dns_stub; + +/** + * Listen socket for IPv4. + */ +static struct GNUNET_NETWORK_Handle *listen_socket4; + +/** + * Listen socket for IPv6. + */ +static struct GNUNET_NETWORK_Handle *listen_socket6; + +/** + * Task for IPv4 socket. + */ +static GNUNET_SCHEDULER_TaskIdentifier t4; + +/** + * Task for IPv6 socket. + */ +static GNUNET_SCHEDULER_TaskIdentifier t6; + +/** + * DNS suffix, suffix of this gateway in DNS; defaults to '.zkey.eu' + */ +static char *dns_suffix; + +/** + * FCFS suffix, suffix of FCFS-authority in DNS; defaults to 'fcfs.zkey.eu'. + */ +static char *fcfs_suffix; + +/** + * IP of DNS server + */ +static char *dns_ip; + +/** + * UDP Port we listen on for inbound DNS requests. + */ +static unsigned int listen_port = 53; + + +/** + * 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 (GNUNET_SCHEDULER_NO_TASK != t4) + GNUNET_SCHEDULER_cancel (t4); + if (GNUNET_SCHEDULER_NO_TASK != t6) + GNUNET_SCHEDULER_cancel (t6); + if (NULL != listen_socket4) + { + GNUNET_NETWORK_socket_close (listen_socket4); + listen_socket4 = NULL; + } + if (NULL != listen_socket6) + { + GNUNET_NETWORK_socket_close (listen_socket6); + listen_socket6 = NULL; + } + GNUNET_GNS_disconnect (gns); + gns = NULL; + GNUNET_DNSSTUB_stop (dns_stub); + dns_stub = NULL; +} + + +/** + * Send the response for the given request and clean up. + * + * @param request context for the request. + */ +static void +send_response (struct Request *request) +{ + char *buf; + size_t size; + + if (GNUNET_SYSERR == + GNUNET_DNSPARSER_pack (request->packet, + UINT16_MAX /* is this not too much? */, + &buf, + &size)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Failed to pack DNS response into UDP packet!\n")); + } + else + { + if (size != + GNUNET_NETWORK_socket_sendto (request->lsock, + buf, size, + request->addr, + request->addr_len)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto"); + GNUNET_free (buf); + } + GNUNET_SCHEDULER_cancel (request->timeout_task); + GNUNET_DNSPARSER_free_packet (request->packet); + GNUNET_free (request); +} + + +/** + * Task run on timeout. Cleans up request. + * + * @param cls 'struct Request' of the request to clean up + * @param tc scheduler context + */ +static void +do_timeout (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct Request *request = cls; + + if (NULL != request->packet) + GNUNET_DNSPARSER_free_packet (request->packet); + if (NULL != request->lookup) + GNUNET_GNS_cancel_lookup_request (request->lookup); + if (NULL != request->dns_lookup) + GNUNET_DNSSTUB_resolve_cancel (request->dns_lookup); + GNUNET_free (request); +} + + +/** + * Iterator called on obtained result for a DNS + * lookup + * + * @param cls closure + * @param rs the request socket + * @param dns the DNS udp payload + * @param r size of the DNS payload + */ +static void +dns_result_processor (void *cls, + struct GNUNET_DNSSTUB_RequestSocket *rs, + const struct GNUNET_TUN_DnsHeader *dns, + size_t r) +{ + struct Request *request = cls; + + request->packet = GNUNET_DNSPARSER_parse ((char*)dns, r); + send_response (request); +} + + +/** + * Iterator called on obtained result for a GNS + * lookup + * + * @param cls closure + * @param rd_count number of records + * @param rd the records in reply + */ +static void +result_processor (void *cls, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct Request *request = cls; + struct GNUNET_DNSPARSER_Packet *packet; + uint32_t i; + struct GNUNET_DNSPARSER_Record rec; + + request->lookup = NULL; + packet = request->packet; + packet->flags.query_or_response = 1; + packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR; + packet->flags.checking_disabled = 0; + packet->flags.authenticated_data = 1; + packet->flags.zero = 0; + packet->flags.recursion_available = 1; + packet->flags.message_truncated = 0; + packet->flags.authoritative_answer = 0; + //packet->flags.opcode = GNUNET_DNSPARSER_OPCODE_STATUS; // ??? + for (i=0;i<rd_count;i++) + { + rec.expiration_time.abs_value = rd[i].expiration_time; + switch (rd[i].record_type) + { + case GNUNET_DNSPARSER_TYPE_A: + GNUNET_assert (sizeof (struct in_addr) == rd[i].data_size); + rec.name = GNUNET_strdup (packet->queries[0].name); + rec.class = GNUNET_DNSPARSER_CLASS_INTERNET; + rec.type = GNUNET_DNSPARSER_TYPE_A; + rec.data.raw.data = GNUNET_malloc (sizeof (struct in_addr)); + memcpy (rec.data.raw.data, + rd[i].data, + rd[i].data_size); + rec.data.raw.data_len = sizeof (struct in_addr); + GNUNET_array_append (packet->answers, + packet->num_answers, + rec); + break; + case GNUNET_DNSPARSER_TYPE_AAAA: + GNUNET_assert (sizeof (struct in6_addr) == rd[i].data_size); + rec.name = GNUNET_strdup (packet->queries[0].name); + rec.data.raw.data = GNUNET_malloc (sizeof (struct in6_addr)); + rec.class = GNUNET_DNSPARSER_CLASS_INTERNET; + rec.type = GNUNET_DNSPARSER_TYPE_AAAA; + memcpy (rec.data.raw.data, + rd[i].data, + rd[i].data_size); + rec.data.raw.data_len = sizeof (struct in6_addr); + GNUNET_array_append (packet->answers, + packet->num_answers, + rec); + break; + case GNUNET_DNSPARSER_TYPE_CNAME: + rec.name = GNUNET_strdup (packet->queries[0].name); + rec.data.hostname = strdup (rd[i].data); + rec.class = GNUNET_DNSPARSER_CLASS_INTERNET; + rec.type = GNUNET_DNSPARSER_TYPE_CNAME; + memcpy (rec.data.hostname, + rd[i].data, + rd[i].data_size); + GNUNET_array_append (packet->answers, + packet->num_answers, + rec); + break; + default: + /* skip */ + break; + } + } + send_response (request); +} + + +/** + * Handle DNS request. + * + * @param lsock socket to use for sending the reply + * @param addr address to use for sending the reply + * @param addr_len number of bytes in addr + * @param udp_msg DNS request payload + * @param udp_msg_size number of bytes in udp_msg + */ +static void +handle_request (struct GNUNET_NETWORK_Handle *lsock, + const void *addr, + size_t addr_len, + const char *udp_msg, + size_t udp_msg_size) +{ + struct Request *request; + struct GNUNET_DNSPARSER_Packet *packet; + char *name; + char *dot; + char *nname; + size_t name_len; + enum GNUNET_GNS_RecordType type; + int use_gns; + struct GNUNET_CRYPTO_ShortHashCode zone; + + packet = GNUNET_DNSPARSER_parse (udp_msg, udp_msg_size); + if (NULL == packet) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Cannot parse DNS request from %s\n"), + GNUNET_a2s (addr, addr_len)); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received request for `%s' with flags %u, #answers %d, #auth %d, #additional %d\n", + packet->queries[0].name, + (unsigned int) packet->flags.query_or_response, + (int) packet->num_answers, + (int) packet->num_authority_records, + (int) packet->num_additional_records); + if ( (0 != packet->flags.query_or_response) || + (0 != packet->num_answers) || + (0 != packet->num_authority_records)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Received malformed DNS request from %s\n"), + GNUNET_a2s (addr, addr_len)); + GNUNET_DNSPARSER_free_packet (packet); + return; + } + if ( (1 != packet->num_queries) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Received unsupported DNS request from %s\n"), + GNUNET_a2s (addr, addr_len)); + GNUNET_DNSPARSER_free_packet (packet); + return; + } + request = GNUNET_malloc (sizeof (struct Request) + addr_len); + request->lsock = lsock; + request->packet = packet; + request->addr = &request[1]; + request->addr_len = addr_len; + memcpy (&request[1], addr, addr_len); + request->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, + &do_timeout, + request); + name = GNUNET_strdup (packet->queries[0].name); + name_len = strlen (name); + use_gns = GNUNET_NO; + if ( (name_len > strlen (dns_suffix)) && + (0 == strcasecmp (dns_suffix, + &name[name_len - strlen (dns_suffix)])) ) + { + /* Test if '.zkey' was requested */ + name[name_len - strlen (dns_suffix)] = '\0'; + dot = strrchr (name, (int) '.'); + if ( (NULL != dot) && + (GNUNET_OK == + GNUNET_CRYPTO_short_hash_from_string (dot + 1, &zone)) ) + { + /* valid '.zkey' name */ + GNUNET_asprintf (&nname, + "%s.%s", + name, + GNUNET_GNS_TLD_ZKEY); + GNUNET_free (name); + name = nname; + } + else + { + /* try '.gads' name */ + GNUNET_asprintf (&nname, + "%s.%s", + name, + GNUNET_GNS_TLD); + GNUNET_free (name); + name = nname; + } + name_len = strlen (name); + } + if ( (name_len >= strlen ((GNUNET_GNS_TLD))) && + (0 == strcasecmp (GNUNET_GNS_TLD, + &name[name_len - strlen (GNUNET_GNS_TLD)])) ) + use_gns = GNUNET_YES; + + if ( (name_len > strlen (GNUNET_GNS_TLD_ZKEY)) && + (0 == strcasecmp (GNUNET_GNS_TLD_ZKEY, + &name[name_len - strlen (GNUNET_GNS_TLD_ZKEY)])) ) + use_gns = GNUNET_YES; + + if (GNUNET_YES == use_gns) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Calling GNS\n"); + type = packet->queries[0].type; + request->lookup = GNUNET_GNS_lookup (gns, + name, + type, + GNUNET_NO, + NULL, + &result_processor, + request); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Calling DNS at %s\n", dns_ip); + GNUNET_DNSPARSER_free_packet (request->packet); + request->packet = NULL; + request->dns_lookup = GNUNET_DNSSTUB_resolve2 (dns_stub, + udp_msg, + udp_msg_size, + &dns_result_processor, + request); + } + GNUNET_free (name); +} + + +/** + * Task to read IPv4 DNS packets. + * + * @param cls the 'listen_socket4' + * @param tc scheduler context + */ +static void +read_dns4 (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct sockaddr_in v4; + socklen_t addrlen; + ssize_t size; + + GNUNET_assert (listen_socket4 == cls); + t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + listen_socket4, + &read_dns4, + listen_socket4); + if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason)) + return; /* shutdown? */ + size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket4); + if (0 > size) + { + GNUNET_break (0); + return; /* read error!? */ + } + { + char buf[size]; + + addrlen = sizeof (v4); + GNUNET_break (size == + GNUNET_NETWORK_socket_recvfrom (listen_socket4, + buf, + size, + (struct sockaddr *) &v4, + &addrlen)); + handle_request (listen_socket4, &v4, addrlen, + buf, size); + } +} + + +/** + * Task to read IPv6 DNS packets. + * + * @param cls the 'listen_socket6' + * @param tc scheduler context + */ +static void +read_dns6 (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct sockaddr_in6 v6; + socklen_t addrlen; + ssize_t size; + + GNUNET_assert (listen_socket6 == cls); + t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + listen_socket6, + &read_dns6, + listen_socket6); + if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason)) + return; /* shutdown? */ + size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket6); + if (0 > size) + { + GNUNET_break (0); + return; /* read error!? */ + } + { + char buf[size]; + + addrlen = sizeof (v6); + GNUNET_break (size == + GNUNET_NETWORK_socket_recvfrom (listen_socket6, + buf, + size, + (struct sockaddr *) &v6, + &addrlen)); + handle_request (listen_socket6, &v6, addrlen, + buf, size); + } +} + + +/** + * 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) +{ + if (NULL == dns_ip) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No DNS server specified!\n"); + return; + } + + if (NULL == dns_suffix) + dns_suffix = DNS_SUFFIX; + if (NULL == fcfs_suffix) + fcfs_suffix = FCFS_SUFFIX; + if (NULL == (gns = GNUNET_GNS_connect (cfg))) + return; + if (NULL == (dns_stub = GNUNET_DNSSTUB_start (dns_ip))) + { + GNUNET_GNS_disconnect (gns); + gns = NULL; + return; + } + listen_socket4 = GNUNET_NETWORK_socket_create (PF_INET, + SOCK_DGRAM, + IPPROTO_UDP); + if (NULL != listen_socket4) + { + struct sockaddr_in v4; + + memset (&v4, 0, sizeof (v4)); + v4.sin_family = AF_INET; +#if HAVE_SOCKADDR_IN_SIN_LEN + v4.sin_len = sizeof (v4); +#endif + v4.sin_port = htons (listen_port); + if (GNUNET_OK != + GNUNET_NETWORK_socket_bind (listen_socket4, + (struct sockaddr *) &v4, + sizeof (v4))) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); + GNUNET_NETWORK_socket_close (listen_socket4); + listen_socket4 = NULL; + } + } + listen_socket6 = GNUNET_NETWORK_socket_create (PF_INET6, + SOCK_DGRAM, + IPPROTO_UDP); + if (NULL != listen_socket6) + { + struct sockaddr_in6 v6; + + memset (&v6, 0, sizeof (v6)); + v6.sin6_family = AF_INET6; +#if HAVE_SOCKADDR_IN_SIN_LEN + v6.sin6_len = sizeof (v6); +#endif + v6.sin6_port = htons (listen_port); + if (GNUNET_OK != + GNUNET_NETWORK_socket_bind (listen_socket6, + (struct sockaddr *) &v6, + sizeof (v6))) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); + GNUNET_NETWORK_socket_close (listen_socket6); + listen_socket6 = NULL; + } + } + if ( (NULL == listen_socket4) && + (NULL == listen_socket6) ) + { + GNUNET_GNS_disconnect (gns); + gns = NULL; + GNUNET_DNSSTUB_stop (dns_stub); + dns_stub = NULL; + return; + } + if (NULL != listen_socket4) + t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + listen_socket4, + &read_dns4, + listen_socket4); + if (NULL != listen_socket6) + t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + listen_socket6, + &read_dns6, + listen_socket6); + + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, + &do_shutdown, NULL); +} + + +/** + * The main function for the fcfs daemon. + * + * @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) +{ + static const struct GNUNET_GETOPT_CommandLineOption options[] = { + {'d', "dns", "IP", + gettext_noop ("IP of recursive DNS resolver to use (required)"), 1, + &GNUNET_GETOPT_set_string, &dns_ip}, + {'s', "suffix", "SUFFIX", + gettext_noop ("Authoritative DNS suffix to use (optional); default: zkey.eu"), 1, + &GNUNET_GETOPT_set_string, &dns_suffix}, + {'f', "fcfs", "NAME", + gettext_noop ("Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu"), 1, + &GNUNET_GETOPT_set_string, &fcfs_suffix}, + {'p', "port", "UDPPORT", + gettext_noop ("UDP port to listen on for inbound DNS requests; default: 53"), 1, + &GNUNET_GETOPT_set_uint, &listen_port}, + GNUNET_GETOPT_OPTION_END + }; + int ret; + + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, + &argc, &argv)) + return 2; + GNUNET_log_setup ("gnunet-dns2gns", "WARNING", NULL); + ret = + (GNUNET_OK == + GNUNET_PROGRAM_run (argc, argv, "gnunet-dns2gns", + _("GNUnet DNS-to-GNS proxy (a DNS server)"), + options, + &run, NULL)) ? 0 : 1; + GNUNET_free ((void*) argv); + return ret; +} + +/* end of gnunet-dns2gns.c */ diff --git a/src/gns/gnunet-gns-fcfsd.c b/src/gns/gnunet-gns-fcfsd.c index cd4e8e7..d553964 100644 --- a/src/gns/gnunet-gns-fcfsd.c +++ b/src/gns/gnunet-gns-fcfsd.c @@ -42,7 +42,7 @@ /** * Front page. (/) */ -#define MAIN_PAGE "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><html><head><title>GNUnet FCFS Authority Name Registration Service</title></head><body><form action=\"S\" method=\"post\">What is your desired domain name? <input type=\"text\" name=\"domain\" /> <p> What is your public key? <input type=\"text\" name=\"pkey\" /> <input type=\"submit\" value=\"Next\" /></body></html>" +#define MAIN_PAGE "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><html><head><title>GNUnet FCFS Authority Name Registration Service</title></head><body><form action=\"S\" method=\"post\">What is your desired domain name? (at most 63 lowercase characters, no dots allowed.) <input type=\"text\" name=\"domain\" /> <p> What is your public key? (Copy from gnunet-setup.) <input type=\"text\" name=\"pkey\" /> <input type=\"submit\" value=\"Next\" /><br/><a href=./Zoneinfo> List of all registered names </a></body></html>" /** * Second page (/S) @@ -50,6 +50,13 @@ #define SUBMIT_PAGE "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><html><head><title>%s</title></head><body>%s</body></html>" /** + * Fcfs zoneinfo page (/Zoneinfo) + */ +#define ZONEINFO_PAGE "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><html><head><title>FCFS Zoneinfo</title></head><body><h1> FCFS Zoneinfo </h1><table border=\"1\"><th>name</th><th>PKEY</th>%s</table></body></html>" + +#define FCFS_ZONEINFO_URL "/Zoneinfo" + +/** * Mime type for HTML pages. */ #define MIME_HTML "text/html" @@ -59,6 +66,7 @@ */ #define COOKIE_NAME "gns-fcfs" +#define DEFAULT_ZONEINFO_BUFSIZE 2048 /** * Phases a request goes through. @@ -137,6 +145,36 @@ struct Request }; +/** + * Zoneinfo request + */ +struct ZoneinfoRequest +{ + /** + * Connection + */ + struct MHD_Connection *connection; + + /** + * List iterator + */ + struct GNUNET_NAMESTORE_ZoneIterator *list_it; + + /** + * Buffer + */ + char* zoneinfo; + + /** + * Buffer length + */ + size_t buf_len; + + /** + * Buffer write offset + */ + size_t write_offset; +}; /** * MHD deamon reference. @@ -165,6 +203,139 @@ static struct GNUNET_CRYPTO_RsaPrivateKey *fcfs_zone_pkey; /** + * Task run whenever HTTP server operations are pending. + * + * @param cls unused + * @param tc scheduler context + */ +static void +do_httpd (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + + +/** + * Schedule task to run MHD server now. + */ +static void +run_httpd_now () +{ + if (GNUNET_SCHEDULER_NO_TASK != httpd_task) + { + GNUNET_SCHEDULER_cancel (httpd_task); + httpd_task = GNUNET_SCHEDULER_NO_TASK; + } + httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL); +} + +static void +iterate_cb (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 ZoneinfoRequest *zr = cls; + struct MHD_Response *response; + char* full_page; + size_t bytes_free; + char* pkey; + char* new_buf; + + + if (NULL == name) + { + zr->list_it = NULL; + + /* return static form */ + GNUNET_asprintf (&full_page, + ZONEINFO_PAGE, + zr->zoneinfo, + zr->zoneinfo); + response = MHD_create_response_from_buffer (strlen (full_page), + (void *) full_page, + MHD_RESPMEM_MUST_FREE); + MHD_add_response_header (response, + MHD_HTTP_HEADER_CONTENT_TYPE, + MIME_HTML); + MHD_queue_response (zr->connection, + MHD_HTTP_OK, + response); + MHD_destroy_response (response); + GNUNET_free (zr->zoneinfo); + GNUNET_free (zr); + run_httpd_now (); + return; + } + + if (1 != rd_len) + { + GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); + return; + } + + if (GNUNET_NAMESTORE_TYPE_PKEY != rd->record_type) + { + GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); + return; + } + + bytes_free = zr->buf_len - zr->write_offset; + pkey = GNUNET_NAMESTORE_value_to_string (rd->record_type, + rd->data, + rd->data_size); + + if (bytes_free < (strlen (name) + strlen (pkey) + 40)) + { + new_buf = GNUNET_malloc (zr->buf_len * 2); + memcpy (new_buf, zr->zoneinfo, zr->write_offset); + GNUNET_free (zr->zoneinfo); + zr->zoneinfo = new_buf; + zr->buf_len *= 2; + } + sprintf (zr->zoneinfo + zr->write_offset, + "<tr><td>%s</td><td>%s</td></tr>", + name, + pkey); + zr->write_offset = strlen (zr->zoneinfo); + GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); + GNUNET_free (pkey); +} + + + +/** + * Handler that returns FCFS zoneinfo page. + * + * @param connection connection to use + * @return MHD_YES on success + */ +static int +serve_zoneinfo_page (struct MHD_Connection *connection) +{ + struct ZoneinfoRequest *zr; + + zr = GNUNET_malloc (sizeof (struct ZoneinfoRequest)); + + zr->zoneinfo = GNUNET_malloc (DEFAULT_ZONEINFO_BUFSIZE); + zr->buf_len = DEFAULT_ZONEINFO_BUFSIZE; + zr->connection = connection; + zr->write_offset = 0; + + printf ("adsadad1!\n"); + zr->list_it = GNUNET_NAMESTORE_zone_iteration_start (ns, + &fcfsd_zone, + GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION, + GNUNET_NAMESTORE_RF_PRIVATE, + &iterate_cb, + zr); + + return MHD_YES; +} + + +/** * Handler that returns a simple static HTTP page. * * @param connection connection to use @@ -283,30 +454,6 @@ post_iterator (void *cls, } -/** - * Task run whenever HTTP server operations are pending. - * - * @param cls unused - * @param tc scheduler context - */ -static void -do_httpd (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc); - - -/** - * Schedule task to run MHD server now. - */ -static void -run_httpd_now () -{ - if (GNUNET_SCHEDULER_NO_TASK != httpd_task) - { - GNUNET_SCHEDULER_cancel (httpd_task); - httpd_task = GNUNET_SCHEDULER_NO_TASK; - } - httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL); -} /** @@ -386,7 +533,7 @@ zone_to_name_cb (void *cls, &pub)); r.data = &pub; r.data_size = sizeof (pub); - r.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + r.expiration_time = UINT64_MAX; r.record_type = GNUNET_NAMESTORE_TYPE_PKEY; r.flags = GNUNET_NAMESTORE_RF_AUTHORITY; request->qe = GNUNET_NAMESTORE_record_create (ns, @@ -492,7 +639,10 @@ create_response (void *cls, if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) || (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) ) { - ret = serve_main_page (connection); + if (0 == strcmp (url, FCFS_ZONEINFO_URL)) + ret = serve_zoneinfo_page (connection); + else + ret = serve_main_page (connection); if (ret != MHD_YES) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to create page for `%s'\n"), @@ -544,6 +694,22 @@ create_response (void *cls, switch (request->phase) { case RP_START: + if (NULL != strchr (request->domain_name, (int) '.')) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Domain name must not contain `.'\n")); + request->phase = RP_FAIL; + return fill_s_reply ("Domain name must not contain `.', sorry.", + request, connection); + } + if (NULL != strchr (request->domain_name, (int) '+')) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Domain name must not contain `+'\n")); + request->phase = RP_FAIL; + return fill_s_reply ("Domain name must not contain `+', sorry.", + request, connection); + } request->phase = RP_LOOKUP; request->qe = GNUNET_NAMESTORE_lookup_record (ns, &fcfsd_zone, @@ -607,6 +773,9 @@ request_completed_callback (void *cls, } +#define UNSIGNED_MHD_LONG_LONG unsigned MHD_LONG_LONG + + /** * Schedule tasks to run MHD server. */ @@ -621,7 +790,7 @@ run_httpd () struct GNUNET_NETWORK_FDSet *wes; int max; int haveto; - unsigned MHD_LONG_LONG timeout; + UNSIGNED_MHD_LONG_LONG timeout; struct GNUNET_TIME_Relative tv; FD_ZERO (&rs); @@ -683,7 +852,7 @@ do_shutdown (void *cls, } if (NULL != ns) { - GNUNET_NAMESTORE_disconnect (ns, GNUNET_NO); + GNUNET_NAMESTORE_disconnect (ns); ns = NULL; } if (NULL != httpd) @@ -721,11 +890,9 @@ run (void *cls, char *const *args, const char *cfgfile, "HTTPPORT", &port)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Option `%s' not specified in configuration section `%s'\n"), - "HTTPPORT", - "fcfsd"); - return; + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "fcfsd", "HTTPPORT"); + return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, @@ -733,10 +900,8 @@ run (void *cls, char *const *args, const char *cfgfile, "ZONEKEY", &keyfile)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Option `%s' not specified in configuration section `%s'\n"), - "ZONEKEY", - "fcfsd"); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "fcfsd", "ZONEKEY"); return; } fcfs_zone_pkey = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); @@ -771,7 +936,7 @@ run (void *cls, char *const *args, const char *cfgfile, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start HTTP server\n")); - GNUNET_NAMESTORE_disconnect (ns, GNUNET_NO); + GNUNET_NAMESTORE_disconnect (ns); ns = NULL; return; } @@ -797,6 +962,9 @@ main (int argc, char *const *argv) int ret; + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + return 2; + GNUNET_log_setup ("fcfsd", "WARNING", NULL); ret = (GNUNET_OK == @@ -804,7 +972,7 @@ main (int argc, char *const *argv) _("GNUnet GNS first come first serve registration service"), options, &run, NULL)) ? 0 : 1; - + GNUNET_free ((void*) argv); return ret; } diff --git a/src/gns/gnunet-gns-helper-service-w32.c b/src/gns/gnunet-gns-helper-service-w32.c new file mode 100644 index 0000000..72956c8 --- /dev/null +++ b/src/gns/gnunet-gns-helper-service-w32.c @@ -0,0 +1,749 @@ +/* + 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-gns-helper-service-w32.c + * @brief an intermediary service to access distributed GNS + * @author Christian Grothoff + * @author LRN + */ +#define INITGUID +#include "platform.h" +#include <gnunet_util_lib.h> +#include <gnunet_dnsparser_lib.h> +#include <gnunet_namestore_service.h> +#include <gnunet_gns_service.h> +#include "gnunet_w32nsp_lib.h" +#include "w32resolver.h" +#include <nspapi.h> +#include <unistr.h> + +#define DEFINE_DNS_GUID(a,x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46) +DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021); +DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + +struct request +{ + struct GNUNET_SERVER_Client *client; + GUID sc; + int af; + wchar_t *name; + char *u8name; +}; + +/** + * Handle to GNS service. + */ +static struct GNUNET_GNS_Handle *gns; + +static struct GNUNET_CRYPTO_ShortHashCode *zone = NULL; +static struct GNUNET_CRYPTO_ShortHashCode user_zone; +struct GNUNET_CRYPTO_RsaPrivateKey *shorten_key = NULL; + + +/** + * 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 != gns) + { + GNUNET_GNS_disconnect (gns); + gns = NULL; + } +} + +/** + * Context for transmitting replies to clients. + */ +struct TransmitCallbackContext +{ + + /** + * We keep these in a doubly-linked list (for cleanup). + */ + struct TransmitCallbackContext *next; + + /** + * We keep these in a doubly-linked list (for cleanup). + */ + struct TransmitCallbackContext *prev; + + /** + * The message that we're asked to transmit. + */ + struct GNUNET_MessageHeader *msg; + + /** + * Handle for the transmission request. + */ + struct GNUNET_SERVER_TransmitHandle *th; + + /** + * Client that we are transmitting to. + */ + struct GNUNET_SERVER_Client *client; + +}; + + +/** + * Head of the doubly-linked list (for cleanup). + */ +static struct TransmitCallbackContext *tcc_head; + +/** + * Tail of the doubly-linked list (for cleanup). + */ +static struct TransmitCallbackContext *tcc_tail; + +/** + * Have we already cleaned up the TCCs and are hence no longer + * willing (or able) to transmit anything to anyone? + */ +static int cleaning_done; + +/** + * Function called to notify a client about the socket + * begin ready to queue more data. "buf" will be + * NULL and "size" zero if the socket was closed for + * writing in the meantime. + * + * @param cls closure + * @param size number of bytes available in buf + * @param buf where the callee should write the message + * @return number of bytes written to buf + */ +static size_t +transmit_callback (void *cls, size_t size, void *buf) +{ + struct TransmitCallbackContext *tcc = cls; + size_t msize; + + tcc->th = NULL; + GNUNET_CONTAINER_DLL_remove (tcc_head, tcc_tail, tcc); + msize = ntohs (tcc->msg->size); + if (size == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Transmission to client failed!\n")); + GNUNET_SERVER_client_drop (tcc->client); + GNUNET_free (tcc->msg); + GNUNET_free (tcc); + return 0; + } + GNUNET_assert (size >= msize); + memcpy (buf, tcc->msg, msize); + GNUNET_SERVER_client_drop (tcc->client); + GNUNET_free (tcc->msg); + GNUNET_free (tcc); + return msize; +} + + +/** + * Transmit the given message to the client. + * + * @param client target of the message + * @param msg message to transmit, will be freed! + */ +static void +transmit (struct GNUNET_SERVER_Client *client, + struct GNUNET_MessageHeader *msg) +{ + struct TransmitCallbackContext *tcc; + + if (GNUNET_YES == cleaning_done) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Shutdown in progress, aborting transmission.\n")); + GNUNET_SERVER_client_drop (client); + GNUNET_free (msg); + return; + } + tcc = GNUNET_malloc (sizeof (struct TransmitCallbackContext)); + tcc->msg = msg; + tcc->client = client; + if (NULL == + (tcc->th = + GNUNET_SERVER_notify_transmit_ready (client, + ntohs (msg->size), + GNUNET_TIME_UNIT_FOREVER_REL, + &transmit_callback, tcc))) + { + GNUNET_break (0); + GNUNET_SERVER_client_drop (client); + GNUNET_free (msg); + GNUNET_free (tcc); + return; + } + GNUNET_SERVER_client_keep (client); + GNUNET_CONTAINER_DLL_insert (tcc_head, tcc_tail, tcc); +} + +#define MarshallPtr(ptr, base, type) \ + if (ptr) \ + ptr = (type *) ((char *) ptr - (char *) base) + +void +MarshallWSAQUERYSETW (WSAQUERYSETW *qs, GUID *sc) +{ + int i; + MarshallPtr (qs->lpszServiceInstanceName, qs, wchar_t); + MarshallPtr (qs->lpServiceClassId, qs, GUID); + MarshallPtr (qs->lpVersion, qs, WSAVERSION); + MarshallPtr (qs->lpNSProviderId, qs, GUID); + MarshallPtr (qs->lpszContext, qs, wchar_t); + MarshallPtr (qs->lpafpProtocols, qs, AFPROTOCOLS); + MarshallPtr (qs->lpszQueryString, qs, wchar_t); + for (i = 0; i < qs->dwNumberOfCsAddrs; i++) + { + MarshallPtr (qs->lpcsaBuffer[i].LocalAddr.lpSockaddr, qs, SOCKADDR); + MarshallPtr (qs->lpcsaBuffer[i].RemoteAddr.lpSockaddr, qs, SOCKADDR); + } + MarshallPtr (qs->lpcsaBuffer, qs, CSADDR_INFO); + if (IsEqualGUID (&SVCID_INET_HOSTADDRBYNAME, sc) && qs->lpBlob != NULL && qs->lpBlob->pBlobData != NULL) + { + struct hostent *he; + he = (struct hostent *) qs->lpBlob->pBlobData; + for (i = 0; he->h_aliases[i] != NULL; i++) + MarshallPtr (he->h_aliases[i], he, char); + MarshallPtr (he->h_aliases, he, char *); + MarshallPtr (he->h_name, he, char); + for (i = 0; he->h_addr_list[i] != NULL; i++) + MarshallPtr (he->h_addr_list[i], he, void); + MarshallPtr (he->h_addr_list, he, char *); + MarshallPtr (qs->lpBlob->pBlobData, qs, void); + } + MarshallPtr (qs->lpBlob, qs, BLOB); +} + + +static void +process_ip_lookup_result (void* cls, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + int i, j, csanum; + struct request *rq = (struct request *) cls; + struct GNUNET_W32RESOLVER_GetMessage *msg; + struct GNUNET_MessageHeader *msgend; + WSAQUERYSETW *qs; + size_t size; + size_t size_recalc; + char *ptr; + size_t blobsize = 0; + size_t blobaddrcount = 0; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got lookup result with count %u for rq %p with client %p\n", + rd_count, rq, rq->client); + + if (rd_count == 0) + { + size = sizeof (struct GNUNET_MessageHeader); + msg = GNUNET_malloc (size); + msg->header.size = htons (size); + msg->header.type = htons (GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE); + transmit (rq->client, &msg->header); + return; + } + + size = sizeof (struct GNUNET_W32RESOLVER_GetMessage) + sizeof (WSAQUERYSETW); + size += (wcslen (rq->name) + 1) * sizeof (wchar_t); + size += sizeof (GUID); + /* lpszComment ? a TXT record? */ + size += sizeof (GUID); + /* lpszContext ? Not sure what it is */ + csanum = 0; + for (i = 0; i < rd_count; i++) + { + switch (rd[i].record_type) + { + case GNUNET_GNS_RECORD_A: + if (rd[i].data_size != sizeof (struct in_addr)) + continue; + size += sizeof (CSADDR_INFO) + sizeof (struct sockaddr_in) * 2; + csanum++; + break; + case GNUNET_GNS_RECORD_AAAA: + if (rd[i].data_size != sizeof (struct in6_addr)) + continue; + size += sizeof (CSADDR_INFO) + sizeof (struct sockaddr_in6) * 2; + csanum++; + break; + } + } + if (IsEqualGUID (&SVCID_INET_HOSTADDRBYNAME, &rq->sc)) + { + size += sizeof (BLOB); + blobsize += sizeof (struct hostent); + blobsize += strlen (rq->u8name) + 1; + blobsize += sizeof (void *); /* For aliases */ + blobsize += sizeof (void *); /* For addresses */ + for (i = 0; i < rd_count; i++) + { + if ((rq->af == AF_INET || rq->af == AF_UNSPEC) && rd[i].record_type == GNUNET_GNS_RECORD_A) + { + blobsize += sizeof (void *); + blobsize += sizeof (struct in_addr); + blobaddrcount++; + } + else if (rq->af == AF_INET6 && rd[i].record_type == GNUNET_GNS_RECORD_AAAA) + { + blobsize += sizeof (void *); + blobsize += sizeof (struct in6_addr); + blobaddrcount++; + } + } + size += blobsize; + } + size += sizeof (struct GNUNET_MessageHeader); + size_recalc = sizeof (struct GNUNET_W32RESOLVER_GetMessage) + sizeof (WSAQUERYSETW); + msg = GNUNET_malloc (size); + msg->header.size = htons (size - sizeof (struct GNUNET_MessageHeader)); + msg->header.type = htons (GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE); + msg->af = htonl (rq->af); + msg->sc_data1 = htonl (rq->sc.Data1); + msg->sc_data2 = htons (rq->sc.Data2); + msg->sc_data3 = htons (rq->sc.Data3); + msg->sc_data4 = 0; + for (i = 0; i < 8; i++) + msg->sc_data4 |= rq->sc.Data4[i] << ((7 - i) * 8); + msg->sc_data4 = GNUNET_htonll (msg->sc_data4); + qs = (WSAQUERYSETW *) &msg[1]; + ptr = (char *) &qs[1]; + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + qs->dwSize = sizeof (WSAQUERYSETW); + qs->lpszServiceInstanceName = (wchar_t *) ptr; + ptr += (wcslen (rq->name) + 1) * sizeof (wchar_t); + size_recalc += (wcslen (rq->name) + 1) * sizeof (wchar_t); + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + wcscpy (qs->lpszServiceInstanceName, rq->name); + qs->lpServiceClassId = (GUID *) ptr; + ptr += sizeof (GUID); + size_recalc += sizeof (GUID); + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + memcpy (qs->lpServiceClassId, &rq->sc, sizeof (GUID)); + qs->lpVersion = NULL; + qs->dwNameSpace = NS_DNS; + qs->lpNSProviderId = (GUID *) ptr; + ptr += sizeof (GUID); + size_recalc += sizeof (GUID); + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + memcpy (qs->lpNSProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS, sizeof (GUID)); + qs->lpszContext = NULL; + qs->dwNumberOfProtocols = 0; + qs->lpafpProtocols = NULL; + /* Don't bother with this... */ + qs->lpszQueryString = NULL; + qs->dwNumberOfCsAddrs = rd_count; + qs->lpcsaBuffer = (CSADDR_INFO *) ptr; + ptr += sizeof (CSADDR_INFO) * csanum; + j = 0; + for (i = 0; i < rd_count; i++) + { + switch (rd[i].record_type) + { + case GNUNET_GNS_RECORD_A: + if (rd[i].data_size != sizeof (struct in_addr)) + continue; + qs->lpcsaBuffer[j].iSocketType = SOCK_STREAM; + qs->lpcsaBuffer[j].iProtocol = IPPROTO_TCP; + + qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength = sizeof (struct sockaddr_in); + qs->lpcsaBuffer[j].LocalAddr.lpSockaddr = (SOCKADDR *) ptr; + ptr += qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength; + memset (qs->lpcsaBuffer[j].LocalAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength); + ((struct sockaddr_in *)qs->lpcsaBuffer[j].LocalAddr.lpSockaddr)->sin_family = AF_INET; + + qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength = sizeof (struct sockaddr_in); + qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr = (SOCKADDR *) ptr; + ptr += qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength; + memset (qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength); + ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_family = AF_INET; + ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_port = htonl (53); /* Don't ask why it's 53 */ + ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_addr = *(struct in_addr *) rd[i].data; + size_recalc += sizeof (CSADDR_INFO) + sizeof (struct sockaddr_in) * 2; + j++; + break; + case GNUNET_GNS_RECORD_AAAA: + if (rd[i].data_size != sizeof (struct in6_addr)) + continue; + qs->lpcsaBuffer[j].iSocketType = SOCK_STREAM; + qs->lpcsaBuffer[j].iProtocol = IPPROTO_TCP; + + qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength = sizeof (struct sockaddr_in6); + qs->lpcsaBuffer[j].LocalAddr.lpSockaddr = (SOCKADDR *) ptr; + ptr += qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength; + memset (qs->lpcsaBuffer[j].LocalAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength); + ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].LocalAddr.lpSockaddr)->sin6_family = AF_INET6; + + qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength = sizeof (struct sockaddr_in6); + qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr = (SOCKADDR *) ptr; + ptr += qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength; + memset (qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength); + ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_family = AF_INET6; + ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_port = htonl (53); /* Don't ask why it's 53 */ + ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_addr = *(struct in6_addr *) rd[i].data; + size_recalc += sizeof (CSADDR_INFO) + sizeof (struct sockaddr_in6) * 2; + j++; + break; + default: + break; + } + } + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + qs->dwOutputFlags = 0; + if (IsEqualGUID (&SVCID_INET_HOSTADDRBYNAME, &rq->sc)) + { + struct hostent *he; + qs->lpBlob = (BLOB *) ptr; + ptr += sizeof (BLOB); + + size_recalc += sizeof (BLOB); + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + + qs->lpBlob->cbSize = blobsize; + qs->lpBlob->pBlobData = (BYTE *) ptr; + ptr += sizeof (struct hostent); + + size_recalc += sizeof (struct hostent); + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + + he = (struct hostent *) qs->lpBlob->pBlobData; + he->h_name = (char *) ptr; + ptr += strlen (rq->u8name) + 1; + + size_recalc += strlen (rq->u8name) + 1; + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + + strcpy (he->h_name, rq->u8name); + he->h_aliases = (char **) ptr; + ptr += sizeof (void *); + + size_recalc += sizeof (void *); /* For aliases */ + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + + he->h_aliases[0] = NULL; + he->h_addrtype = rq->af; + he->h_length = rq->af == AF_INET || rq->af == AF_UNSPEC ? sizeof (struct in_addr) : sizeof (struct in6_addr); + he->h_addr_list = (char **) ptr; + ptr += sizeof (void *) * (blobaddrcount + 1); + + size_recalc += sizeof (void *) * (blobaddrcount + 1); /* For addresses */ + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + + j = 0; + for (i = 0; i < rd_count; i++) + { + if ((rq->af == AF_INET || rq->af == AF_UNSPEC) && + rd[i].record_type == GNUNET_GNS_RECORD_A) + { + he->h_addr_list[j] = (char *) ptr; + ptr += sizeof (struct in_addr); + + size_recalc += sizeof (struct in_addr); + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + + memcpy (he->h_addr_list[j], rd[i].data, sizeof (struct in_addr)); + j++; + } + else if (rq->af == AF_INET6 && rd[i].record_type == GNUNET_GNS_RECORD_AAAA) + { + he->h_addr_list[j] = (char *) ptr; + ptr += sizeof (struct in6_addr); + + size_recalc += sizeof (struct in6_addr); + GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); + + memcpy (he->h_addr_list[j], rd[i].data, sizeof (struct in6_addr)); + j++; + } + } + he->h_addr_list[j] = NULL; + } + msgend = (struct GNUNET_MessageHeader *) ptr; + ptr += sizeof (struct GNUNET_MessageHeader); + size_recalc += sizeof (struct GNUNET_MessageHeader); + + msgend->type = htons (GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE); + msgend->size = htons (sizeof (struct GNUNET_MessageHeader)); + + if ((char *) ptr - (char *) msg != size || size_recalc != size || size_recalc != ((char *) ptr - (char *) msg)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error in WSAQUERYSETW size calc: expected %lu, got %lu (recalc %lu)\n", size, (unsigned long) ((char *) ptr - (char *) msg), size_recalc); + } + MarshallWSAQUERYSETW (qs, &rq->sc); + transmit (rq->client, &msg->header); +} + +static void +get_ip_from_hostname (struct GNUNET_SERVER_Client *client, + const wchar_t *name, int af, GUID sc) +{ + struct request *rq; + char *hostname; + size_t strl; + size_t namelen; + uint32_t rtype; + + if (IsEqualGUID (&SVCID_DNS_TYPE_A, &sc)) + rtype = GNUNET_GNS_RECORD_A; + else if (IsEqualGUID (&SVCID_DNS_TYPE_NS, &sc)) + rtype = GNUNET_GNS_RECORD_NS; + else if (IsEqualGUID (&SVCID_DNS_TYPE_CNAME, &sc)) + rtype = GNUNET_GNS_RECORD_CNAME; + else if (IsEqualGUID (&SVCID_DNS_TYPE_SOA, &sc)) + rtype = GNUNET_GNS_RECORD_SOA; + else if (IsEqualGUID (&SVCID_DNS_TYPE_PTR, &sc)) + rtype = GNUNET_GNS_RECORD_PTR; + else if (IsEqualGUID (&SVCID_DNS_TYPE_MX, &sc)) + rtype = GNUNET_GNS_RECORD_MX; + else if (IsEqualGUID (&SVCID_DNS_TYPE_TEXT, &sc)) + rtype = GNUNET_GNS_RECORD_TXT; + else if (IsEqualGUID (&SVCID_DNS_TYPE_AAAA, &sc)) + rtype = GNUNET_GNS_RECORD_AAAA; + else if (IsEqualGUID (&SVCID_DNS_TYPE_SRV, &sc)) + rtype = GNUNET_GNS_RECORD_SRV; + else if (IsEqualGUID (&SVCID_INET_HOSTADDRBYNAME, &sc)) + rtype = GNUNET_GNS_RECORD_A; + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Unknown GUID: %08X-%04X-%04X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n", + sc.Data1, sc.Data2, sc.Data3, sc.Data4[0], sc.Data4[1], sc.Data4[2], + sc.Data4[3], sc.Data4[4], sc.Data4[5], sc.Data4[6], sc.Data4[7]); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + + if (name) + namelen = wcslen (name); + else + namelen = 0; + if (namelen > 0) + hostname = (char *) u16_to_u8 (name, namelen + 1, NULL, &strl); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "W32 DNS resolver asked to look up %s for `%s'.\n", + af == AF_INET ? "IPv4" : af == AF_INET6 ? "IPv6" : "anything", + hostname); + rq = GNUNET_malloc (sizeof (struct request)); + rq->sc = sc; + rq->client = client; + rq->af = af; + if (rq->af != AF_INET && rq->af != AF_INET6) + rq->af = AF_INET; + if (namelen) + { + rq->name = GNUNET_malloc ((namelen + 1) * sizeof (wchar_t)); + memcpy (rq->name, name, (namelen + 1) * sizeof (wchar_t)); + rq->u8name = hostname; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Launching a lookup for client %p with rq %p\n", + client, rq); + + if (NULL != GNUNET_GNS_lookup_zone (gns, hostname, zone, rtype, + GNUNET_YES, shorten_key, &process_ip_lookup_result, rq)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Lookup launched, waiting for a reply\n"); + GNUNET_SERVER_client_keep (client); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Lookup was not, disconnecting the client\n"); + if (namelen) + { + GNUNET_free (rq->name); + free (rq->u8name); + } + GNUNET_free (rq); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + } +} + +/** + * Handle GET-message. + * + * @param cls closure + * @param client identification of the client + * @param message the actual message + */ +static void +handle_get (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + uint16_t msize; + const struct GNUNET_W32RESOLVER_GetMessage *msg; + GUID sc; + uint16_t size; + uint64_t data4; + int i; + const wchar_t *hostname; + int af; + + msize = ntohs (message->size); + if (msize < sizeof (struct GNUNET_W32RESOLVER_GetMessage)) + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + msg = (const struct GNUNET_W32RESOLVER_GetMessage *) message; + size = msize - sizeof (struct GNUNET_W32RESOLVER_GetMessage); + af = ntohl (msg->af); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got NBO GUID: %08X-%04X-%04X-%016llX\n", + msg->sc_data1, msg->sc_data2, msg->sc_data3, msg->sc_data4); + sc.Data1 = ntohl (msg->sc_data1); + sc.Data2 = ntohs (msg->sc_data2); + sc.Data3 = ntohs (msg->sc_data3); + data4 = GNUNET_ntohll (msg->sc_data4); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got GUID: %08X-%04X-%04X-%016llX\n", + sc.Data1, sc.Data2, sc.Data3, data4); + for (i = 0; i < 8; i++) + sc.Data4[i] = 0xFF & (data4 >> ((7 - i) * 8)); + + hostname = (const wchar_t *) &msg[1]; + if (hostname[size - 1] != L'\0') + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "name of length %u, not 0-terminated: %*S\n", + size, size, hostname); + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + get_ip_from_hostname (client, hostname, af, sc); + return; +} + + +/** + * Start up gns-helper-w32 service. + * + * @param cls closure + * @param server the initialized server + * @param cfg configuration to use + */ +static void +run (void *cls, struct GNUNET_SERVER_Handle *server, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + static const struct GNUNET_SERVER_MessageHandler handlers[] = { + {&handle_get, NULL, GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST, 0}, + {NULL, NULL, 0, 0} + }; + + char* keyfile; + struct GNUNET_CRYPTO_RsaPrivateKey *key = NULL; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; + struct GNUNET_CRYPTO_ShortHashAsciiEncoded zonename; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", &keyfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "No private key for root zone found, using default!\n"); + zone = NULL; + } + else + { + if (GNUNET_YES == GNUNET_DISK_file_test (keyfile)) + { + key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); + GNUNET_CRYPTO_short_hash(&pkey, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &user_zone); + zone = &user_zone; + GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Using zone: %s!\n", &zonename); + GNUNET_CRYPTO_rsa_key_free(key); + } + GNUNET_free(keyfile); + } + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "SHORTEN_ZONEKEY", &keyfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "No shorten key found!\n"); + shorten_key = NULL; + } + else + { + if (GNUNET_YES == GNUNET_DISK_file_test (keyfile)) + { + shorten_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + } + GNUNET_free(keyfile); + } + + gns = GNUNET_GNS_connect (cfg); + if (gns == NULL) + return; + + GNUNET_SERVER_add_handlers (server, handlers); + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, + NULL); + +} + + +/** + * The main function for gns-helper-w32. + * + * @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) +{ + int ret; + + ret = + (GNUNET_OK == + GNUNET_SERVICE_run (argc, argv, "gns-helper-service-w32", GNUNET_SERVICE_OPTION_NONE, + &run, NULL)) ? 0 : 1; + + return ret; +} + +/* end of gnunet-gns.c */ diff --git a/src/gns/gnunet-gns-proxy-setup-ca b/src/gns/gnunet-gns-proxy-setup-ca new file mode 100644 index 0000000..4564583 --- /dev/null +++ b/src/gns/gnunet-gns-proxy-setup-ca @@ -0,0 +1,31 @@ +echo "Generating CA" + +openssl req -new -x509 -days 3650 -extensions v3_ca -keyout gnscakey.pem -out gnscacert.pem -subj "/C=DE/ST=Bavaria/L=Munich/O=GADS/OU=GNUnet/CN=GADS Proxy CA/emailAddress=bounce@gnunet.org" -passout pass:"GNUnet Naming System" + +echo "Removing passphrase from key" +openssl rsa -passin pass:"GNUnet Naming System" -in gnscakey.pem -out gnscakeynoenc.pem + +cp gnscacert.pem $HOME/.gnunet/gns/gnscert.pem +cat gnscacert.pem > $HOME/.gnunet/gns/gnsCAcert.pem +cat gnscakeynoenc.pem >> $HOME/.gnunet/gns/gnsCAcert.pem + +echo "Importing CA into browsers" +for f in ~/.mozilla/firefox/*.default +do + if [ -d $f ]; then + echo "Importing CA info firefox $f" + certutil -D -n "GNS Proxy CA" -d ~/.mozilla/firefox/*.default >/dev/null 2&>1 + certutil -A -n "GNS Proxy CA" -t CT,, -d ~/.mozilla/firefox/*.default < gnscacert.pem + fi +done + +if [ -d ~/.pki/nssdb ]; then + echo "Importing CA into chrome" + certutil -D -n "GADS Proxy CA" -d ~/.pki/nssdb >/dev/null 2&>1 + certutil -A -n "GADS Proxy CA" -t CT,, -d ~/.pki/nssdb < gnscacert.pem +fi + + +rm gnscakey.pem gnscakeynoenc.pem gnscacert.pem + +echo "You can now start gnunet-gns-proxy and configure your browser to use a SOCKS proxy on port 7777" diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c index 876f531..7b78378 100644 --- a/src/gns/gnunet-gns-proxy.c +++ b/src/gns/gnunet-gns-proxy.c @@ -17,93 +17,1865 @@ Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - +/** + * @author Martin Schanzenbach + * @file src/gns/gnunet-gns-proxy.c + * @brief HTTP(S) proxy that rewrites URIs and fakes certificats to make GADS work + * with legacy browsers + */ #include "platform.h" -#include <gnunet_util_lib.h> #include <microhttpd.h> +#include <curl/curl.h> +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> +#include <gnutls/abstract.h> +#include <gnutls/crypto.h> +#include <regex.h> +#include "gnunet_util_lib.h" +#include "gnunet_gns_service.h" #include "gns_proxy_proto.h" #include "gns.h" +#define HAVE_MHD_NO_LISTEN_SOCKET (MHD_VERSION >= 0x00091401) + #define GNUNET_GNS_PROXY_PORT 7777 +#define MHD_MAX_CONNECTIONS 300 +#define MAX_HTTP_URI_LENGTH 2048 +#define POSTBUFFERSIZE 4096 + +/* MHD/cURL defines */ +enum BufferStatus + { + BUF_WAIT_FOR_CURL, + BUF_WAIT_FOR_MHD, + BUF_WAIT_FOR_PP + }; + +#define HTML_HDR_CONTENT "Content-Type: text/html" + +/* buffer padding for proper RE matching */ +#define CURL_BUF_PADDING 1000 + +/* regexp */ +//#define RE_DOTPLUS "<a href=\"http://(([A-Za-z]+[.])+)([+])" +#define RE_A_HREF "href=\"https?://(([A-Za-z0-9]+[.])+)([+]|[a-z]+)" +#define RE_N_MATCHES 4 + +/* The usual suspects */ +#define HTTP_PORT 80 +#define HTTPS_PORT 443 + -//TODO maybe make this an api call /** - * Checks if name is in tld - * - * @param name the name to check - * @param tld the TLD to check for - * @return GNUNET_YES or GNUNET_NO + * A structure for CA cert/key */ -int -is_tld(const char* name, const char* tld) +struct ProxyCA { - int offset = 0; + /* The certificate */ + gnutls_x509_crt_t cert; - if (strlen(name) <= strlen(tld)) - { - return GNUNET_NO; - } + /* The private key */ + gnutls_x509_privkey_t key; +}; - offset = strlen(name)-strlen(tld); - if (strcmp (name+offset, tld) != 0) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "%s is not in .%s TLD\n", name, tld); - return GNUNET_NO; - } +#define MAX_PEM_SIZE (10 * 1024) + +/** + * Structure for GNS certificates + */ +struct ProxyGNSCertificate +{ + /* The certificate as PEM */ + char cert[MAX_PEM_SIZE]; + + /* The private key as PEM */ + char key[MAX_PEM_SIZE]; +}; - return GNUNET_YES; -} +/** + * A structure for socks requests + */ struct Socks5Request { + /* The client socket */ struct GNUNET_NETWORK_Handle *sock; - struct GNUNET_NETWORK_Handle *remote_sock; + /* The server socket */ + struct GNUNET_NETWORK_Handle *remote_sock; + + /* The socks state */ int state; - + + /* Client socket read task */ GNUNET_SCHEDULER_TaskIdentifier rtask; + + /* Server socket read task */ GNUNET_SCHEDULER_TaskIdentifier fwdrtask; + + /* Client socket write task */ GNUNET_SCHEDULER_TaskIdentifier wtask; + + /* Server socket write task */ GNUNET_SCHEDULER_TaskIdentifier fwdwtask; + /* Read buffer */ char rbuf[2048]; + + /* Write buffer */ char wbuf[2048]; + + /* Length of data in read buffer */ unsigned int rbuf_len; + + /* Length of data in write buffer */ unsigned int wbuf_len; + + /* This handle is scheduled for cleanup? */ + int cleanup; + + /* Shall we close the client socket on cleanup? */ + int cleanup_sock; +}; + +/** + * DLL for Network Handles + */ +struct NetworkHandleList +{ + /*DLL*/ + struct NetworkHandleList *next; + + /*DLL*/ + struct NetworkHandleList *prev; + + /* The handle */ + struct GNUNET_NETWORK_Handle *h; +}; + +/** + * A structure for all running Httpds + */ +struct MhdHttpList +{ + /* DLL for httpds */ + struct MhdHttpList *prev; + + /* DLL for httpds */ + struct MhdHttpList *next; + + /* is this an ssl daemon? */ + int is_ssl; + + /* the domain name to server (only important for SSL) */ + char domain[256]; + + /* The daemon handle */ + struct MHD_Daemon *daemon; + + /* Optional proxy certificate used */ + struct ProxyGNSCertificate *proxy_cert; + + /* The task ID */ + GNUNET_SCHEDULER_TaskIdentifier httpd_task; + + /* Handles associated with this daemon */ + struct NetworkHandleList *socket_handles_head; + + /* Handles associated with this daemon */ + struct NetworkHandleList *socket_handles_tail; +}; + +/** + * A structure for MHD<->cURL streams + */ +struct ProxyCurlTask +{ + /* DLL for tasks */ + struct ProxyCurlTask *prev; + + /* DLL for tasks */ + struct ProxyCurlTask *next; + + /* Handle to cURL */ + CURL *curl; + + /* Optional header replacements for curl (LEHO) */ + struct curl_slist *headers; + + /* Optional resolver replacements for curl (LEHO) */ + struct curl_slist *resolver; + + /* curl response code */ + long curl_response_code; + + /* The URL to fetch */ + char url[MAX_HTTP_URI_LENGTH]; + + /* The cURL write buffer / MHD read buffer */ + char buffer[CURL_MAX_WRITE_SIZE + CURL_BUF_PADDING]; + + /* Read pos of the data in the buffer */ + char *buffer_read_ptr; + + /* Write pos in the buffer */ + char *buffer_write_ptr; + + /* connection */ + struct MHD_Connection *connection; + + /*put*/ + size_t put_read_offset; + size_t put_read_size; + + /*post*/ + struct MHD_PostProcessor *post_handler; + + /* post data */ + struct ProxyUploadData *upload_data_head; + struct ProxyUploadData *upload_data_tail; + + /* the type of POST encoding */ + char* post_type; + + struct curl_httppost *httppost; + + struct curl_httppost *httppost_last; + + /* Number of bytes in buffer */ + unsigned int bytes_in_buffer; + + /* PP task */ + GNUNET_SCHEDULER_TaskIdentifier pp_task; + + /* PP match list */ + struct ProxyREMatch *pp_match_head; + + /* PP match list */ + struct ProxyREMatch *pp_match_tail; + + /* The associated daemon list entry */ + struct MhdHttpList *mhd; + + /* The associated response */ + struct MHD_Response *response; + + /* Cookies to set */ + struct ProxySetCookieHeader *set_cookies_head; + + /* Cookies to set */ + struct ProxySetCookieHeader *set_cookies_tail; + + /* The authority of the corresponding host (site of origin) */ + char authority[256]; + + /* The hostname (Host header field) */ + char host[256]; + + /* The LEgacy HOstname (can be empty) */ + char leho[256]; + + /* The port */ + uint16_t port; + + /* The buffer status (BUF_WAIT_FOR_CURL or BUF_WAIT_FOR_MHD) */ + enum BufferStatus buf_status; + + /* connection status */ + int ready_to_queue; + + /* is curl running? */ + int curl_running; + + /* are we done */ + int fin; + + /* Already accepted */ + int accepted; + + /* Indicates wheather the download is in progress */ + int download_in_progress; + + /* Indicates wheather the download was successful */ + int download_is_finished; + + /* Indicates wheather the download failed */ + int download_error; + + /* Indicates wheather we need to parse HTML */ + int parse_content; + + /* Indicates wheather we are postprocessing the HTML right now */ + int is_postprocessing; + + /* Indicates wheather postprocessing has finished */ + int pp_finished; + + int post_done; + + int is_httppost; + +}; + +/** + * Struct for RE matches in postprocessing of HTML + */ +struct ProxyREMatch +{ + /* DLL */ + struct ProxyREMatch *next; + + /* DLL */ + struct ProxyREMatch *prev; + + /* start of match in buffer */ + char* start; + + /* end of match in buffer */ + char* end; + + /* associated proxycurltask */ + struct ProxyCurlTask *ctask; + + /* hostname found */ + char hostname[255]; + + /* PP result */ + char result[255]; + + /* shorten task */ + struct GNUNET_GNS_ShortenRequest *shorten_task; + + /* are we done */ + int done; + + /* is SSL */ + int is_ssl; + +}; + +/** + * Struct for set-cookies + */ +struct ProxySetCookieHeader +{ + /* DLL */ + struct ProxySetCookieHeader *next; + + /* DLL */ + struct ProxySetCookieHeader *prev; + + /* the cookie */ + char *cookie; }; -unsigned long port = GNUNET_GNS_PROXY_PORT; +/** + * Post data structure + */ +struct ProxyUploadData +{ + /* DLL */ + struct ProxyUploadData *next; + + /* DLL */ + struct ProxyUploadData *prev; + + char *key; + + char *filename; + + char *content_type; + + size_t content_length; + + /* value */ + char *value; + + /* to copy */ + size_t bytes_left; + + /* size */ + size_t total_bytes; +}; + + +/* The port the proxy is running on (default 7777) */ +static unsigned long port = GNUNET_GNS_PROXY_PORT; + +/* The CA file (pem) to use for the proxy CA */ +static char* cafile_opt; + +/* The listen socket of the proxy */ static struct GNUNET_NETWORK_Handle *lsock; -GNUNET_SCHEDULER_TaskIdentifier ltask; + +/* The listen task ID */ +static GNUNET_SCHEDULER_TaskIdentifier ltask; + +/* The cURL download task */ +static GNUNET_SCHEDULER_TaskIdentifier curl_download_task; + +/* The non SSL httpd daemon handle */ static struct MHD_Daemon *httpd; -static GNUNET_SCHEDULER_TaskIdentifier httpd_task; +/* Number of current mhd connections */ +static unsigned int total_mhd_connections; + +/* The cURL multi handle */ +static CURLM *curl_multi; + +/* Handle to the GNS service */ +static struct GNUNET_GNS_Handle *gns_handle; + +/* DLL for ProxyCurlTasks */ +static struct ProxyCurlTask *ctasks_head; + +/* DLL for ProxyCurlTasks */ +static struct ProxyCurlTask *ctasks_tail; + +/* DLL for http daemons */ +static struct MhdHttpList *mhd_httpd_head; + +/* DLL for http daemons */ +static struct MhdHttpList *mhd_httpd_tail; + +/* Handle to the regex for dotplus (.+) replacement in HTML */ +static regex_t re_dotplus; + +/* The users local GNS zone hash */ +static struct GNUNET_CRYPTO_ShortHashCode *local_gns_zone; + +/* The users local private zone */ +static struct GNUNET_CRYPTO_ShortHashCode *local_private_zone; + +/* The users local shorten zone */ +static struct GNUNET_CRYPTO_ShortHashCode *local_shorten_zone; + +/* The CA for SSL certificate generation */ +static struct ProxyCA proxy_ca; + +/* UNIX domain socket for mhd */ +#if !HAVE_MHD_NO_LISTEN_SOCKET +static struct GNUNET_NETWORK_Handle *mhd_unix_socket; +#endif + +/* Shorten zone private key */ +static struct GNUNET_CRYPTO_RsaPrivateKey *shorten_zonekey; + + +/** + * Checks if name is in tld + * + * @param name the name to check + * @param tld the TLD to check for (must NOT begin with ".") + * @return GNUNET_YES or GNUNET_NO + */ +static int +is_tld (const char* name, const char* tld) +{ + size_t name_len = strlen (name); + size_t tld_len = strlen (tld); + + GNUNET_break ('.' != tld[0]); + return ( (tld_len < name_len) && + ( ('.' == name[name_len - tld_len - 1]) || (name_len == tld_len) ) && + (0 == memcmp (tld, + name + (name_len - tld_len), + tld_len)) ); +} + + +static int +con_post_data_iter (void *cls, + enum MHD_ValueKind kind, + const char *key, + const char *filename, + const char *content_type, + const char *transfer_encoding, + const char *data, + uint64_t off, + size_t size) +{ + struct ProxyCurlTask* ctask = cls; + struct ProxyUploadData* pdata; + char* enc; + char* new_value; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got POST data (file: %s, content type: %s): '%s=%.*s' at offset %llu size %llu\n", + filename, content_type, + key, (int) size, data, + (unsigned long long) off, + (unsigned long long) size); + GNUNET_assert (NULL != ctask->post_type); + + if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, + ctask->post_type)) + { + ctask->is_httppost = GNUNET_YES; + /* new part */ + if (0 == off) + { + pdata = GNUNET_malloc (sizeof (struct ProxyUploadData)); + pdata->key = GNUNET_strdup (key); + + if (NULL != filename) + pdata->filename = GNUNET_strdup (filename); + if (NULL != content_type) + pdata->content_type = GNUNET_strdup (content_type); + pdata->value = GNUNET_malloc (size); + pdata->total_bytes = size; + memcpy (pdata->value, data, size); + GNUNET_CONTAINER_DLL_insert_tail (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Copied %llu bytes of POST Data\n", + (unsigned long long) size); + return MHD_YES; + } + + pdata = ctask->upload_data_tail; + new_value = GNUNET_malloc (size + pdata->total_bytes); + memcpy (new_value, pdata->value, pdata->total_bytes); + memcpy (new_value+off, data, size); + GNUNET_free (pdata->value); + pdata->value = new_value; + pdata->total_bytes += size; + + return MHD_YES; + } + + if (0 != strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, + ctask->post_type)) + { + return MHD_NO; + } + + ctask->is_httppost = GNUNET_NO; + + if (NULL != ctask->curl) + curl_easy_pause (ctask->curl, CURLPAUSE_CONT); + + if (0 == off) + { + enc = curl_easy_escape (ctask->curl, key, 0); + if (NULL == enc) + { + GNUNET_break (0); + return MHD_NO; + } + /* a key */ + pdata = GNUNET_malloc (sizeof (struct ProxyUploadData)); + pdata->value = GNUNET_malloc (strlen (enc) + 3); + if (NULL != ctask->upload_data_head) + { + pdata->value[0] = '&'; + memcpy (pdata->value+1, enc, strlen (enc)); + } + else + memcpy (pdata->value, enc, strlen (enc)); + pdata->value[strlen (pdata->value)] = '='; + pdata->bytes_left = strlen (pdata->value); + pdata->total_bytes = pdata->bytes_left; + curl_free (enc); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Escaped POST key: '%s'\n", + pdata->value); + + GNUNET_CONTAINER_DLL_insert_tail (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + } + + /* a value */ + enc = curl_easy_escape (ctask->curl, data, 0); + if (NULL == enc) + { + GNUNET_break (0); + return MHD_NO; + } + pdata = GNUNET_malloc (sizeof (struct ProxyUploadData)); + pdata->value = GNUNET_malloc (strlen (enc) + 1); + memcpy (pdata->value, enc, strlen (enc)); + pdata->bytes_left = strlen (pdata->value); + pdata->total_bytes = pdata->bytes_left; + curl_free (enc); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Escaped POST value: '%s'\n", + pdata->value); + + GNUNET_CONTAINER_DLL_insert_tail (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + return MHD_YES; +} + + +/** + * Read HTTP request header field 'Host' + * + * @param cls buffer to write to + * @param kind value kind + * @param key field key + * @param value field value + * @return MHD_NO when Host found + */ static int con_val_iter (void *cls, enum MHD_ValueKind kind, const char *key, const char *value) { - char* buf = (char*)cls; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "%s:%s\n", key, value); + struct ProxyCurlTask *ctask = cls; + char* buf = ctask->host; + char* port; + char* cstr; + const char* hdr_val; + unsigned int uport; if (0 == strcmp ("Host", key)) { - strcpy (buf, value); - return MHD_NO; + port = strchr (value, ':'); + if (NULL != port) + { + strncpy (buf, value, port-value); + port++; + if ((1 != sscanf (port, "%u", &uport)) || + (uport > UINT16_MAX) || + (0 == uport)) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to parse port!\n"); + else + ctask->port = (uint16_t) uport; + } + else + strcpy (buf, value); + return MHD_YES; } + + if (0 == strcmp (MHD_HTTP_HEADER_ACCEPT_ENCODING, key)) + hdr_val = ""; + else + hdr_val = value; + + if (0 == strcasecmp (MHD_HTTP_HEADER_CONTENT_TYPE, + key)) + { + if (0 == strncasecmp (value, + MHD_HTTP_POST_ENCODING_FORM_URLENCODED, + strlen (MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) + ctask->post_type = MHD_HTTP_POST_ENCODING_FORM_URLENCODED; + else if (0 == strncasecmp (value, + MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, + strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) + ctask->post_type = MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA; + else + ctask->post_type = NULL; + + } + + cstr = GNUNET_malloc (strlen (key) + strlen (hdr_val) + 3); + GNUNET_snprintf (cstr, strlen (key) + strlen (hdr_val) + 3, + "%s: %s", key, hdr_val); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client Header: %s\n", cstr); + + ctask->headers = curl_slist_append (ctask->headers, cstr); + GNUNET_free (cstr); + return MHD_YES; } + +/** + * Callback for MHD response + * + * @param cls closure + * @param pos in buffer + * @param buf buffer + * @param max space in buffer + * @return number of bytes written + */ +static ssize_t +mhd_content_cb (void *cls, + uint64_t pos, + char* buf, + size_t max); + + +/** + * Check HTTP response header for mime + * + * @param buffer curl buffer + * @param size curl blocksize + * @param nmemb curl blocknumber + * @param cls handle + * @return size of read bytes + */ +static size_t +curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) +{ + size_t bytes = size * nmemb; + struct ProxyCurlTask *ctask = cls; + int html_mime_len = strlen (HTML_HDR_CONTENT); + int cookie_hdr_len = strlen (MHD_HTTP_HEADER_SET_COOKIE); + char hdr_mime[html_mime_len+1]; + char hdr_generic[bytes+1]; + char new_cookie_hdr[bytes+strlen (ctask->leho)+1]; + char new_location[MAX_HTTP_URI_LENGTH+500]; + char real_host[264]; + char leho_host[264]; + char* ndup; + char* tok; + char* cookie_domain; + char* hdr_type; + char* hdr_val; + int delta_cdomain; + size_t offset = 0; + char cors_hdr[strlen (ctask->leho) + strlen ("https://")]; + + if (NULL == ctask->response) + { + /* FIXME: get total size from curl (if available) */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Creating response for %s\n", ctask->url); + ctask->response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, + sizeof (ctask->buffer), + &mhd_content_cb, + ctask, + NULL); + + /* if we have a leho add a CORS header */ + if (0 != strcmp ("", ctask->leho)) + { + /* We could also allow ssl and http here */ + if (ctask->mhd->is_ssl) + sprintf (cors_hdr, "https://%s", ctask->leho); + else + sprintf (cors_hdr, "http://%s", ctask->leho); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Adding CORS header field %s\n", + cors_hdr); + + if (GNUNET_NO == MHD_add_response_header (ctask->response, + "Access-Control-Allow-Origin", + cors_hdr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "MHD: Error adding CORS header field %s\n", + cors_hdr); + } + } + ctask->ready_to_queue = GNUNET_YES; + } + + if (html_mime_len <= bytes) + { + memcpy (hdr_mime, buffer, html_mime_len); + hdr_mime[html_mime_len] = '\0'; + + if (0 == strcmp (hdr_mime, HTML_HDR_CONTENT)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got HTML HTTP response header\n"); + ctask->parse_content = GNUNET_YES; + } + } + + if (cookie_hdr_len > bytes) + return bytes; + + memcpy (hdr_generic, buffer, bytes); + hdr_generic[bytes] = '\0'; + /* remove crlf */ + if ('\n' == hdr_generic[bytes-1]) + hdr_generic[bytes-1] = '\0'; + + if (hdr_generic[bytes-2] == '\r') + hdr_generic[bytes-2] = '\0'; + + if (0 == memcmp (hdr_generic, + MHD_HTTP_HEADER_SET_COOKIE, + cookie_hdr_len)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Looking for cookie in: `%s'\n", hdr_generic); + ndup = GNUNET_strdup (hdr_generic+cookie_hdr_len+1); + memset (new_cookie_hdr, 0, sizeof (new_cookie_hdr)); + for (tok = strtok (ndup, ";"); tok != NULL; tok = strtok (NULL, ";")) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got Cookie token: %s\n", tok); + //memcpy (new_cookie_hdr+offset, tok, strlen (tok)); + if (0 == memcmp (tok, " domain", strlen (" domain"))) + { + cookie_domain = tok + strlen (" domain") + 1; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got Set-Cookie Domain: %s\n", cookie_domain); + + if (strlen (cookie_domain) < strlen (ctask->leho)) + { + delta_cdomain = strlen (ctask->leho) - strlen (cookie_domain); + if (0 == strcmp (cookie_domain, ctask->leho + (delta_cdomain))) + { + GNUNET_snprintf (new_cookie_hdr+offset, + sizeof (new_cookie_hdr), + " domain=%s", ctask->authority); + offset += strlen (" domain=") + strlen (ctask->authority); + new_cookie_hdr[offset] = ';'; + offset++; + continue; + } + } + else if (strlen (cookie_domain) == strlen (ctask->leho)) + { + if (0 == strcmp (cookie_domain, ctask->leho)) + { + GNUNET_snprintf (new_cookie_hdr+offset, + sizeof (new_cookie_hdr), + " domain=%s", ctask->host); + offset += strlen (" domain=") + strlen (ctask->host); + new_cookie_hdr[offset] = ';'; + offset++; + continue; + } + } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Cookie domain invalid\n"); + + + } + memcpy (new_cookie_hdr+offset, tok, strlen (tok)); + offset += strlen (tok); + new_cookie_hdr[offset] = ';'; + offset++; + } + + GNUNET_free (ndup); + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got Set-Cookie HTTP header %s\n", new_cookie_hdr); + + if (GNUNET_NO == MHD_add_response_header (ctask->response, + MHD_HTTP_HEADER_SET_COOKIE, + new_cookie_hdr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "MHD: Error adding set-cookie header field %s\n", + hdr_generic+cookie_hdr_len+1); + } + return bytes; + } + + ndup = GNUNET_strdup (hdr_generic); + hdr_type = strtok (ndup, ":"); + + if (NULL == hdr_type) + { + GNUNET_free (ndup); + return bytes; + } + + hdr_val = strtok (NULL, ""); + + if (NULL == hdr_val) + { + GNUNET_free (ndup); + return bytes; + } + + hdr_val++; + + if (0 == strcasecmp (MHD_HTTP_HEADER_LOCATION, hdr_type)) + { + if (ctask->mhd->is_ssl) + { + sprintf (leho_host, "https://%s", ctask->leho); + sprintf (real_host, "https://%s", ctask->host); + } + else + { + sprintf (leho_host, "http://%s", ctask->leho); + sprintf (real_host, "http://%s", ctask->host); + } + + if (0 == memcmp (leho_host, hdr_val, strlen (leho_host))) + { + sprintf (new_location, "%s%s", real_host, hdr_val+strlen (leho_host)); + hdr_val = new_location; + } + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying to set %s: %s\n", + hdr_type, + hdr_val); + if (GNUNET_NO == MHD_add_response_header (ctask->response, + hdr_type, + hdr_val)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "MHD: Error adding %s header field %s\n", + hdr_type, + hdr_val); + } + GNUNET_free (ndup); + return bytes; +} + + +/** + * schedule mhd + * + * @param hd a http daemon list entry + */ +static void +run_httpd (struct MhdHttpList *hd); + + +/** + * schedule all mhds + * + */ +static void +run_httpds (void); + + +/** + * Task run whenever HTTP server operations are pending. + * + * @param cls unused + * @param tc sched context + */ +static void +do_httpd (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + + +static void +run_mhd_now (struct MhdHttpList *hd) +{ + if (GNUNET_SCHEDULER_NO_TASK != hd->httpd_task) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: killing old task\n"); + GNUNET_SCHEDULER_cancel (hd->httpd_task); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Scheduling MHD now\n"); + hd->httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, hd); +} + + +/** + * Ask cURL for the select sets and schedule download + */ +static void +curl_download_prepare (void); + + +/** + * Callback to free content + * + * @param cls content to free + * @param tc task context + */ +static void +mhd_content_free (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct ProxyCurlTask *ctask = cls; + struct ProxyUploadData *pdata; + + GNUNET_assert (NULL == ctask->pp_match_head); + if (NULL != ctask->headers) + curl_slist_free_all (ctask->headers); + + if (NULL != ctask->headers) + curl_slist_free_all (ctask->resolver); + + if (NULL != ctask->response) + MHD_destroy_response (ctask->response); + + if (NULL != ctask->post_handler) + MHD_destroy_post_processor (ctask->post_handler); + + if (GNUNET_SCHEDULER_NO_TASK != ctask->pp_task) + GNUNET_SCHEDULER_cancel (ctask->pp_task); + + for (pdata = ctask->upload_data_head; NULL != pdata; pdata = ctask->upload_data_head) + { + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free_non_null (pdata->filename); + GNUNET_free_non_null (pdata->content_type); + GNUNET_free_non_null (pdata->key); + GNUNET_free_non_null (pdata->value); + GNUNET_free (pdata); + } + GNUNET_free (ctask); +} + + +/** + * Callback for MHD response + * + * @param cls closure + * @param pos in buffer + * @param buf buffer + * @param max space in buffer + * @return number of bytes written + */ +static ssize_t +mhd_content_cb (void *cls, + uint64_t pos, + char* buf, + size_t max) +{ + struct ProxyCurlTask *ctask = cls; + struct ProxyREMatch *re_match; + ssize_t copied = 0; + size_t bytes_to_copy = ctask->buffer_write_ptr - ctask->buffer_read_ptr; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: content cb for %s. To copy: %u\n", + ctask->url, (unsigned int) bytes_to_copy); + if ((GNUNET_YES == ctask->download_is_finished) && + (GNUNET_NO == ctask->download_error) && + (0 == bytes_to_copy)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "MHD: sending response for %s\n", ctask->url); + ctask->download_in_progress = GNUNET_NO; + run_mhd_now (ctask->mhd); + GNUNET_SCHEDULER_add_now (&mhd_content_free, ctask); + total_mhd_connections--; + return MHD_CONTENT_READER_END_OF_STREAM; + } + + if ((GNUNET_YES == ctask->download_error) && + (GNUNET_YES == ctask->download_is_finished) && + (0 == bytes_to_copy)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "MHD: sending error response\n"); + ctask->download_in_progress = GNUNET_NO; + run_mhd_now (ctask->mhd); + GNUNET_SCHEDULER_add_now (&mhd_content_free, ctask); + total_mhd_connections--; + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + if ( ctask->buf_status == BUF_WAIT_FOR_CURL ) + return 0; + + copied = 0; + for (re_match = ctask->pp_match_head; NULL != re_match; re_match = ctask->pp_match_head) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Processing PP %s\n", + re_match->hostname); + bytes_to_copy = re_match->start - ctask->buffer_read_ptr; + if (bytes_to_copy+copied > max) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: buffer in response too small for %u. Using available space (%d). (%s)\n", + (unsigned int) bytes_to_copy, + max, + ctask->url); + memcpy (buf+copied, ctask->buffer_read_ptr, max-copied); + ctask->buffer_read_ptr += max-copied; + copied = max; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: copied %d bytes\n", (int) copied); + return copied; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: copying %u bytes to mhd response at offset %d\n", + (unsigned int) bytes_to_copy, ctask->buffer_read_ptr); + memcpy (buf+copied, ctask->buffer_read_ptr, bytes_to_copy); + copied += bytes_to_copy; + + if (GNUNET_NO == re_match->done) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Waiting for PP of %s\n", re_match->hostname); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: copied %d bytes\n", (int) copied); + ctask->buffer_read_ptr += bytes_to_copy; + return copied; + } + + if (strlen (re_match->result) > (max - copied)) + { + //FIXME partially copy domain here + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: buffer in response too small for %s! (%s)\n", + re_match->result, + ctask->url); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: copied %d bytes\n", (int) copied); + ctask->buffer_read_ptr += bytes_to_copy; + return copied; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Adding PP result %s to buffer\n", + re_match->result); + memcpy (buf + copied, re_match->result, strlen (re_match->result)); + copied += strlen (re_match->result); + ctask->buffer_read_ptr = re_match->end; + GNUNET_CONTAINER_DLL_remove (ctask->pp_match_head, + ctask->pp_match_tail, + re_match); + GNUNET_free (re_match); + } + + bytes_to_copy = ctask->buffer_write_ptr - ctask->buffer_read_ptr; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: copied: %d left: %u, space left in buf: %d\n", + copied, + (unsigned int) bytes_to_copy, (int) (max - copied)); + + if (GNUNET_NO == ctask->download_is_finished) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Purging buffer\n"); + memmove (ctask->buffer, ctask->buffer_read_ptr, bytes_to_copy); + ctask->buffer_read_ptr = ctask->buffer; + ctask->buffer_write_ptr = ctask->buffer + bytes_to_copy; + ctask->buffer[bytes_to_copy] = '\0'; + } + + if (bytes_to_copy + copied > max) + bytes_to_copy = max - copied; + memcpy (buf+copied, ctask->buffer_read_ptr, bytes_to_copy); + ctask->buffer_read_ptr += bytes_to_copy; + copied += bytes_to_copy; + ctask->buf_status = BUF_WAIT_FOR_CURL; + + if (NULL != ctask->curl) + curl_easy_pause (ctask->curl, CURLPAUSE_CONT); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: copied %d bytes\n", (int) copied); + run_mhd_now (ctask->mhd); + return copied; +} + + +/** + * Shorten result callback + * + * @param cls the proxycurltask + * @param short_name the shortened name (NULL on error) + */ +static void +process_shorten (void* cls, const char* short_name) +{ + struct ProxyREMatch *re_match = cls; + char result[sizeof (re_match->result)]; + + if (NULL == short_name) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "PP: Unable to shorten %s\n", + re_match->hostname); + GNUNET_CONTAINER_DLL_remove (re_match->ctask->pp_match_head, + re_match->ctask->pp_match_tail, + re_match); + GNUNET_free (re_match); + return; + } + + if (0 == strcmp (short_name, re_match->ctask->leho)) + strcpy (result, re_match->ctask->host); + else + strcpy (result, short_name); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "PP: Shorten %s -> %s\n", + re_match->hostname, + result); + + if (re_match->is_ssl) + sprintf (re_match->result, "href=\"https://%s", result); + else + sprintf (re_match->result, "href=\"http://%s", result); + + re_match->done = GNUNET_YES; + run_mhd_now (re_match->ctask->mhd); +} + + +/** + * Postprocess data in buffer. From read ptr to write ptr + * + * @param cls the curlproxytask + * @param tc task context + */ +static void +postprocess_buffer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct ProxyCurlTask *ctask = cls; + struct ProxyREMatch *re_match; + char* re_ptr = ctask->buffer_read_ptr; + char re_hostname[255]; + regmatch_t m[RE_N_MATCHES]; + + ctask->pp_task = GNUNET_SCHEDULER_NO_TASK; + + if (GNUNET_YES != ctask->parse_content) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "PP: Not parsing content\n"); + ctask->buf_status = BUF_WAIT_FOR_MHD; + run_mhd_now (ctask->mhd); + return; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "PP: We need to parse the HTML\n"); + + /* 0 means match found */ + while (0 == regexec (&re_dotplus, re_ptr, RE_N_MATCHES, m, 0)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "PP: regex match\n"); + + GNUNET_assert (m[1].rm_so != -1); + + memset (re_hostname, 0, sizeof (re_hostname)); + memcpy (re_hostname, re_ptr+m[1].rm_so, (m[3].rm_eo-m[1].rm_so)); + + + re_match = GNUNET_malloc (sizeof (struct ProxyREMatch)); + re_match->start = re_ptr + m[0].rm_so; + re_match->end = re_ptr + m[3].rm_eo; + re_match->done = GNUNET_NO; + re_match->ctask = ctask; + + if ('s' == *(re_ptr+m[1].rm_so-strlen("://")-1)) //FIXME strcmp + re_match->is_ssl = GNUNET_YES; + else + re_match->is_ssl = GNUNET_NO; + + strcpy (re_match->hostname, re_hostname); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "PP: Got hostname %s\n", re_hostname); + re_ptr += m[3].rm_eo; + + if (GNUNET_YES == is_tld (re_match->hostname, GNUNET_GNS_TLD_PLUS)) + { + re_match->hostname[strlen(re_match->hostname)-1] = '\0'; + strcpy (re_match->hostname+strlen(re_match->hostname), + ctask->authority); + } + + re_match->shorten_task = GNUNET_GNS_shorten_zone (gns_handle, + re_match->hostname, + local_private_zone, + local_shorten_zone, + local_gns_zone, + &process_shorten, + re_match); //FIXME cancel appropriately + + GNUNET_CONTAINER_DLL_insert_tail (ctask->pp_match_head, + ctask->pp_match_tail, + re_match); + } + + ctask->buf_status = BUF_WAIT_FOR_MHD; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "PP: No more matches\n"); + run_mhd_now (ctask->mhd); +} + + +/** + * Handle data from cURL + * + * @param ptr pointer to the data + * @param size number of blocks of data + * @param nmemb blocksize + * @param ctx the curlproxytask + * @return number of bytes handled + */ +static size_t +curl_download_cb (void *ptr, size_t size, size_t nmemb, void* ctx) +{ + const char *cbuf = ptr; + size_t total = size * nmemb; + struct ProxyCurlTask *ctask = ctx; + size_t buf_space = sizeof (ctask->buffer) - + (ctask->buffer_write_ptr-ctask->buffer); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: Got %d. %d free in buffer\n", + total, buf_space); + + if (BUF_WAIT_FOR_CURL != ctask->buf_status) + return CURL_WRITEFUNC_PAUSE; + + if (total > (buf_space - CURL_BUF_PADDING)) + { + if (ctask->buf_status == BUF_WAIT_FOR_CURL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: Buffer full starting postprocessing\n"); + ctask->buf_status = BUF_WAIT_FOR_PP; + ctask->pp_task = GNUNET_SCHEDULER_add_now (&postprocess_buffer, + ctask); + return CURL_WRITEFUNC_PAUSE; + } + + /* we should not get called in that case */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "CURL: called out of context and no space in buffer!\n"); + return CURL_WRITEFUNC_PAUSE; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: Copying %d bytes to buffer (%s)\n", total, ctask->url); + memcpy (ctask->buffer_write_ptr, cbuf, total); + ctask->bytes_in_buffer += total; + ctask->buffer_write_ptr += total; + ctask->buffer_write_ptr[0] = '\0'; + + return total; +} + + +/** + * cURL callback for put data + */ +static size_t +put_read_callback (void *buf, size_t size, size_t nmemb, void *cls) +{ + struct ProxyCurlTask *ctask = cls; + struct ProxyUploadData *pdata = ctask->upload_data_head; + size_t len = size * nmemb; + size_t to_copy; + char* pos; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: put read callback\n"); + + if (NULL == pdata) + return CURL_READFUNC_PAUSE; + + //fin + if (NULL == pdata->value) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: Terminating PUT\n"); + + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free (pdata); + return 0; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: read callback value %s\n", pdata->value); + + to_copy = pdata->bytes_left; + if (to_copy > len) + to_copy = len; + + pos = pdata->value + (pdata->total_bytes - pdata->bytes_left); + memcpy (buf, pos, to_copy); + pdata->bytes_left -= to_copy; + if (pdata->bytes_left <= 0) + { + GNUNET_free (pdata->value); + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free (pdata); + } + return to_copy; +} + + +/** + * cURL callback for post data + */ +static size_t +post_read_callback (void *buf, size_t size, size_t nmemb, void *cls) +{ + struct ProxyCurlTask *ctask = cls; + struct ProxyUploadData *pdata = ctask->upload_data_head; + size_t len = size * nmemb; + size_t to_copy; + char* pos; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: read callback\n"); + + if (NULL == pdata) + return CURL_READFUNC_PAUSE; + + //fin + if (NULL == pdata->value) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: Terminating POST data\n"); + + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free (pdata); + return 0; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: read callback value %s\n", pdata->value); + + to_copy = pdata->bytes_left; + if (to_copy > len) + to_copy = len; + + pos = pdata->value + (pdata->total_bytes - pdata->bytes_left); + memcpy (buf, pos, to_copy); + pdata->bytes_left -= to_copy; + if (pdata->bytes_left <= 0) + { + GNUNET_free (pdata->value); + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free (pdata); + } + return to_copy; +} + + +/** + * Task that is run when we are ready to receive more data + * from curl + * + * @param cls closure + * @param tc task context + */ +static void +curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); + + +/** + * Ask cURL for the select sets and schedule download + */ +static void +curl_download_prepare () +{ + CURLMcode mret; + fd_set rs; + fd_set ws; + fd_set es; + int max; + struct GNUNET_NETWORK_FDSet *grs; + struct GNUNET_NETWORK_FDSet *gws; + long to; + struct GNUNET_TIME_Relative rtime; + + max = -1; + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + if (CURLM_OK != (mret = curl_multi_fdset (curl_multi, &rs, &ws, &es, &max))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "%s failed at %s:%d: `%s'\n", + "curl_multi_fdset", __FILE__, __LINE__, + curl_multi_strerror (mret)); + //TODO cleanup here? + return; + } + to = -1; + GNUNET_break (CURLM_OK == curl_multi_timeout (curl_multi, &to)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "cURL multi fds: max=%d timeout=%lld\n", max, (long long) to); + if (-1 == to) + rtime = GNUNET_TIME_UNIT_FOREVER_REL; + else + rtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, to); + grs = GNUNET_NETWORK_fdset_create (); + gws = GNUNET_NETWORK_fdset_create (); + GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); + GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); + if (curl_download_task != GNUNET_SCHEDULER_NO_TASK) + GNUNET_SCHEDULER_cancel (curl_download_task); + if (-1 != max) + { + curl_download_task = + GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, + rtime, + grs, gws, + &curl_task_download, curl_multi); + } + else if (NULL != ctasks_head) + { + /* as specified in curl docs */ + curl_download_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, + &curl_task_download, + curl_multi); + } + GNUNET_NETWORK_fdset_destroy (gws); + GNUNET_NETWORK_fdset_destroy (grs); +} + + +/** + * Task that is run when we are ready to receive more data + * from curl + * + * @param cls closure + * @param tc task context + */ +static void +curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + int running; + int msgnum; + struct CURLMsg *msg; + CURLMcode mret; + struct ProxyCurlTask *ctask; + int num_ctasks; + long resp_code; + struct ProxyCurlTask *clean_head = NULL; + struct ProxyCurlTask *clean_tail = NULL; + + curl_download_task = GNUNET_SCHEDULER_NO_TASK; + + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Shutdown requested while trying to download\n"); + //TODO cleanup + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Ready to dl\n"); + + do + { + running = 0; + num_ctasks = 0; + + mret = curl_multi_perform (curl_multi, &running); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Running curl tasks: %d\n", running); + + for (ctask = ctasks_head; NULL != ctask; ctask = ctask->next) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CTask: %s\n", ctask->url); + num_ctasks++; + } + + if (num_ctasks != running) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "%d ctasks, %d curl running\n", num_ctasks, running); + } + + do + { + + msg = curl_multi_info_read (curl_multi, &msgnum); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Messages left: %d\n", msgnum); + + if (msg == NULL) + break; + switch (msg->msg) + { + case CURLMSG_DONE: + if ((msg->data.result != CURLE_OK) && + (msg->data.result != CURLE_GOT_NOTHING)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Download curl failed"); + + for (ctask = ctasks_head; NULL != ctask; ctask = ctask->next) + { + if (NULL == ctask->curl) + continue; + + if (memcmp (msg->easy_handle, ctask->curl, sizeof (CURL)) != 0) + continue; + + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "CURL: Download failed for task %s: %s.\n", + ctask->url, + curl_easy_strerror (msg->data.result)); + ctask->download_is_finished = GNUNET_YES; + ctask->download_error = GNUNET_YES; + if (CURLE_OK == curl_easy_getinfo (ctask->curl, + CURLINFO_RESPONSE_CODE, + &resp_code)) + ctask->curl_response_code = resp_code; + ctask->ready_to_queue = MHD_YES; + ctask->buf_status = BUF_WAIT_FOR_MHD; + run_mhd_now (ctask->mhd); + + GNUNET_CONTAINER_DLL_remove (ctasks_head, ctasks_tail, + ctask); + GNUNET_CONTAINER_DLL_insert (clean_head, clean_tail, ctask); + break; + } + GNUNET_assert (ctask != NULL); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: download completed.\n"); + + for (ctask = ctasks_head; NULL != ctask; ctask = ctask->next) + { + if (NULL == ctask->curl) + continue; + + if (0 != memcmp (msg->easy_handle, ctask->curl, sizeof (CURL))) + continue; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: completed task %s found.\n", ctask->url); + if (CURLE_OK == curl_easy_getinfo (ctask->curl, + CURLINFO_RESPONSE_CODE, + &resp_code)) + ctask->curl_response_code = resp_code; + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: Completed ctask!\n"); + if (GNUNET_SCHEDULER_NO_TASK == ctask->pp_task) + { + ctask->buf_status = BUF_WAIT_FOR_PP; + ctask->pp_task = GNUNET_SCHEDULER_add_now (&postprocess_buffer, + ctask); + } + + ctask->ready_to_queue = MHD_YES; + ctask->download_is_finished = GNUNET_YES; + + /* We MUST not modify the multi handle else we loose messages */ + GNUNET_CONTAINER_DLL_remove (ctasks_head, ctasks_tail, + ctask); + GNUNET_CONTAINER_DLL_insert (clean_head, clean_tail, ctask); + + break; + } + GNUNET_assert (ctask != NULL); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: %s\n", curl_easy_strerror(msg->data.result)); + break; + default: + GNUNET_assert (0); + break; + } + } while (msgnum > 0); + + for (ctask=clean_head; NULL != ctask; ctask = ctask->next) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: Removing task %s.\n", ctask->url); + curl_multi_remove_handle (curl_multi, ctask->curl); + curl_easy_cleanup (ctask->curl); + ctask->curl = NULL; + } + + num_ctasks=0; + for (ctask=ctasks_head; NULL != ctask; ctask = ctask->next) + num_ctasks++; + + if (num_ctasks != running) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: %d tasks, %d running\n", num_ctasks, running); + } + + GNUNET_assert ( num_ctasks == running ); + + } while (mret == CURLM_CALL_MULTI_PERFORM); + + if (mret != CURLM_OK) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "CURL: %s failed at %s:%d: `%s'\n", + "curl_multi_perform", __FILE__, __LINE__, + curl_multi_strerror (mret)); + } + curl_download_prepare(); +} + + +/** + * Process LEHO lookup + * + * @param cls the ctask + * @param rd_count number of records returned + * @param rd record data + */ +static void +process_leho_lookup (void *cls, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct ProxyCurlTask *ctask = cls; + char hosthdr[262]; //256 + "Host: " + int i; + CURLcode ret; + CURLMcode mret; + struct hostent *phost; + char *ssl_ip; + char resolvename[512]; + char curlurl[512]; + + strcpy (ctask->leho, ""); + + if (rd_count == 0) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No LEHO present!\n"); + + for (i=0; i<rd_count; i++) + { + if (rd[i].record_type != GNUNET_GNS_RECORD_LEHO) + continue; + + memcpy (ctask->leho, rd[i].data, rd[i].data_size); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Found LEHO %s for %s\n", ctask->leho, ctask->url); + } + + if (0 != strcmp (ctask->leho, "")) + { + sprintf (hosthdr, "%s%s:%d", "Host: ", ctask->leho, ctask->port); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "New HTTP header value: %s\n", hosthdr); + ctask->headers = curl_slist_append (ctask->headers, hosthdr); + GNUNET_assert (NULL != ctask->headers); + ret = curl_easy_setopt (ctask->curl, CURLOPT_HTTPHEADER, ctask->headers); + if (CURLE_OK != ret) + { + GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s failed at %s:%d: `%s'\n", + "curl_easy_setopt", __FILE__, __LINE__, curl_easy_strerror(ret)); + } + + } + + if (ctask->mhd->is_ssl) + { + phost = (struct hostent*)gethostbyname (ctask->host); + + if (phost!=NULL) + { + ssl_ip = inet_ntoa(*((struct in_addr*)(phost->h_addr))); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "SSL target server: %s\n", ssl_ip); + sprintf (resolvename, "%s:%d:%s", ctask->leho, HTTPS_PORT, ssl_ip); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Curl resolve: %s\n", resolvename); + ctask->resolver = curl_slist_append ( ctask->resolver, resolvename); + curl_easy_setopt (ctask->curl, CURLOPT_RESOLVE, ctask->resolver); + sprintf (curlurl, "https://%s:%d%s", ctask->leho, ctask->port, ctask->url); + curl_easy_setopt (ctask->curl, CURLOPT_URL, curlurl); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "gethostbyname failed for %s!\n", ctask->host); + ctask->download_is_finished = GNUNET_YES; + ctask->download_error = GNUNET_YES; + return; + } + } + + if (CURLM_OK != (mret=curl_multi_add_handle (curl_multi, ctask->curl))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "%s failed at %s:%d: `%s'\n", + "curl_multi_add_handle", __FILE__, __LINE__, + curl_multi_strerror (mret)); + ctask->download_is_finished = GNUNET_YES; + ctask->download_error = GNUNET_YES; + return; + } + GNUNET_CONTAINER_DLL_insert (ctasks_head, ctasks_tail, ctask); + + curl_download_prepare (); + +} + + +/** + * Initialize download and trigger curl + * + * @param cls the proxycurltask + * @param auth_name the name of the authority (site of origin) of ctask->host + * + */ +static void +process_get_authority (void *cls, + const char* auth_name) +{ + struct ProxyCurlTask *ctask = cls; + + if (NULL == auth_name) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Get authority failed!\n"); + strcpy (ctask->authority, ""); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Get authority yielded %s\n", auth_name); + strcpy (ctask->authority, auth_name); + } + + GNUNET_GNS_lookup_zone (gns_handle, + ctask->host, + local_gns_zone, + GNUNET_GNS_RECORD_LEHO, + GNUNET_YES, //Only cached for performance + shorten_zonekey, + &process_leho_lookup, + ctask); +} + + +static void* +mhd_log_callback (void* cls, const char* url) +{ + struct ProxyCurlTask *ctask; + + ctask = GNUNET_malloc (sizeof (struct ProxyCurlTask)); + strcpy (ctask->url, url); + return ctask; +} + + /** * Main MHD callback for handling requests. * * @param cls unused - * @param connection MHD connection handle - * @param method the HTTP method used ("GET", "PUT", etc.) - * @param version the HTTP version string (i.e. "HTTP/1.1") + * @param con MHD connection handle + * @param url the url in the request + * @param meth the HTTP method used ("GET", "PUT", etc.) + * @param ver the HTTP version string (i.e. "HTTP/1.1") * @param upload_data the data being uploaded (excluding HEADERS, * for a POST that fits into memory and that is encoded * with a supported encoding, the POST data will NOT be @@ -114,7 +1886,7 @@ con_val_iter (void *cls, * @param upload_data_size set initially to the size of the * upload_data provided; the method must update this * value to the number of bytes NOT processed; - * @param ptr pointer to location where we store the 'struct Request' + * @param con_cls pointer to location where we store the 'struct Request' * @return MHD_YES if the connection was handled successfully, * MHD_NO if the socket must be closed due to a serious * error while handling the request @@ -129,58 +1901,277 @@ create_response (void *cls, size_t *upload_data_size, void **con_cls) { - static int dummy; - const char* page = "<html><head><title>gnoxy</title>"\ - "</head><body>gnoxy demo</body></html>"; - struct MHD_Response *response; - char host[265]; - int ret; + struct MhdHttpList* hd = cls; + const char* page = "<html><head><title>gnunet-gns-proxy</title>" + "</head><body>cURL fail</body></html>"; - if (0 != strcmp (meth, "GET")) + char curlurl[MAX_HTTP_URI_LENGTH]; // buffer overflow! + int ret = MHD_YES; + int i; + struct ProxyCurlTask *ctask = *con_cls; + struct ProxyUploadData *fin_post; + struct curl_forms forms[5]; + struct ProxyUploadData *upload_data_iter; + + //FIXME handle + if ((0 != strcasecmp (meth, MHD_HTTP_METHOD_GET)) && + (0 != strcasecmp (meth, MHD_HTTP_METHOD_PUT)) && + (0 != strcasecmp (meth, MHD_HTTP_METHOD_POST)) && + (0 != strcasecmp (meth, MHD_HTTP_METHOD_HEAD))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "MHD: %s NOT IMPLEMENTED!\n", meth); return MHD_NO; - if (&dummy != *con_cls) + } + + + if (GNUNET_NO == ctask->accepted) { - *con_cls = &dummy; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got %s request for %s\n", meth, url); + ctask->mhd = hd; + ctask->curl = curl_easy_init(); + ctask->curl_running = GNUNET_NO; + if (NULL == ctask->curl) + { + ctask->response = MHD_create_response_from_buffer (strlen (page), + (void*)page, + MHD_RESPMEM_PERSISTENT); + ret = MHD_queue_response (con, + MHD_HTTP_OK, + ctask->response); + MHD_destroy_response (ctask->response); + GNUNET_free (ctask); + return ret; + } + + if (ctask->mhd->is_ssl) + ctask->port = HTTPS_PORT; + else + ctask->port = HTTP_PORT; + + MHD_get_connection_values (con, + MHD_HEADER_KIND, + &con_val_iter, ctask); + + curl_easy_setopt (ctask->curl, CURLOPT_HEADERFUNCTION, &curl_check_hdr); + curl_easy_setopt (ctask->curl, CURLOPT_HEADERDATA, ctask); + curl_easy_setopt (ctask->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb); + curl_easy_setopt (ctask->curl, CURLOPT_WRITEDATA, ctask); + curl_easy_setopt (ctask->curl, CURLOPT_FOLLOWLOCATION, 0); + curl_easy_setopt (ctask->curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + + if (GNUNET_NO == ctask->mhd->is_ssl) + { + sprintf (curlurl, "http://%s:%d%s", ctask->host, ctask->port, ctask->url); + curl_easy_setopt (ctask->curl, CURLOPT_URL, curlurl); + } + + + curl_easy_setopt (ctask->curl, CURLOPT_FAILONERROR, 1); + curl_easy_setopt (ctask->curl, CURLOPT_CONNECTTIMEOUT, 600L); + curl_easy_setopt (ctask->curl, CURLOPT_TIMEOUT, 600L); + + /* Add GNS header */ + ctask->headers = curl_slist_append (ctask->headers, + "GNS: YES"); + ctask->accepted = GNUNET_YES; + ctask->download_in_progress = GNUNET_YES; + ctask->buf_status = BUF_WAIT_FOR_CURL; + ctask->connection = con; + ctask->curl_response_code = MHD_HTTP_OK; + ctask->buffer_read_ptr = ctask->buffer; + ctask->buffer_write_ptr = ctask->buffer; + ctask->pp_task = GNUNET_SCHEDULER_NO_TASK; + + + if (0 == strcasecmp (meth, MHD_HTTP_METHOD_PUT)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Setting up PUT\n"); + + curl_easy_setopt (ctask->curl, CURLOPT_UPLOAD, 1); + curl_easy_setopt (ctask->curl, CURLOPT_READDATA, ctask); + curl_easy_setopt (ctask->curl, CURLOPT_READFUNCTION, &put_read_callback); + ctask->headers = curl_slist_append (ctask->headers, + "Transfer-Encoding: chunked"); + } + + if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST)) + { + //FIXME handle multipart + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Setting up POST processor\n"); + ctask->post_handler = MHD_create_post_processor (con, + POSTBUFFERSIZE, + &con_post_data_iter, + ctask); + ctask->headers = curl_slist_append (ctask->headers, + "Transfer-Encoding: chunked"); + return MHD_YES; + } + + if (0 == strcasecmp (meth, MHD_HTTP_METHOD_HEAD)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Setting NOBODY\n"); + curl_easy_setopt (ctask->curl, CURLOPT_NOBODY, 1); + } + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Adding new curl task for %s\n", ctask->host); + + GNUNET_GNS_get_authority (gns_handle, + ctask->host, + &process_get_authority, + ctask); + ctask->ready_to_queue = GNUNET_NO; + ctask->fin = GNUNET_NO; + ctask->curl_running = GNUNET_YES; return MHD_YES; } - if (0 != *upload_data_size) - return MHD_NO; + ctask = (struct ProxyCurlTask *) *con_cls; + if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST)) + { + if (0 != *upload_data_size) + { + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Invoking POST processor\n"); + MHD_post_process (ctask->post_handler, + upload_data, *upload_data_size); + *upload_data_size = 0; + if ((GNUNET_NO == ctask->is_httppost) && + (GNUNET_NO == ctask->curl_running)) + { + curl_easy_setopt (ctask->curl, CURLOPT_POST, 1); + curl_easy_setopt (ctask->curl, CURLOPT_READFUNCTION, + &post_read_callback); + curl_easy_setopt (ctask->curl, CURLOPT_READDATA, ctask); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Adding new curl task for %s\n", ctask->host); + + GNUNET_GNS_get_authority (gns_handle, + ctask->host, + &process_get_authority, + ctask); + ctask->ready_to_queue = GNUNET_NO; + ctask->fin = GNUNET_NO; + ctask->curl_running = GNUNET_YES; + } + return MHD_YES; + } + else if (GNUNET_NO == ctask->post_done) + { + if (GNUNET_YES == ctask->is_httppost) + { + for (upload_data_iter = ctask->upload_data_head; + NULL != upload_data_iter; + upload_data_iter = upload_data_iter->next) + { + i = 0; + if (NULL != upload_data_iter->filename) + { + forms[i].option = CURLFORM_FILENAME; + forms[i].value = upload_data_iter->filename; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding filename %s\n", + forms[i].value); + i++; + } + if (NULL != upload_data_iter->content_type) + { + forms[i].option = CURLFORM_CONTENTTYPE; + forms[i].value = upload_data_iter->content_type; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding content type %s\n", + forms[i].value); + i++; + } + forms[i].option = CURLFORM_PTRCONTENTS; + forms[i].value = upload_data_iter->value; + forms[i+1].option = CURLFORM_END; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding formdata for %s (len=%lld)\n", + upload_data_iter->key, + upload_data_iter->total_bytes); + + curl_formadd(&ctask->httppost, &ctask->httppost_last, + CURLFORM_COPYNAME, upload_data_iter->key, + CURLFORM_CONTENTSLENGTH, upload_data_iter->total_bytes, + CURLFORM_ARRAY, forms, + CURLFORM_END); + } + curl_easy_setopt (ctask->curl, CURLOPT_HTTPPOST, + ctask->httppost); - *con_cls = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Adding new curl task for %s\n", ctask->host); + + GNUNET_GNS_get_authority (gns_handle, + ctask->host, + &process_get_authority, + ctask); + ctask->ready_to_queue = GNUNET_YES; + ctask->fin = GNUNET_NO; + ctask->curl_running = GNUNET_YES; + ctask->post_done = GNUNET_YES; + return MHD_YES; + } + + fin_post = GNUNET_malloc (sizeof (struct ProxyUploadData)); + GNUNET_CONTAINER_DLL_insert_tail (ctask->upload_data_head, + ctask->upload_data_tail, + fin_post); + ctask->post_done = GNUNET_YES; + return MHD_YES; + } + } + + if (GNUNET_YES != ctask->ready_to_queue) + return MHD_YES; /* wait longer */ + + if (GNUNET_YES == ctask->fin) + return MHD_YES; + ctask->fin = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "url %s\n", url); - - MHD_get_connection_values (con, - MHD_HEADER_KIND, - &con_val_iter, host); - - response = MHD_create_response_from_buffer (strlen (page), - (void*)page, - MHD_RESPMEM_PERSISTENT); - ret = MHD_queue_response (con, - MHD_HTTP_OK, - response); - MHD_destroy_response (response); + "MHD: Queueing response for %s\n", ctask->url); + ret = MHD_queue_response (con, ctask->curl_response_code, ctask->response); + run_mhd_now (ctask->mhd); return ret; } + /** - * Task run whenever HTTP server operations are pending. - * - * @param cls unused - * @param tc sched context + * run all httpd */ static void -do_httpd (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc); +run_httpds () +{ + struct MhdHttpList *hd; + + for (hd=mhd_httpd_head; NULL != hd; hd = hd->next) + run_httpd (hd); + +} + + +#define UNSIGNED_MHD_LONG_LONG unsigned MHD_LONG_LONG + /** - * Schedule MHD + * schedule mhd + * + * @param hd the daemon to run */ static void -run_httpd () +run_httpd (struct MhdHttpList *hd) { fd_set rs; fd_set ws; @@ -190,7 +2181,7 @@ run_httpd () struct GNUNET_NETWORK_FDSet *wes; int max; int haveto; - unsigned MHD_LONG_LONG timeout; + UNSIGNED_MHD_LONG_LONG timeout; struct GNUNET_TIME_Relative tv; FD_ZERO (&rs); @@ -200,10 +2191,15 @@ run_httpd () wes = GNUNET_NETWORK_fdset_create (); wws = GNUNET_NETWORK_fdset_create (); max = -1; - GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max)); - haveto = MHD_get_timeout (httpd, &timeout); + GNUNET_assert (MHD_YES == MHD_get_fdset (hd->daemon, &rs, &ws, &es, &max)); + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD fds: max=%d\n", max); + + haveto = MHD_get_timeout (hd->daemon, &timeout); - if (haveto == MHD_YES) + if (MHD_YES == haveto) tv.rel_value = (uint64_t) timeout; else tv = GNUNET_TIME_UNIT_FOREVER_REL; @@ -211,17 +2207,18 @@ run_httpd () GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1); - if (httpd_task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (httpd_task); - httpd_task = + if (GNUNET_SCHEDULER_NO_TASK != hd->httpd_task) + GNUNET_SCHEDULER_cancel (hd->httpd_task); + hd->httpd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, tv, wrs, wws, - &do_httpd, NULL); + &do_httpd, hd); GNUNET_NETWORK_fdset_destroy (wrs); GNUNET_NETWORK_fdset_destroy (wws); GNUNET_NETWORK_fdset_destroy (wes); } + /** * Task run whenever HTTP server operations are pending. * @@ -232,11 +2229,16 @@ static void do_httpd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - httpd_task = GNUNET_SCHEDULER_NO_TASK; - MHD_run (httpd); - run_httpd (); + struct MhdHttpList *hd = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Main loop\n"); + hd->httpd_task = GNUNET_SCHEDULER_NO_TASK; + MHD_run (hd->daemon); + run_httpd (hd); } + /** * Read data from socket * @@ -246,6 +2248,7 @@ do_httpd (void *cls, static void do_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); + /** * Read from remote end * @@ -255,6 +2258,7 @@ do_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void do_read_remote (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc); + /** * Write data to remote socket * @@ -271,8 +2275,8 @@ do_write_remote (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if ((NULL != tc->read_ready) && (GNUNET_NETWORK_fdset_isset (tc->write_ready, s5r->remote_sock)) && - (len = GNUNET_NETWORK_socket_send (s5r->remote_sock, s5r->rbuf, - s5r->rbuf_len))) + ((len = GNUNET_NETWORK_socket_send (s5r->remote_sock, s5r->rbuf, + s5r->rbuf_len)>0))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully sent %d bytes to remote socket\n", @@ -281,12 +2285,11 @@ do_write_remote (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) else { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write remote"); - //Really!?!?!? - if (s5r->rtask != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != s5r->rtask) GNUNET_SCHEDULER_cancel (s5r->rtask); - if (s5r->wtask != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != s5r->wtask) GNUNET_SCHEDULER_cancel (s5r->wtask); - if (s5r->fwdrtask != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != s5r->fwdrtask) GNUNET_SCHEDULER_cancel (s5r->fwdrtask); GNUNET_NETWORK_socket_close (s5r->remote_sock); GNUNET_NETWORK_socket_close (s5r->sock); @@ -302,6 +2305,29 @@ do_write_remote (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** + * Clean up s5r handles + * + * @param s5r the handle to destroy + */ +static void +cleanup_s5r (struct Socks5Request *s5r) +{ + if (GNUNET_SCHEDULER_NO_TASK != s5r->rtask) + GNUNET_SCHEDULER_cancel (s5r->rtask); + if (GNUNET_SCHEDULER_NO_TASK != s5r->fwdwtask) + GNUNET_SCHEDULER_cancel (s5r->fwdwtask); + if (GNUNET_SCHEDULER_NO_TASK != s5r->fwdrtask) + GNUNET_SCHEDULER_cancel (s5r->fwdrtask); + if (NULL != s5r->remote_sock) + GNUNET_NETWORK_socket_close (s5r->remote_sock); + if ((NULL != s5r->sock) && (s5r->cleanup_sock == GNUNET_YES)) + GNUNET_NETWORK_socket_close (s5r->sock); + + GNUNET_free(s5r); +} + + +/** * Write data to socket * * @param cls the closure @@ -317,27 +2343,25 @@ do_write (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if ((NULL != tc->read_ready) && (GNUNET_NETWORK_fdset_isset (tc->write_ready, s5r->sock)) && - (len = GNUNET_NETWORK_socket_send (s5r->sock, s5r->wbuf, - s5r->wbuf_len))) + ((len = GNUNET_NETWORK_socket_send (s5r->sock, s5r->wbuf, + s5r->wbuf_len)>0))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully sent %d bytes to socket\n", len); } else - { - + { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write"); - //Really!?!?!? - if (s5r->rtask != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (s5r->rtask); - if (s5r->fwdwtask != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (s5r->fwdwtask); - if (s5r->fwdrtask != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (s5r->fwdrtask); - GNUNET_NETWORK_socket_close (s5r->remote_sock); - GNUNET_NETWORK_socket_close (s5r->sock); - GNUNET_free(s5r); + s5r->cleanup = GNUNET_YES; + s5r->cleanup_sock = GNUNET_YES; + cleanup_s5r (s5r); + return; + } + + if (GNUNET_YES == s5r->cleanup) + { + cleanup_s5r (s5r); return; } @@ -349,6 +2373,7 @@ do_write (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) &do_read_remote, s5r); } + /** * Read from remote end * @@ -361,8 +2386,6 @@ do_read_remote (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct Socks5Request *s5r = cls; s5r->fwdrtask = GNUNET_SCHEDULER_NO_TASK; - - if ((NULL != tc->write_ready) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, s5r->remote_sock)) && (s5r->wbuf_len = GNUNET_NETWORK_socket_recv (s5r->remote_sock, s5r->wbuf, @@ -374,7 +2397,7 @@ do_read_remote (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } else { - if (s5r->wbuf_len == 0) + if (0 == s5r->wbuf_len) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "0 bytes received from remote... graceful shutdown!\n"); if (s5r->fwdwtask != GNUNET_SCHEDULER_NO_TASK) @@ -392,25 +2415,312 @@ do_read_remote (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, - &do_write, s5r); - + &do_write, s5r); } +/** + * Adds a socket to MHD + * + * @param h the handle to the socket to add + * @param daemon the daemon to add the fd to + * @return whatever MHD_add_connection returns + */ static int -add_handle_to_mhd (struct GNUNET_NETWORK_Handle *h) +add_handle_to_mhd (struct GNUNET_NETWORK_Handle *h, struct MHD_Daemon *daemon) { int fd; struct sockaddr *addr; socklen_t len; - fd = GNUNET_NETWORK_get_fd (h); + fd = dup (GNUNET_NETWORK_get_fd (h)); addr = GNUNET_NETWORK_get_addr (h); len = GNUNET_NETWORK_get_addrlen (h); - return MHD_add_connection (httpd, fd, addr, len); + return MHD_add_connection (daemon, fd, addr, len); +} + + +/** + * Read file in filename + * + * @param filename file to read + * @param size pointer where filesize is stored + * @return NULL on error + */ +static void* +load_file (const char* filename, + unsigned int* size) +{ + void *buffer; + uint64_t fsize; + + if (GNUNET_OK != + GNUNET_DISK_file_size (filename, &fsize, + GNUNET_YES, GNUNET_YES)) + return NULL; + if (fsize > MAX_PEM_SIZE) + return NULL; + *size = (unsigned int) fsize; + buffer = GNUNET_malloc (*size); + if (fsize != GNUNET_DISK_fn_read (filename, buffer, (size_t) fsize)) + { + GNUNET_free (buffer); + return NULL; + } + return buffer; } + +/** + * Load PEM key from file + * + * @param key where to store the data + * @param keyfile path to the PEM file + * @return GNUNET_OK on success + */ +static int +load_key_from_file (gnutls_x509_privkey_t key, const char* keyfile) +{ + gnutls_datum_t key_data; + int ret; + + key_data.data = load_file (keyfile, &key_data.size); + ret = gnutls_x509_privkey_import (key, &key_data, + GNUTLS_X509_FMT_PEM); + if (GNUTLS_E_SUCCESS != ret) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Unable to import private key from file `%s'\n"), + keyfile); + GNUNET_break (0); + } + GNUNET_free (key_data.data); + return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK; +} + + +/** + * Load cert from file + * + * @param crt struct to store data in + * @param certfile path to pem file + * @return GNUNET_OK on success + */ +static int +load_cert_from_file (gnutls_x509_crt_t crt, char* certfile) +{ + gnutls_datum_t cert_data; + int ret; + + cert_data.data = load_file (certfile, &cert_data.size); + ret = gnutls_x509_crt_import (crt, &cert_data, + GNUTLS_X509_FMT_PEM); + if (GNUTLS_E_SUCCESS != ret) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Unable to import certificate %s\n"), certfile); + GNUNET_break (0); + } + GNUNET_free (cert_data.data); + return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK; +} + + +/** + * Generate new certificate for specific name + * + * @param name the subject name to generate a cert for + * @return a struct holding the PEM data + */ +static struct ProxyGNSCertificate * +generate_gns_certificate (const char *name) +{ + int ret; + unsigned int serial; + size_t key_buf_size; + size_t cert_buf_size; + gnutls_x509_crt_t request; + time_t etime; + struct tm *tm_data; + + ret = gnutls_x509_crt_init (&request); + + if (GNUTLS_E_SUCCESS != ret) + { + GNUNET_break (0); + } + + GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_set_key (request, proxy_ca.key)); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Generating cert\n"); + + struct ProxyGNSCertificate *pgc = + GNUNET_malloc (sizeof (struct ProxyGNSCertificate)); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding DNs\n"); + + gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_COUNTRY_NAME, + 0, "DE", 2); + gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_ORGANIZATION_NAME, + 0, "GADS", 4); + gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_COMMON_NAME, + 0, name, strlen (name)); + GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_set_version (request, 3)); + + ret = gnutls_rnd (GNUTLS_RND_NONCE, &serial, sizeof (serial)); + + etime = time (NULL); + tm_data = localtime (&etime); + + + ret = gnutls_x509_crt_set_serial (request, + &serial, + sizeof (serial)); + + ret = gnutls_x509_crt_set_activation_time (request, + etime); + tm_data->tm_year++; + etime = mktime (tm_data); + + if (-1 == etime) + { + GNUNET_break (0); + } + + ret = gnutls_x509_crt_set_expiration_time (request, + etime); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Signing...\n"); + + ret = gnutls_x509_crt_sign (request, proxy_ca.cert, proxy_ca.key); + + key_buf_size = sizeof (pgc->key); + cert_buf_size = sizeof (pgc->cert); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Exporting certificate...\n"); + + gnutls_x509_crt_export (request, GNUTLS_X509_FMT_PEM, + pgc->cert, &cert_buf_size); + + gnutls_x509_privkey_export (proxy_ca.key, GNUTLS_X509_FMT_PEM, + pgc->key, &key_buf_size); + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); + gnutls_x509_crt_deinit (request); + + return pgc; + +} + + +/** + * Accept policy for mhdaemons + * + * @param cls NULL + * @param addr the sockaddr + * @param addrlen the sockaddr length + * @return MHD_NO if sockaddr is wrong or number of connections is too high + */ +static int +accept_cb (void* cls, const struct sockaddr *addr, socklen_t addrlen) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "In MHD accept policy cb\n"); + + if (addr != NULL) + { + if (addr->sa_family == AF_UNIX) + return MHD_NO; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Connection accepted\n"); + + return MHD_YES; +} + + +/** + * Adds a socket to an SSL MHD instance + * It is important the the domain name is + * correct. In most cases we need to start a new daemon + * + * @param h the handle to add to a daemon + * @param domain the domain the ssl daemon has to serve + * @return MHD_YES on success + */ +static int +add_handle_to_ssl_mhd (struct GNUNET_NETWORK_Handle *h, const char* domain) +{ + struct MhdHttpList *hd; + struct ProxyGNSCertificate *pgc; + struct NetworkHandleList *nh; + + for (hd = mhd_httpd_head; NULL != hd; hd = hd->next) + if (0 == strcmp (hd->domain, domain)) + break; + + if (NULL == hd) + { + pgc = generate_gns_certificate (domain); + + hd = GNUNET_malloc (sizeof (struct MhdHttpList)); + hd->is_ssl = GNUNET_YES; + strcpy (hd->domain, domain); + hd->proxy_cert = pgc; + + /* Start new MHD */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No previous SSL instance found... starting new one for %s\n", + domain); +#if HAVE_MHD_NO_LISTEN_SOCKET + hd->daemon = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL | MHD_USE_NO_LISTEN_SOCKET, + 0, + &accept_cb, NULL, + &create_response, hd, + MHD_OPTION_CONNECTION_LIMIT, + MHD_MAX_CONNECTIONS, + MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, + MHD_OPTION_NOTIFY_COMPLETED, NULL, NULL, + MHD_OPTION_HTTPS_MEM_KEY, pgc->key, + MHD_OPTION_HTTPS_MEM_CERT, pgc->cert, + MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, + NULL, + MHD_OPTION_END); +#else + hd->daemon = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL, + 4444 /* dummy port */, + &accept_cb, NULL, + &create_response, hd, + MHD_OPTION_LISTEN_SOCKET, GNUNET_NETWORK_get_fd (mhd_unix_socket), + MHD_OPTION_CONNECTION_LIMIT, + MHD_MAX_CONNECTIONS, + MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, + MHD_OPTION_NOTIFY_COMPLETED, NULL, NULL, + MHD_OPTION_HTTPS_MEM_KEY, pgc->key, + MHD_OPTION_HTTPS_MEM_CERT, pgc->cert, + MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, + NULL, + MHD_OPTION_END); +#endif + GNUNET_assert (hd->daemon != NULL); + hd->httpd_task = GNUNET_SCHEDULER_NO_TASK; + + GNUNET_CONTAINER_DLL_insert (mhd_httpd_head, mhd_httpd_tail, hd); + } + + nh = GNUNET_malloc (sizeof (struct NetworkHandleList)); + nh->h = h; + + GNUNET_CONTAINER_DLL_insert (hd->socket_handles_head, + hd->socket_handles_tail, + nh); + + return add_handle_to_mhd (h, hd->daemon); +} + + /** * Read data from incoming connection * @@ -425,7 +2735,7 @@ do_read (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct socks5_server_hello *s_hello; struct socks5_client_request *c_req; struct socks5_server_response *s_resp; - + int ret; char domain[256]; uint8_t dom_len; uint16_t req_port; @@ -433,6 +2743,7 @@ do_read (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) uint32_t remote_ip; struct sockaddr_in remote_addr; struct in_addr *r_sin_addr; + struct NetworkHandleList *nh; s5r->rtask = GNUNET_SCHEDULER_NO_TASK; @@ -518,39 +2829,56 @@ do_read (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requested connection is gnunet tld\n", domain); + + ret = MHD_NO; + if (ntohs(req_port) == HTTPS_PORT) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Requested connection is HTTPS\n"); + ret = add_handle_to_ssl_mhd ( s5r->sock, domain ); + } + else if (NULL != httpd) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Requested connection is HTTP\n"); + nh = GNUNET_malloc (sizeof (struct NetworkHandleList)); + nh->h = s5r->sock; + + GNUNET_CONTAINER_DLL_insert (mhd_httpd_head->socket_handles_head, + mhd_httpd_head->socket_handles_tail, + nh); + + ret = add_handle_to_mhd ( s5r->sock, httpd ); + } - if (NULL == httpd) + if (ret != MHD_YES) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start HTTP server\n")); s_resp->version = 0x05; s_resp->reply = 0x01; + s5r->cleanup = GNUNET_YES; + s5r->cleanup_sock = GNUNET_YES; s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, &do_write, s5r); - //ERROR! - //TODO! close socket after the write! schedule task - //GNUNET_NETWORK_socket_close (s5r->sock); - //GNUNET_free(s5r); return; } - - if (MHD_YES == add_handle_to_mhd ( s5r->sock )) - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sucessfully added client to MHD!\n"); + + /* Signal success */ s_resp->version = 0x05; s_resp->reply = 0x00; s_resp->reserved = 0x00; s_resp->addr_type = 0x01; - + + s5r->cleanup = GNUNET_YES; + s5r->cleanup_sock = GNUNET_NO; s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, &do_write, s5r); - run_httpd (); - //GNUNET_free ( s5r ); - //FIXME complete socks resp! + run_httpds (); return; } else @@ -562,14 +2890,12 @@ do_read (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) "Resolve %s error!\n", domain ); s_resp->version = 0x05; s_resp->reply = 0x01; + s5r->cleanup = GNUNET_YES; + s5r->cleanup_sock = GNUNET_YES; s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, &do_write, s5r); - //ERROR! - //TODO! close socket after the write! schedule task - //GNUNET_NETWORK_socket_close (s5r->sock); - //GNUNET_free(s5r); return; } @@ -669,14 +2995,10 @@ do_read (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) s5r->remote_sock, &do_read_remote, s5r); } - - } - - //GNUNET_CONTAINER_DLL_remove (s5conns.head, s5conns.tail, s5r); - } + /** * Accept new incoming connections * @@ -701,7 +3023,7 @@ do_accept (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (NULL == s) { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "accept"); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "accept"); return; } @@ -717,9 +3039,251 @@ do_accept (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, &do_read, s5r); - //GNUNET_CONTAINER_DLL_insert (s5conns.head, s5conns.tail, s5r); } + +/** + * Task run on shutdown + * + * @param cls closure + * @param tc task context + */ +static void +do_shutdown (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct MhdHttpList *hd; + struct MhdHttpList *tmp_hd; + struct NetworkHandleList *nh; + struct NetworkHandleList *tmp_nh; + struct ProxyCurlTask *ctask; + struct ProxyCurlTask *ctask_tmp; + struct ProxyUploadData *pdata; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Shutting down...\n"); + if (NULL != local_gns_zone) + GNUNET_free (local_gns_zone); + if (NULL != local_private_zone) + GNUNET_free (local_private_zone); + if (NULL != local_shorten_zone) + GNUNET_free (local_shorten_zone); + + if (GNUNET_SCHEDULER_NO_TASK != curl_download_task) + { + GNUNET_SCHEDULER_cancel (curl_download_task); + curl_download_task = GNUNET_SCHEDULER_NO_TASK; + } + + for (hd = mhd_httpd_head; hd != NULL; hd = tmp_hd) + { + tmp_hd = hd->next; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Stopping daemon\n"); + + if (GNUNET_SCHEDULER_NO_TASK != hd->httpd_task) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Stopping select task %d\n", + hd->httpd_task); + GNUNET_SCHEDULER_cancel (hd->httpd_task); + hd->httpd_task = GNUNET_SCHEDULER_NO_TASK; + } + if (NULL != hd->daemon) + { + MHD_stop_daemon (hd->daemon); + hd->daemon = NULL; + } + for (nh = hd->socket_handles_head; nh != NULL; nh = tmp_nh) + { + tmp_nh = nh->next; + + GNUNET_NETWORK_socket_close (nh->h); + + GNUNET_free (nh); + } + + if (NULL != hd->proxy_cert) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Free certificate\n"); + GNUNET_free (hd->proxy_cert); + } + + GNUNET_free (hd); + } + + for (ctask=ctasks_head; ctask != NULL; ctask=ctask_tmp) + { + ctask_tmp = ctask->next; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cleaning up cURL task\n"); + + if (ctask->curl != NULL) + curl_easy_cleanup (ctask->curl); + ctask->curl = NULL; + if (NULL != ctask->headers) + curl_slist_free_all (ctask->headers); + if (NULL != ctask->resolver) + curl_slist_free_all (ctask->resolver); + + if (NULL != ctask->response) + MHD_destroy_response (ctask->response); + + pdata = ctask->upload_data_head; + + //FIXME free pdata here + for (; pdata != NULL; pdata = ctask->upload_data_head) + { + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free_non_null (pdata->filename); + GNUNET_free_non_null (pdata->content_type); + GNUNET_free_non_null (pdata->key); + GNUNET_free_non_null (pdata->value); + GNUNET_free (pdata); + } + GNUNET_free (ctask); + } + curl_multi_cleanup (curl_multi); + GNUNET_GNS_disconnect (gns_handle); + gnutls_global_deinit (); +} + + +/** + * Compiles a regex for us + * + * @param re ptr to re struct + * @param rt the expression to compile + * @return 0 on success + */ +static int +compile_regex (regex_t *re, const char* rt) +{ + int status; + char err[1024]; + + status = regcomp (re, rt, REG_EXTENDED|REG_NEWLINE); + if (status) + { + regerror (status, re, err, 1024); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Regex error compiling '%s': %s\n", rt, err); + return 1; + } + return 0; +} + + +/** + * Loads the users local zone key + * + * @return GNUNET_YES on success + */ +static int +load_local_zone_key (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *keyfile; + struct GNUNET_CRYPTO_RsaPrivateKey *key; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; + struct GNUNET_CRYPTO_ShortHashCode *zone; + struct GNUNET_CRYPTO_ShortHashAsciiEncoded zonename; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", &keyfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to load zone key config value!\n"); + return GNUNET_NO; + } + + if (GNUNET_NO == GNUNET_DISK_file_test (keyfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to load zone key %s!\n", keyfile); + GNUNET_free(keyfile); + return GNUNET_NO; + } + + key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); + local_gns_zone = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + GNUNET_CRYPTO_short_hash(&pkey, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + local_gns_zone); + zone = local_gns_zone; + GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Using zone: %s!\n", &zonename); + GNUNET_CRYPTO_rsa_key_free(key); + GNUNET_free(keyfile); + keyfile = NULL; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "PRIVATE_ZONEKEY", &keyfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to load private zone key config value!\n"); + } + + if ((NULL != keyfile) && (GNUNET_NO == GNUNET_DISK_file_test (keyfile))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to load private zone key %s!\n", keyfile); + GNUNET_free(keyfile); + } + else + { + key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); + local_private_zone = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + GNUNET_CRYPTO_short_hash(&pkey, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + local_private_zone); + GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Using private zone: %s!\n", &zonename); + GNUNET_CRYPTO_rsa_key_free(key); + GNUNET_free(keyfile); + } + keyfile = NULL; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "SHORTEN_ZONEKEY", &keyfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to load shorten zone key config value!\n"); + } + + if ((NULL != keyfile) && (GNUNET_NO == GNUNET_DISK_file_test (keyfile))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to load shorten zone key %s!\n", keyfile); + GNUNET_free(keyfile); + } + else + { + key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); + local_shorten_zone = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + GNUNET_CRYPTO_short_hash(&pkey, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + local_shorten_zone); + GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Using shorten zone: %s!\n", &zonename); + GNUNET_CRYPTO_rsa_key_free(key); + GNUNET_free(keyfile); + } + + return GNUNET_YES; +} + + /** * Main function that will be run * @@ -733,6 +3297,72 @@ run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct sockaddr_in sa; + struct MhdHttpList *hd; + char* cafile_cfg = NULL; + char* cafile; +#if !HAVE_MHD_NO_LISTEN_SOCKET + size_t len; + char* proxy_sockfile; + struct sockaddr_un mhd_unix_sock_addr; +#endif + + if (NULL == (curl_multi = curl_multi_init ())) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to create cURL multo handle!\n"); + return; + } + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Loading CA\n"); + cafile = cafile_opt; + if (NULL == cafile) + { + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns-proxy", + "PROXY_CACERT", + &cafile_cfg)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to load proxy CA config value!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No proxy CA provided!\n"); + return; + } + cafile = cafile_cfg; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Using %s as CA\n", cafile); + + gnutls_global_init (); + gnutls_x509_crt_init (&proxy_ca.cert); + gnutls_x509_privkey_init (&proxy_ca.key); + + if ( (GNUNET_OK != load_cert_from_file (proxy_ca.cert, cafile)) || + (GNUNET_OK != load_key_from_file (proxy_ca.key, cafile)) ) + { + // FIXME: release resources... + return; + } + + GNUNET_free_non_null (cafile_cfg); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Loading Template\n"); + + compile_regex (&re_dotplus, (char*) RE_A_HREF); + + if (NULL == (gns_handle = GNUNET_GNS_connect (cfg))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to connect to GNS!\n"); + return; + } + if (GNUNET_NO == load_local_zone_key (cfg)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to load zone!\n"); + return; + } memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; @@ -765,26 +3395,106 @@ run (void *cls, char *const *args, const char *cfgfile, GNUNET_a2s ((const struct sockaddr *) &sa, sizeof (sa))); return; } - ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, lsock, &do_accept, NULL); + if (0 != curl_global_init (CURL_GLOBAL_WIN32)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "cURL global init failed!\n"); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Proxy listens on port %u\n", port); - - httpd = MHD_start_daemon (MHD_USE_DEBUG, 4444, - NULL, NULL, - &create_response, NULL, - MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 128, - MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, - MHD_OPTION_NOTIFY_COMPLETED, - NULL, NULL, - MHD_OPTION_END); - run_httpd (); +#if ! HAVE_MHD_NO_LISTEN_SOCKET + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns-proxy", + "PROXY_UNIXPATH", + &proxy_sockfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Specify PROXY_UNIXPATH in gns-proxy config section!\n"); + return; + } + if (NULL == (mhd_unix_socket = GNUNET_NETWORK_socket_create (AF_UNIX, + SOCK_STREAM, + 0))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to create unix domain socket!\n"); + return; + } + + mhd_unix_sock_addr.sun_family = AF_UNIX; + strcpy (mhd_unix_sock_addr.sun_path, proxy_sockfile); + +#if LINUX + mhd_unix_sock_addr.sun_path[0] = '\0'; +#endif +#if HAVE_SOCKADDR_IN_SIN_LEN + mhd_unix_sock_addr.sun_len = (u_char) sizeof (struct sockaddr_un); +#endif + + len = strlen (proxy_sockfile) + sizeof(AF_UNIX); + GNUNET_free (proxy_sockfile); + if (GNUNET_OK != GNUNET_NETWORK_socket_bind (mhd_unix_socket, + (struct sockaddr*)&mhd_unix_sock_addr, + len)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to bind unix domain socket!\n"); + return; + } + + if (GNUNET_OK != GNUNET_NETWORK_socket_listen (mhd_unix_socket, + 1)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to listen on unix domain socket!\n"); + return; + } +#endif + + hd = GNUNET_malloc (sizeof (struct MhdHttpList)); + hd->is_ssl = GNUNET_NO; + strcpy (hd->domain, ""); + +#if HAVE_MHD_NO_LISTEN_SOCKET + httpd = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET, + 0, + &accept_cb, NULL, + &create_response, hd, + MHD_OPTION_CONNECTION_LIMIT, MHD_MAX_CONNECTIONS, + MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, + MHD_OPTION_NOTIFY_COMPLETED, + NULL, NULL, + MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, NULL, + MHD_OPTION_END); +#else + httpd = MHD_start_daemon (MHD_USE_DEBUG, + 4444 /* Dummy port */, + &accept_cb, NULL, + &create_response, hd, + MHD_OPTION_LISTEN_SOCKET, GNUNET_NETWORK_get_fd (mhd_unix_socket), + MHD_OPTION_CONNECTION_LIMIT, MHD_MAX_CONNECTIONS, + MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, + MHD_OPTION_NOTIFY_COMPLETED, + NULL, NULL, + MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, NULL, + MHD_OPTION_END); +#endif + GNUNET_break (httpd != NULL); + hd->daemon = httpd; + hd->httpd_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_CONTAINER_DLL_insert (mhd_httpd_head, mhd_httpd_tail, hd); + run_httpds (); + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, + &do_shutdown, NULL); } + /** * The main function for gnunet-gns-proxy. * @@ -797,13 +3507,17 @@ main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'p', "port", NULL, - gettext_noop ("listen on specified port"), 1, - &GNUNET_GETOPT_set_string, &port}, + gettext_noop ("listen on specified port (default: 7777)"), 1, + &GNUNET_GETOPT_set_ulong, &port}, + {'a', "authority", NULL, + gettext_noop ("pem file to use as CA"), 1, + &GNUNET_GETOPT_set_string, &cafile_opt}, GNUNET_GETOPT_OPTION_END }; - int ret; + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + return 2; GNUNET_log_setup ("gnunet-gns-proxy", "WARNING", NULL); ret = (GNUNET_OK == @@ -811,5 +3525,8 @@ main (int argc, char *const *argv) _("GNUnet GNS proxy"), options, &run, NULL)) ? 0 : 1; + GNUNET_free_non_null ((char *) argv); return ret; } + +/* end of gnunet-gns-proxy.c */ diff --git a/src/gns/gnunet-gns.c b/src/gns/gnunet-gns.c index ca3a594..74212d4 100644 --- a/src/gns/gnunet-gns.c +++ b/src/gns/gnunet-gns.c @@ -22,8 +22,6 @@ * @brief command line tool to access distributed GNS * @author Christian Grothoff * - * TODO: - * - everything */ #include "platform.h" #include <gnunet_util_lib.h> @@ -46,7 +44,6 @@ static char *shorten_name; */ static char *lookup_name; - /** * record type to look up (-t option) */ @@ -60,11 +57,30 @@ static char *auth_name; /** * raw output */ -static int raw = 0; +static int raw; +/** + * Requested record type. + */ static enum GNUNET_GNS_RecordType rtype; /** + * Handle to lookup request + */ +static struct GNUNET_GNS_LookupRequest *lookup_request; + +/** + * Handle to shorten request + */ +static struct GNUNET_GNS_ShortenRequest *shorten_request; + +/** + * Handle to get authority request + */ +static struct GNUNET_GNS_GetAuthRequest *getauth_request; + + +/** * Task run on shutdown. Cleans up everything. * * @param cls unused @@ -74,6 +90,21 @@ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + if (NULL != lookup_request) + { + GNUNET_GNS_cancel_lookup_request (lookup_request); + lookup_request = NULL; + } + if (NULL != shorten_request) + { + GNUNET_GNS_cancel_shorten_request (shorten_request); + shorten_request = NULL; + } + if (NULL != getauth_request) + { + GNUNET_GNS_cancel_get_auth_request (getauth_request); + getauth_request = NULL; + } if (NULL != gns) { GNUNET_GNS_disconnect (gns); @@ -82,57 +113,84 @@ do_shutdown (void *cls, } +/** + * Function called with the result of a shorten operation. + * Prints the result. + * + * @param cls a 'const char *' with the original (long) name + * @param nshort the shortened name + */ static void -process_shorten_result(void* cls, const char* nshort) +process_shorten_result (void* cls, const char *nshort) { + const char *original_name = cls; + + shorten_request = NULL; if (raw) printf("%s", nshort); else - printf("%s shortened to %s\n", (char*) cls, nshort); - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + printf("%s shortened to %s\n", original_name, nshort); + GNUNET_SCHEDULER_shutdown (); } + +/** + * Function called with the result of a GADS lookup. + * + * @param cls the 'const char *' name that was resolved + * @param rd_count number of records returned + * @param rd array of 'rd_count' records with the results + */ static void -process_lookup_result(void* cls, uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +process_lookup_result (void* cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { - int i; - char* name = (char*) cls; + const char* name = cls; + uint32_t i; const char* typename; char* string_val; - - if (!raw) { - if (rd_count == 0) + + lookup_request = NULL; + if (!raw) + { + if (0 == rd_count) printf("No results.\n"); else printf("%s:\n", name); } - - - for (i=0; i<rd_count; i++) { typename = GNUNET_NAMESTORE_number_to_typename (rd[i].record_type); - string_val = GNUNET_NAMESTORE_value_to_string(rd[i].record_type, - rd[i].data, - rd[i].data_size); + string_val = GNUNET_NAMESTORE_value_to_string (rd[i].record_type, + rd[i].data, + rd[i].data_size); if (raw) - printf("%s\n", string_val); + printf ("%s\n", string_val); else - printf("Got %s record: %s\n", typename, string_val); - + printf ("Got `%s' record: %s\n", typename, string_val); + GNUNET_free_non_null (string_val); } - - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + GNUNET_SCHEDULER_shutdown (); } + +/** + * Function called with the result of an authority lookup. + * + * @param cls the 'const char *' with the name for which the + * authority was resolved + * @param auth name of the authority + */ static void -process_auth_result(void* cls, const char* auth) +process_auth_result (void* cls, + const char *auth) { + getauth_request = NULL; printf ("%s\n", auth); - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + GNUNET_SCHEDULER_shutdown (); } + /** * Main function that will be run. * @@ -151,69 +209,135 @@ run (void *cls, char *const *args, const char *cfgfile, struct GNUNET_CRYPTO_ShortHashCode *zone = NULL; struct GNUNET_CRYPTO_ShortHashCode user_zone; struct GNUNET_CRYPTO_ShortHashAsciiEncoded zonename; + struct GNUNET_CRYPTO_RsaPrivateKey *shorten_key = NULL; + struct GNUNET_CRYPTO_RsaPrivateKey *private_key = NULL; + struct GNUNET_CRYPTO_ShortHashCode *private_zone = NULL; + struct GNUNET_CRYPTO_ShortHashCode *shorten_zone = NULL; + gns = GNUNET_GNS_connect (cfg); + if (NULL == gns) + { + fprintf (stderr, + _("Failed to connect to GNS\n")); + return; + } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", "ZONEKEY", &keyfile)) { - if (!raw) + if (! raw) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "No private key for root zone found, using default!\n"); - zone = NULL; } else { - if (GNUNET_YES == GNUNET_DISK_file_test (keyfile)) - { - key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); - GNUNET_CRYPTO_short_hash(&pkey, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &user_zone); - zone = &user_zone; - GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); - if (!raw) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Using zone: %s!\n", &zonename); - GNUNET_CRYPTO_rsa_key_free(key); - } + key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); + GNUNET_CRYPTO_short_hash (&pkey, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &user_zone); + zone = &user_zone; + GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); + if (!raw) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Using zone: %s!\n", &zonename); + GNUNET_CRYPTO_rsa_key_free (key); GNUNET_free(keyfile); } - - gns = GNUNET_GNS_connect (cfg); - if (lookup_type != NULL) - rtype = GNUNET_NAMESTORE_typename_to_number(lookup_type); + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "SHORTEN_ZONEKEY", &keyfile)) + { + if (! raw) + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "No shorten key found!\n"); + } else - rtype = GNUNET_GNS_RECORD_TYPE_A; - - if (NULL == gns) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to connect to GNS\n")); - return; + shorten_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + GNUNET_CRYPTO_rsa_key_get_public (shorten_key, &pkey); + shorten_zone = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + GNUNET_CRYPTO_short_hash(&pkey, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + shorten_zone); + GNUNET_CRYPTO_short_hash_to_enc (shorten_zone, &zonename); + if (! raw) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Using shorten zone: %s!\n", &zonename); + GNUNET_free (keyfile); } - - if (shorten_name != NULL) + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "PRIVATE_ZONEKEY", &keyfile)) { - /** shorten name */ - GNUNET_GNS_shorten_zone (gns, shorten_name, zone, &process_shorten_result, - shorten_name); + if (! raw) + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "No private zone key file name specified in configuration!\n"); } - - if (lookup_name != NULL) + else { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Lookup\n"); - GNUNET_GNS_lookup_zone (gns, lookup_name, zone, rtype, - &process_lookup_result, lookup_name); + private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + GNUNET_CRYPTO_rsa_key_get_public (private_key, &pkey); + private_zone = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + GNUNET_CRYPTO_short_hash(&pkey, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + private_zone); + GNUNET_CRYPTO_short_hash_to_enc (private_zone, &zonename); + if (! raw) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Using private zone: %s!\n", &zonename); + GNUNET_CRYPTO_rsa_key_free (private_key); } + + if (NULL != lookup_type) + rtype = GNUNET_NAMESTORE_typename_to_number (lookup_type); + else + rtype = GNUNET_GNS_RECORD_A; - if (auth_name != NULL) + if ( (NULL != shorten_name) && + (NULL != shorten_zone) && + (NULL != private_zone) ) + { + shorten_request = GNUNET_GNS_shorten_zone (gns, shorten_name, + private_zone, + shorten_zone, + zone, + &process_shorten_result, + shorten_name); + } + if (NULL != lookup_name) { - GNUNET_GNS_get_authority(gns, auth_name, &process_auth_result, auth_name); + lookup_request = GNUNET_GNS_lookup_zone (gns, lookup_name, + zone, + rtype, + GNUNET_NO, /* Use DHT */ + shorten_key, + &process_lookup_result, + lookup_name); } + if (NULL != auth_name) + { + getauth_request = GNUNET_GNS_get_authority (gns, auth_name, + &process_auth_result, auth_name); + } + + if (NULL != shorten_key) + GNUNET_CRYPTO_rsa_key_free (shorten_key); + if (NULL != shorten_zone) + GNUNET_free (shorten_zone); + if (NULL != private_zone) + GNUNET_free (private_zone); - // FIXME: do work here... - //GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + if ( (NULL == auth_name) && + (NULL == shorten_name) && + (NULL == lookup_name)) + { + fprintf (stderr, + _("Please specify lookup, shorten or authority operation!\n")); + GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + return; + } + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, + &do_shutdown, NULL); } @@ -228,26 +352,28 @@ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { - {'s', "shorten", NULL, - gettext_noop ("try to shorten a given GNS name"), 1, + {'s', "shorten", "NAME", + gettext_noop ("try to shorten a given name"), 1, &GNUNET_GETOPT_set_string, &shorten_name}, - {'u', "lookup", NULL, - gettext_noop ("Lookup a record using GNS (NOT IMPLEMENTED)"), 1, + {'u', "lookup", "NAME", + gettext_noop ("Lookup a record for the given name"), 1, &GNUNET_GETOPT_set_string, &lookup_name}, - {'a', "authority", NULL, + {'a', "authority", "NAME", gettext_noop ("Get the authority of a particular name"), 1, &GNUNET_GETOPT_set_string, &auth_name}, - {'t', "type", NULL, - gettext_noop ("Specify the type of the record lookup"), 1, + {'t', "type", "TYPE", + gettext_noop ("Specify the type of the record to lookup"), 1, &GNUNET_GETOPT_set_string, &lookup_type}, {'r', "raw", NULL, gettext_noop ("No unneeded output"), 0, &GNUNET_GETOPT_set_one, &raw}, GNUNET_GETOPT_OPTION_END }; - int ret; + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + return 2; + GNUNET_log_setup ("gnunet-gns", "WARNING", NULL); ret = (GNUNET_OK == @@ -255,7 +381,7 @@ main (int argc, char *const *argv) _("GNUnet GNS access tool"), options, &run, NULL)) ? 0 : 1; - + GNUNET_free ((void*) argv); return ret; } diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c index 5e22801..5ce0890 100644 --- a/src/gns/gnunet-service-gns.c +++ b/src/gns/gnunet-service-gns.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) + (C) 2009, 2010, 2011, 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 @@ -17,9 +17,7 @@ Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - /** - * * @file gns/gnunet-service-gns.c * @brief GNUnet GNS service * @author Martin Schanzenbach @@ -32,18 +30,36 @@ #include "gnunet_dht_service.h" #include "gnunet_namestore_service.h" #include "gnunet_gns_service.h" +#include "gnunet_statistics_service.h" #include "block_gns.h" #include "gns.h" +#include "gns_common.h" #include "gnunet-service-gns_resolver.h" #include "gnunet-service-gns_interceptor.h" +#include "gnunet_protocols.h" -/* FIXME move to proper header in include */ -#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP 23 -#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT 24 -#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN 25 -#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT 26 -#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH 27 -#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT 28 +/** + * The initial interval in milliseconds btween puts in + * a zone iteration + */ +#define INITIAL_PUT_INTERVAL GNUNET_TIME_UNIT_MILLISECONDS + +/** + * The upper bound for the zone iteration interval in milliseconds + */ +#define MINIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_UNIT_SECONDS + +/** + * The default put interval for the zone iteration. In case + * No option is found + */ +#define DEFAULT_ZONE_PUBLISH_TIME_WINDOW GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4) + +/** + * The factor the current zone iteration interval is divided by for each + * additional new record + */ +#define LATE_ITERATION_SPEEDUP_FACTOR 2 /** @@ -51,37 +67,89 @@ */ struct ClientShortenHandle { - /* the requesting client that */ + + /** + * List for all shorten requests + */ + struct ClientShortenHandle *next; + + /** + * List for all shorten requests + */ + struct ClientShortenHandle *prev; + + /** + * Handle to the requesting client + */ struct GNUNET_SERVER_Client *client; - /* request id */ - uint64_t unique_id; + /** + * Namestore lookup task + */ + struct GNUNET_NAMESTORE_QueueEntry *namestore_task; + + /** + * master zone + */ + struct GNUNET_CRYPTO_ShortHashCode root_zone; + + /** + * private zone + */ + struct GNUNET_CRYPTO_ShortHashCode private_zone; + + /** + * shorten zone + */ + struct GNUNET_CRYPTO_ShortHashCode shorten_zone; + + /** + * The request id + */ + uint32_t request_id; - /* request type */ + /** + * request type + */ enum GNUNET_GNS_RecordType type; - /* optional zone private key used for lookup */ - struct GNUNET_CRYPTO_RsaPrivateKey *zone_key; + /** + * name to shorten + */ + char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + + /** + * name of private zone (relative to root) + */ + char private_zone_id[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - /* name to shorten */ - char* name; + /** + * name of shorten zone (relative to root) + */ + char shorten_zone_id[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; }; /** - * Handle to a get auhtority operation from api + * Handle to a get authority operation from api */ struct ClientGetAuthHandle { - /* the requesting client that */ + /** + * Handle to the requesting client + */ struct GNUNET_SERVER_Client *client; - /* request id */ - uint64_t unique_id; + /** + * name to lookup authority + */ + char *name; - /* name to lookup authority */ - char* name; + /** + * request id + */ + uint32_t request_id; }; @@ -91,22 +159,44 @@ struct ClientGetAuthHandle */ struct ClientLookupHandle { - /* the requesting client that */ + + /** + * Handle to the requesting client + */ struct GNUNET_SERVER_Client *client; - /* request id */ - uint64_t unique_id; + /** + * optional zone private key used for shorten + */ + struct GNUNET_CRYPTO_RsaPrivateKey *shorten_key; - /* request type */ - enum GNUNET_GNS_RecordType type; + /** + * the name to look up + */ + char *name; + + /** + * The zone we look up in + */ + struct GNUNET_CRYPTO_ShortHashCode zone; + + /** + * request id + */ + uint32_t request_id; - /* optional zone private key used for lookup */ - struct GNUNET_CRYPTO_RsaPrivateKey *zone_key; + /** + * GNUNET_YES if we only want to lookup from local cache + */ + int only_cached; - /* the name to look up */ - char* name; //Needed? + /** + * request type + */ + enum GNUNET_GNS_RecordType type; }; + /** * Our handle to the DHT */ @@ -115,23 +205,17 @@ static struct GNUNET_DHT_Handle *dht_handle; /** * Our zone's private key */ -struct GNUNET_CRYPTO_RsaPrivateKey *zone_key; +static struct GNUNET_CRYPTO_RsaPrivateKey *zone_key; /** * Our handle to the namestore service - * FIXME maybe need a second handle for iteration */ -struct GNUNET_NAMESTORE_Handle *namestore_handle; +static struct GNUNET_NAMESTORE_Handle *namestore_handle; /** * Handle to iterate over our authoritative zone in namestore */ -struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter; - -/** - * The configuration the GNS service is running with - */ -const struct GNUNET_CONFIGURATION_Handle *GNS_cfg; +static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter; /** * Our notification context. @@ -141,41 +225,74 @@ static struct GNUNET_SERVER_NotificationContext *nc; /** * Our zone hash */ -struct GNUNET_CRYPTO_ShortHashCode zone_hash; +static struct GNUNET_CRYPTO_ShortHashCode zone_hash; /** * Useful for zone update for DHT put */ -static int num_public_records; +static unsigned long long num_public_records; /** - * update interval in seconds + * Last seen record count */ -static unsigned long long max_record_put_interval; +static unsigned long long last_num_public_records; -static unsigned long long dht_max_update_interval; +/** + * Zone iteration PUT interval. + */ +static struct GNUNET_TIME_Relative put_interval; -/* dht update interval FIXME define? */ -static struct GNUNET_TIME_Relative record_put_interval; +/** + * Time window for zone iteration + */ +static struct GNUNET_TIME_Relative zone_publish_time_window; -/* zone update task */ -GNUNET_SCHEDULER_TaskIdentifier zone_update_taskid = GNUNET_SCHEDULER_NO_TASK; +/** + * zone publish task + */ +static GNUNET_SCHEDULER_TaskIdentifier zone_publish_task; -/* automatic pkey import for name shortening */ +/** + * GNUNET_YES if automatic pkey import for name shortening + * is enabled + */ static int auto_import_pkey; -/* lookup timeout */ +/** + * GNUNET_YES if zone has never been published before + */ +static int first_zone_iteration; + +/** + * The lookup timeout + */ static struct GNUNET_TIME_Relative default_lookup_timeout; /** - * Continue shutdown + * GNUNET_YES if ipv6 is supported */ -static void -on_resolver_cleanup(void) -{ - GNUNET_NAMESTORE_disconnect(namestore_handle, 1); - GNUNET_DHT_disconnect(dht_handle); -} +static int v6_enabled; + +/** + * GNUNET_YES if ipv4 is supported + */ +static int v4_enabled; + +/** + * List for shorten requests + */ +static struct ClientShortenHandle *csh_head; + +/** + * List for shorten requests + */ +static struct ClientShortenHandle *csh_tail; + +/** + * Handle to the statistics service + */ +static struct GNUNET_STATISTICS_Handle *statistics; + /** * Task run during shutdown. @@ -186,54 +303,71 @@ on_resolver_cleanup(void) static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + struct ClientShortenHandle *csh_tmp; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Shutting down!"); - /* Kill zone task for it may make the scheduler hang */ - if (zone_update_taskid != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel(zone_update_taskid); - - GNUNET_SERVER_notification_context_destroy (nc); - - gns_interceptor_stop(); - gns_resolver_cleanup(&on_resolver_cleanup); - + while (NULL != (csh_tmp = csh_head)) + { + GNUNET_CONTAINER_DLL_remove (csh_head, csh_tail, csh_tmp); + GNUNET_free (csh_tmp); + } + GNUNET_SERVER_notification_context_destroy (nc); + gns_interceptor_stop (); + gns_resolver_cleanup (); + if (NULL != statistics) + { + GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); + statistics = NULL; + } + if (GNUNET_SCHEDULER_NO_TASK != zone_publish_task) + { + GNUNET_SCHEDULER_cancel (zone_publish_task); + zone_publish_task = GNUNET_SCHEDULER_NO_TASK; + } + if (NULL != namestore_iter) + { + GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter); + namestore_iter = NULL; + } + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + if (NULL != dht_handle) + { + GNUNET_DHT_disconnect (dht_handle); + dht_handle = NULL; + } } /** - * Method called periodicattluy that triggers - * iteration over root zone + * Method called periodically that triggers iteration over authoritative records * * @param cls closure * @param tc task context */ static void -update_zone_dht_next(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +publish_zone_dht_next (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { - zone_update_taskid = GNUNET_SCHEDULER_NO_TASK; - GNUNET_NAMESTORE_zone_iterator_next(namestore_iter); + zone_publish_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_NAMESTORE_zone_iterator_next (namestore_iter); } + /** - * Continuation for DHT put + * Periodically iterate over our zone and store everything in dht * - * @param cls closure - * @param success GNUNET_OK if the PUT was transmitted, - * GNUNET_NO on timeout, - * GNUNET_SYSERR on disconnect from service - * after the PUT message was transmitted - * (so we don't know if it was received or not) + * @param cls NULL + * @param tc task context */ static void -record_dht_put(void *cls, int success) -{ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "put request transmitted\n"); -} +publish_zone_dht_start (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); -/* prototype */ -static void -update_zone_dht_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Function used to put all records successively into the DHT. @@ -247,134 +381,167 @@ update_zone_dht_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); * @param signature the signature for the record data */ static void -put_gns_record(void *cls, +put_gns_record (void *cls, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, struct GNUNET_TIME_Absolute expiration, const char *name, unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature) -{ - +{ struct GNSNameRecordBlock *nrb; - struct GNUNET_CRYPTO_ShortHashCode name_hash; struct GNUNET_CRYPTO_ShortHashCode zhash; - GNUNET_HashCode xor_hash; - GNUNET_HashCode name_hash_double; - GNUNET_HashCode zone_hash_double; + struct GNUNET_HashCode dht_key; uint32_t rd_payload_length; char* nrb_data = NULL; size_t namelen; + struct GNUNET_TIME_Relative next_put_interval; - /* we're done */ if (NULL == name) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Zone iteration finished. Rescheduling put in %ds\n", - dht_max_update_interval); - zone_update_taskid = GNUNET_SCHEDULER_add_delayed ( - GNUNET_TIME_relative_multiply( - GNUNET_TIME_UNIT_SECONDS, - dht_max_update_interval - ), - &update_zone_dht_start, - NULL); + /* we're done */ + namestore_iter = NULL; + last_num_public_records = num_public_records; + first_zone_iteration = GNUNET_NO; + if (0 == num_public_records) + { + /** + * If no records are known (startup) or none present + * we can safely set the interval to the value for a single + * record + */ + put_interval = zone_publish_time_window; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, + "No records in db.\n"); + } + else + { + put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window, + num_public_records); + } + put_interval = GNUNET_TIME_relative_max (MINIMUM_ZONE_ITERATION_INTERVAL, + put_interval); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Zone iteration finished. Adjusted zone iteration interval to %s\n", + GNUNET_STRINGS_relative_time_to_string (put_interval, GNUNET_YES)); + GNUNET_STATISTICS_set (statistics, + "Current zone iteration interval (in ms)", + put_interval.rel_value, + GNUNET_NO); + GNUNET_STATISTICS_update (statistics, + "Number of zone iterations", 1, GNUNET_NO); + GNUNET_STATISTICS_set (statistics, + "Number of public records in DHT", + last_num_public_records, + GNUNET_NO); + if (0 == num_public_records) + zone_publish_task = GNUNET_SCHEDULER_add_delayed (put_interval, + &publish_zone_dht_start, + NULL); + else + zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, NULL); return; } - namelen = strlen(name) + 1; - - if (signature == NULL) + namelen = strlen (name) + 1; + if (0 == rd_count) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "No signature for %s record data provided! Skipping...\n", - name); - zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_next, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No records for name `%s'! Skipping.\n", + name); + zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next, + NULL); + return; + } + if (NULL == signature) + { + GNUNET_break (0); + zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next, NULL); return; - } - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Putting records for %s into the DHT\n", name); - - rd_payload_length = GNUNET_NAMESTORE_records_get_size (rd_count, rd); - - nrb = GNUNET_malloc(rd_payload_length + namelen - + sizeof(struct GNSNameRecordBlock)); - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Putting records for `%s' into the DHT\n", name); + rd_payload_length = GNUNET_NAMESTORE_records_get_size (rd_count, rd); + nrb = GNUNET_malloc (rd_payload_length + namelen + + sizeof (struct GNSNameRecordBlock)); nrb->signature = *signature; - nrb->public_key = *key; - - nrb->rd_count = htonl(rd_count); - - memcpy(&nrb[1], name, namelen); - - nrb_data = (char*)&nrb[1]; + nrb->rd_count = htonl (rd_count); + memcpy (&nrb[1], name, namelen); + nrb_data = (char *) &nrb[1]; nrb_data += namelen; - rd_payload_length += sizeof(struct GNSNameRecordBlock) + namelen; - + GNUNET_CRYPTO_short_hash (key, + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &zhash); if (-1 == GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_payload_length, nrb_data)) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Record serialization failed! Skipping...\n"); - GNUNET_free(nrb); - zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_next, + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Records for name `%s' in zone %s too large to fit into DHT"), + name, + GNUNET_short_h2s (&zhash)); + GNUNET_free (nrb); + zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next, NULL); return; } - - /* - * calculate DHT key: H(name) xor H(pubkey) - */ - GNUNET_CRYPTO_short_hash(key, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &zhash); - GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash); - GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double); - GNUNET_CRYPTO_short_hash_double (&zhash, &zone_hash_double); - GNUNET_CRYPTO_hash_xor(&zone_hash_double, &name_hash_double, &xor_hash); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "zone identity: %s\n", GNUNET_h2s (&zone_hash_double)); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "putting records for %s under key: %s with size %d\n", - name, GNUNET_h2s (&xor_hash), rd_payload_length); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "DHT req to %d\n", DHT_OPERATION_TIMEOUT.rel_value); - /* FIXME: keep return value to possibly cancel? */ - GNUNET_DHT_put (dht_handle, &xor_hash, - DHT_GNS_REPLICATION_LEVEL, - GNUNET_DHT_RO_NONE, - GNUNET_BLOCK_TYPE_GNS_NAMERECORD, - rd_payload_length, - (char*)nrb, - expiration, - DHT_OPERATION_TIMEOUT, - &record_dht_put, - NULL); //cls for cont + GNUNET_GNS_get_key_for_record (name, &zhash, &dht_key); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "putting %u records from zone %s for `%s' under key: %s with size %u and timeout %s\n", + rd_count, + GNUNET_short_h2s (&zhash), + name, + GNUNET_h2s (&dht_key), + (unsigned int) rd_payload_length, + GNUNET_STRINGS_relative_time_to_string (DHT_OPERATION_TIMEOUT, GNUNET_YES)); - num_public_records++; - - /** - * Reschedule periodic put - */ - zone_update_taskid = GNUNET_SCHEDULER_add_delayed (record_put_interval, - &update_zone_dht_next, - NULL); - - GNUNET_free(nrb); - + GNUNET_STATISTICS_update (statistics, + "Record bytes put into DHT", + rd_payload_length, GNUNET_NO); + + (void) GNUNET_DHT_put (dht_handle, &dht_key, + DHT_GNS_REPLICATION_LEVEL, + GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, + GNUNET_BLOCK_TYPE_GNS_NAMERECORD, + rd_payload_length, + (char*)nrb, + expiration, + DHT_OPERATION_TIMEOUT, + NULL, + NULL); + GNUNET_free (nrb); + + num_public_records++; + if ( (num_public_records > last_num_public_records) + && (GNUNET_NO == first_zone_iteration) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Last record count was lower than current record count. Reducing interval.\n"); + put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window, + num_public_records); + next_put_interval = GNUNET_TIME_relative_divide (put_interval, + LATE_ITERATION_SPEEDUP_FACTOR); + } + else + next_put_interval = put_interval; + + GNUNET_STATISTICS_set (statistics, + "Current zone iteration interval (ms)", + next_put_interval.rel_value, + GNUNET_NO); + zone_publish_task = GNUNET_SCHEDULER_add_delayed (next_put_interval, + &publish_zone_dht_next, + NULL); } + /** * Periodically iterate over our zone and store everything in dht * @@ -382,100 +549,27 @@ put_gns_record(void *cls, * @param tc task context */ static void -update_zone_dht_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +publish_zone_dht_start (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { - unsigned long long interval = 0; - - zone_update_taskid = GNUNET_SCHEDULER_NO_TASK; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Scheduling DHT zone update!\n"); - if (0 == num_public_records) - { - /** - * If no records are known (startup) or none present - * we can safely set the interval to 1s - */ - record_put_interval = GNUNET_TIME_relative_multiply( - GNUNET_TIME_UNIT_SECONDS, - 1); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "No records in db. Adjusted record put interval to 1s\n"); - } - else - { - interval = max_record_put_interval/num_public_records; - if (interval == 0) - interval = 1; - record_put_interval = GNUNET_TIME_relative_multiply( - GNUNET_TIME_UNIT_SECONDS, - interval); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Adjusted DHT update interval to %ds!\n", - interval); - } + zone_publish_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Scheduling DHT zone update!\n"); /* start counting again */ num_public_records = 0; namestore_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle, - NULL, //All zones - GNUNET_NAMESTORE_RF_AUTHORITY, - GNUNET_NAMESTORE_RF_PRIVATE, - &put_gns_record, - NULL); + NULL, /* All zones */ + GNUNET_NAMESTORE_RF_AUTHORITY, + GNUNET_NAMESTORE_RF_PRIVATE, + &put_gns_record, + NULL); } -/** - * Lookup the private key for the zone - * - * @param zone the zone we want a private key for - * @return NULL of not found else the key - */ -struct GNUNET_CRYPTO_RsaPrivateKey* -lookup_private_key(struct GNUNET_CRYPTO_ShortHashCode *zone) -{ - char* keydir; - struct GNUNET_CRYPTO_ShortHashAsciiEncoded zonename; - char* location; - struct GNUNET_CRYPTO_RsaPrivateKey *key = NULL; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Looking for private key\n"); - - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (GNS_cfg, - "namestore", - "ZONEFILE_DIRECTORY", &keydir)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No zonefile directory!\n"); - return NULL; - } - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Zonefile directory is %s\n", keydir); - - GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Zonefile is %s.zkey\n", &zonename); - - GNUNET_asprintf(&location, "%s%s%s.zkey", keydir, - DIR_SEPARATOR_STR, &zonename); - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Checking for %s\n", location); - - if (GNUNET_YES == GNUNET_DISK_file_test (location)) - key = GNUNET_CRYPTO_rsa_key_create_from_file (location); - - GNUNET_free(location); - GNUNET_free(keydir); - - return key; - -} /* END DHT ZONE PROPAGATION */ + /** * Send shorten response back to client * @@ -483,136 +577,291 @@ lookup_private_key(struct GNUNET_CRYPTO_ShortHashCode *zone) * @param name the shortened name result or NULL if cannot be shortened */ static void -send_shorten_response(void* cls, const char* name) +send_shorten_response (void* cls, const char* name) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n", - "SHORTEN_RESULT", name); + struct ClientShortenHandle *csh = cls; struct GNUNET_GNS_ClientShortenResultMessage *rmsg; - struct ClientShortenHandle *csh = (struct ClientShortenHandle *)cls; + size_t name_len; - if (name == NULL) - { - name = ""; - } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending `%s' message with %s\n", + "SHORTEN_RESULT", name); + if (NULL == name) + name_len = 0; + else + name_len = strlen (name) + 1; + GNUNET_STATISTICS_update (statistics, + "Name shorten results", 1, GNUNET_NO); - rmsg = GNUNET_malloc(sizeof(struct GNUNET_GNS_ClientShortenResultMessage) - + strlen(name) + 1); + rmsg = GNUNET_malloc (sizeof (struct GNUNET_GNS_ClientShortenResultMessage) + + name_len); - rmsg->id = csh->unique_id; + rmsg->id = csh->request_id; rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT); rmsg->header.size = htons(sizeof(struct GNUNET_GNS_ClientShortenResultMessage) + - strlen(name) + 1); + name_len); + memcpy (&rmsg[1], name, name_len); + GNUNET_SERVER_notification_context_unicast (nc, csh->client, + &rmsg->header, + GNUNET_NO); + if (NULL != csh->namestore_task) + GNUNET_NAMESTORE_cancel (csh->namestore_task); + GNUNET_free (rmsg); + GNUNET_free (csh); +} - strcpy((char*)&rmsg[1], name); - GNUNET_SERVER_notification_context_unicast (nc, csh->client, - (const struct GNUNET_MessageHeader *) rmsg, - GNUNET_NO); - GNUNET_SERVER_receive_done (csh->client, GNUNET_OK); +/** + * Lookup the zone infos and shorten name + * + * @param cls the client shorten handle + * @param key key of the zone + * @param expiration expiration of record + * @param name name found or null if no result + * @param rd_count number of records found + * @param rd record data + * @param signature + * + */ +static void +process_shorten_in_private_zone_lookup (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, + struct GNUNET_TIME_Absolute expiration, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct ClientShortenHandle *csh = cls; + struct GNUNET_CRYPTO_ShortHashCode *szone = &csh->shorten_zone; + struct GNUNET_CRYPTO_ShortHashCode *pzone = &csh->private_zone; + + csh->namestore_task = NULL; + if (0 == strcmp (csh->private_zone_id, "")) + pzone = NULL; + if (0 == rd_count) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No shorten zone in private zone!\n"); + strcpy (csh->shorten_zone_id, ""); + szone = NULL; + } + else + { + GNUNET_break (1 == rd_count); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Shorten zone %s found in private zone %s\n", + name, csh->private_zone_id); + + sprintf (csh->shorten_zone_id, "%s.%s", name, csh->private_zone_id); + } + GNUNET_CONTAINER_DLL_remove (csh_head, csh_tail, csh); + gns_resolver_shorten_name (&csh->root_zone, + pzone, + szone, + csh->name, + csh->private_zone_id, + csh->shorten_zone_id, + &send_shorten_response, csh); + +} + + +/** + * Lookup the zone infos and shorten name + * + * @param cls the shorten handle + * @param key key of the zone + * @param expiration expiration of record + * @param name name found or null if no result + * @param rd_count number of records found + * @param rd record data + * @param signature + * + */ +static void +process_shorten_in_root_zone_lookup (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, + struct GNUNET_TIME_Absolute expiration, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct ClientShortenHandle *csh = cls; + struct GNUNET_CRYPTO_ShortHashCode *szone = &csh->shorten_zone; + struct GNUNET_CRYPTO_ShortHashCode *pzone = &csh->private_zone; - GNUNET_free(rmsg); - GNUNET_free_non_null(csh->name); - GNUNET_free_non_null(csh->zone_key); - GNUNET_free(csh); + csh->namestore_task = NULL; + if (0 == strcmp (csh->private_zone_id, "")) + pzone = NULL; + if (0 == rd_count) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No shorten zone in zone and no private zone!\n"); + + strcpy (csh->shorten_zone_id, ""); + GNUNET_CONTAINER_DLL_remove (csh_head, csh_tail, csh); + szone = NULL; + gns_resolver_shorten_name (&csh->root_zone, + pzone, + szone, + csh->name, + csh->private_zone_id, + csh->shorten_zone_id, + &send_shorten_response, csh); + return; + } + GNUNET_break (rd_count == 1); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Private zone %s found in root zone\n", name); + strcpy (csh->private_zone_id, name); + csh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + pzone, + szone, + &process_shorten_in_private_zone_lookup, + csh); +} + +/** + * Lookup the zone infos and shorten name + * + * @param cls the shorten handle + * @param key key of the zone + * @param expiration expiration of record + * @param name name found or null if no result + * @param rd_count number of records found + * @param rd record data + * @param signature + */ +static void +process_private_in_root_zone_lookup (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, + struct GNUNET_TIME_Absolute expiration, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct ClientShortenHandle *csh = cls; + + csh->namestore_task = NULL; + if (0 == rd_count) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No private zone in root zone\n"); + strcpy (csh->private_zone_id, ""); + csh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + &csh->root_zone, + &csh->shorten_zone, + &process_shorten_in_root_zone_lookup, + csh); + return; + } + GNUNET_break (1 == rd_count); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Private zone `%s' found in root zone\n", + name); + strcpy (csh->private_zone_id, name); + csh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + &csh->private_zone, + &csh->shorten_zone, + &process_shorten_in_private_zone_lookup, + csh); } + /** * Handle a shorten message from the api * - * @param cls the closure + * @param cls the closure (unused) * @param client the client * @param message the message */ -static void handle_shorten(void *cls, - struct GNUNET_SERVER_Client * client, - const struct GNUNET_MessageHeader * message) +static void +handle_shorten (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "SHORTEN"); - - size_t msg_size = 0; struct ClientShortenHandle *csh; - char name[MAX_DNS_NAME_LENGTH]; + const char *utf_in; + char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; char* nameptr = name; - struct GNUNET_CRYPTO_ShortHashCode zone; - struct GNUNET_CRYPTO_RsaPrivateKey *key; + uint16_t msg_size; + const struct GNUNET_GNS_ClientShortenMessage *sh_msg; - if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientShortenMessage)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' message\n", "SHORTEN"); + msg_size = ntohs (message->size); + if (msg_size < sizeof (struct GNUNET_GNS_ClientShortenMessage)) { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - - - struct GNUNET_GNS_ClientShortenMessage *sh_msg = - (struct GNUNET_GNS_ClientShortenMessage *) message; - - msg_size = ntohs(message->size); - - if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE) + sh_msg = (const struct GNUNET_GNS_ClientShortenMessage *) message; + utf_in = (const char *) &sh_msg[1]; + if ('\0' != utf_in[msg_size - sizeof (struct GNUNET_GNS_ClientShortenMessage) - 1]) { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - - csh = GNUNET_malloc(sizeof(struct ClientShortenHandle)); + csh = GNUNET_malloc(sizeof (struct ClientShortenHandle)); csh->client = client; - csh->unique_id = sh_msg->id; - csh->zone_key = NULL; - - GNUNET_STRINGS_utf8_tolower((char*)&sh_msg[1], &nameptr); - - if (strlen (name) < strlen(GNUNET_GNS_TLD)) { + csh->request_id = sh_msg->id; + GNUNET_CONTAINER_DLL_insert (csh_head, csh_tail, csh); + GNUNET_STRINGS_utf8_tolower (utf_in, &nameptr); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "SHORTEN: Converted `%s' to `%s'\n", + utf_in, + nameptr); + GNUNET_SERVER_notification_context_add (nc, client); + if (strlen (name) < strlen (GNUNET_GNS_TLD)) + { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "SHORTEN: %s is too short", name); - csh->name = NULL; + "SHORTEN: %s is too short\n", name); + GNUNET_CONTAINER_DLL_remove (csh_head, csh_tail, csh); send_shorten_response(csh, name); + GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } - - if (strlen (name) > MAX_DNS_NAME_LENGTH) { + if (strlen (name) > GNUNET_DNSPARSER_MAX_NAME_LENGTH) + { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "SHORTEN: %s is too long", name); - csh->name = NULL; + "SHORTEN: %s is too long\n", name); + GNUNET_CONTAINER_DLL_remove (csh_head, csh_tail, csh); send_shorten_response(csh, name); + GNUNET_SERVER_receive_done (client, GNUNET_OK); return; - } - - if (!is_gnunet_tld(name) && !is_zkey_tld(name)) + } + if ( (! is_gads_tld (name)) && + (! is_zkey_tld (name)) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s is not our domain. Returning\n", name); - csh->name = NULL; - send_shorten_response(csh, name); + GNUNET_CONTAINER_DLL_remove (csh_head, csh_tail, csh); + send_shorten_response (csh, name); + GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } - - GNUNET_SERVER_notification_context_add (nc, client); - + csh->shorten_zone = sh_msg->shorten_zone; + csh->private_zone = sh_msg->private_zone; + strcpy (csh->name, name); if (1 == ntohl(sh_msg->use_default_zone)) - zone = zone_hash; //Default zone + csh->root_zone = zone_hash; //Default zone else - zone = sh_msg->zone; - - /* Start shortening */ - if (GNUNET_YES == auto_import_pkey) - { - if (1 == ntohl(sh_msg->use_default_zone)) - key = zone_key; - else - { - key = lookup_private_key(&sh_msg->zone); - csh->zone_key = key; - } - gns_resolver_shorten_name(zone, zone, name, key, - &send_shorten_response, csh); - } - else - gns_resolver_shorten_name(zone, zone, name, NULL, - &send_shorten_response, csh); + csh->root_zone = sh_msg->zone; + csh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + &csh->root_zone, + &csh->private_zone, + &process_private_in_root_zone_lookup, + csh); + GNUNET_STATISTICS_update (statistics, + "Name shorten attempts", 1, GNUNET_NO); + GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -620,45 +869,42 @@ static void handle_shorten(void *cls, * Send get authority response back to client * * @param cls the closure containing a client get auth handle - * @param name the shortened name result or NULL if cannot be shortened + * @param name the name of the authority, or NULL on error */ -static void -send_get_auth_response(void *cls, const char* name) +static void +send_get_auth_response (void *cls, + const char* name) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n", - "GET_AUTH_RESULT", name); + struct ClientGetAuthHandle *cah = cls; struct GNUNET_GNS_ClientGetAuthResultMessage *rmsg; - struct ClientGetAuthHandle *cah = (struct ClientGetAuthHandle *)cls; - if (name == NULL) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending `%s' message with `%s'\n", + "GET_AUTH_RESULT", name); + if (NULL != name) { - name = ""; - } - - rmsg = GNUNET_malloc(sizeof(struct GNUNET_GNS_ClientGetAuthResultMessage) - + strlen(name) + 1); + GNUNET_STATISTICS_update (statistics, + "Authorities resolved", 1, GNUNET_NO); + } + if (NULL == name) + name = ""; + rmsg = GNUNET_malloc (sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage) + + strlen (name) + 1); - rmsg->id = cah->unique_id; + rmsg->id = cah->request_id; rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT); rmsg->header.size = htons(sizeof(struct GNUNET_GNS_ClientGetAuthResultMessage) + - strlen(name) + 1); - - strcpy((char*)&rmsg[1], name); + strlen (name) + 1); + strcpy ((char*)&rmsg[1], name); GNUNET_SERVER_notification_context_unicast (nc, cah->client, - (const struct GNUNET_MessageHeader *) rmsg, - GNUNET_NO); + &rmsg->header, + GNUNET_NO); GNUNET_SERVER_receive_done (cah->client, GNUNET_OK); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up handles...\n"); - GNUNET_free(rmsg); GNUNET_free_non_null(cah->name); - GNUNET_free(cah); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done.\n"); - + GNUNET_free(cah); } @@ -669,74 +915,67 @@ send_get_auth_response(void *cls, const char* name) * @param client the client * @param message the message */ -static void handle_get_authority(void *cls, - struct GNUNET_SERVER_Client * client, - const struct GNUNET_MessageHeader * message) +static void +handle_get_authority (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "GET_AUTH"); - - size_t msg_size = 0; struct ClientGetAuthHandle *cah; - char name[MAX_DNS_NAME_LENGTH]; + const char *utf_in; + char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; char* nameptr = name; + uint16_t msg_size; + const struct GNUNET_GNS_ClientGetAuthMessage *sh_msg; - - if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientGetAuthMessage)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' message\n", "GET_AUTH"); + msg_size = ntohs(message->size); + if (msg_size < sizeof (struct GNUNET_GNS_ClientGetAuthMessage)) { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - GNUNET_SERVER_notification_context_add (nc, client); - - struct GNUNET_GNS_ClientGetAuthMessage *sh_msg = - (struct GNUNET_GNS_ClientGetAuthMessage *) message; - - msg_size = ntohs(message->size); - - if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE) + sh_msg = (const struct GNUNET_GNS_ClientGetAuthMessage *) message; + utf_in = (const char *) &sh_msg[1]; + if ('\0' != utf_in[msg_size - sizeof (struct GNUNET_GNS_ClientGetAuthMessage) - 1]) { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; - } - - GNUNET_STRINGS_utf8_tolower((char*)&sh_msg[1], &nameptr); - - + } + GNUNET_STRINGS_utf8_tolower(utf_in, &nameptr); cah = GNUNET_malloc(sizeof(struct ClientGetAuthHandle)); cah->client = client; - cah->unique_id = sh_msg->id; - - if (strlen(name) < strlen(GNUNET_GNS_TLD)) + cah->request_id = sh_msg->id; + if (strlen (name) < strlen(GNUNET_GNS_TLD)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "GET_AUTH: %s is too short. Returning\n", name); + "GET_AUTH: `%s' is too short. Returning\n", name); cah->name = NULL; send_get_auth_response(cah, name); return; - } - - if (strlen (name) > MAX_DNS_NAME_LENGTH) { + } + if (strlen (name) > GNUNET_DNSPARSER_MAX_NAME_LENGTH) + { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GET_AUTH: %s is too long", name); + "GET_AUTH: `%s' is too long", name); cah->name = NULL; send_get_auth_response(cah, name); return; - } - - if (strcmp(name+strlen(name)-strlen(GNUNET_GNS_TLD), - GNUNET_GNS_TLD) != 0) + } + if (0 != strcmp (name + strlen (name) - strlen (GNUNET_GNS_TLD), + GNUNET_GNS_TLD)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GET_AUTH: %s is not our domain. Returning\n", name); cah->name = NULL; - send_get_auth_response(cah, name); + send_get_auth_response (cah, name); return; } - if (strcmp(name, GNUNET_GNS_TLD) == 0) + if (0 == strcmp (name, GNUNET_GNS_TLD)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GET_AUTH: %s is us. Returning\n", name); @@ -745,19 +984,19 @@ static void handle_get_authority(void *cls, return; } - cah->name = GNUNET_malloc(strlen(name) - - strlen(GNUNET_GNS_TLD) + 1); - memset(cah->name, 0, - strlen(name)-strlen(GNUNET_GNS_TLD) + 1); - memcpy(cah->name, name, - strlen(name)-strlen(GNUNET_GNS_TLD)); + cah->name = GNUNET_malloc (strlen (name) + - strlen (GNUNET_GNS_TLD) + 1); + memcpy (cah->name, name, + strlen (name) - strlen (GNUNET_GNS_TLD)); /* Start delegation resolution in our namestore */ - gns_resolver_get_authority(zone_hash, zone_hash, name, &send_get_auth_response, cah); + gns_resolver_get_authority (zone_hash, zone_hash, name, + &send_get_auth_response, cah); + GNUNET_STATISTICS_update (statistics, + "Authority lookup attempts", 1, GNUNET_NO); } - /** * Reply to client with the result from our lookup. * @@ -766,11 +1005,11 @@ static void handle_get_authority(void *cls, * @param rd the record data */ static void -send_lookup_response(void* cls, - uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +send_lookup_response (void* cls, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { - struct ClientLookupHandle* clh = (struct ClientLookupHandle*)cls; + struct ClientLookupHandle* clh = cls; struct GNUNET_GNS_ClientLookupResultMessage *rmsg; size_t len; @@ -778,14 +1017,14 @@ send_lookup_response(void* cls, "LOOKUP_RESULT", rd_count); len = GNUNET_NAMESTORE_records_get_size (rd_count, rd); - rmsg = GNUNET_malloc(len+sizeof(struct GNUNET_GNS_ClientLookupResultMessage)); + rmsg = GNUNET_malloc (len + sizeof (struct GNUNET_GNS_ClientLookupResultMessage)); - rmsg->id = clh->unique_id; + rmsg->id = clh->request_id; rmsg->rd_count = htonl(rd_count); rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT); rmsg->header.size = htons(len+sizeof(struct GNUNET_GNS_ClientLookupResultMessage)); - + GNUNET_NAMESTORE_records_serialize (rd_count, rd, len, (char*)&rmsg[1]); GNUNET_SERVER_notification_context_unicast (nc, clh->client, @@ -796,11 +1035,14 @@ send_lookup_response(void* cls, GNUNET_free(rmsg); GNUNET_free(clh->name); - if (NULL != clh->zone_key) - GNUNET_free(clh->zone_key); - - GNUNET_free(clh); - + if (NULL != clh->shorten_key) + GNUNET_CRYPTO_rsa_key_free (clh->shorten_key); + GNUNET_free (clh); + GNUNET_STATISTICS_update (statistics, + "Completed lookups", 1, GNUNET_NO); + if (NULL != rd) + GNUNET_STATISTICS_update (statistics, + "Records resolved", rd_count, GNUNET_NO); } @@ -812,94 +1054,123 @@ send_lookup_response(void* cls, * @param message the message */ static void -handle_lookup(void *cls, - struct GNUNET_SERVER_Client * client, - const struct GNUNET_MessageHeader * message) +handle_lookup (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "LOOKUP"); - - size_t msg_size = 0; size_t namelen; - char name[MAX_DNS_NAME_LENGTH]; + char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; struct ClientLookupHandle *clh; char* nameptr = name; - struct GNUNET_CRYPTO_RsaPrivateKey *key = NULL; - struct GNUNET_CRYPTO_ShortHashCode zone; - - if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientLookupMessage)) + const char *utf_in; + int only_cached; + struct GNUNET_CRYPTO_RsaPrivateKey *key; + struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *pkey; + char* tmp_pkey; + uint16_t msg_size; + const struct GNUNET_GNS_ClientLookupMessage *sh_msg; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' message\n", "LOOKUP"); + msg_size = ntohs(message->size); + if (msg_size < sizeof (struct GNUNET_GNS_ClientLookupMessage)) { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - + sh_msg = (const struct GNUNET_GNS_ClientLookupMessage *) message; GNUNET_SERVER_notification_context_add (nc, client); + if (GNUNET_YES == ntohl (sh_msg->have_key)) + { + pkey = (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *) &sh_msg[1]; + tmp_pkey = (char*) &sh_msg[1]; + key = GNUNET_CRYPTO_rsa_decode_key (tmp_pkey, ntohs (pkey->len)); + GNUNET_STRINGS_utf8_tolower (&tmp_pkey[ntohs (pkey->len)], &nameptr); + } + else + { + key = NULL; + utf_in = (const char *) &sh_msg[1]; + if ('\0' != utf_in[msg_size - sizeof (struct GNUNET_GNS_ClientLookupMessage) - 1]) + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + GNUNET_STRINGS_utf8_tolower (utf_in, &nameptr); + } + + namelen = strlen (name) + 1; + clh = GNUNET_malloc (sizeof (struct ClientLookupHandle)); + memset (clh, 0, sizeof (struct ClientLookupHandle)); + clh->client = client; + clh->name = GNUNET_malloc (namelen); + strcpy (clh->name, name); + clh->request_id = sh_msg->id; + clh->type = ntohl (sh_msg->type); + clh->shorten_key = key; - struct GNUNET_GNS_ClientLookupMessage *sh_msg = - (struct GNUNET_GNS_ClientLookupMessage *) message; + only_cached = ntohl (sh_msg->only_cached); - msg_size = ntohs(message->size); + if (strlen (name) > GNUNET_DNSPARSER_MAX_NAME_LENGTH) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "LOOKUP: %s is too long", name); + clh->name = NULL; + send_lookup_response (clh, 0, NULL); + return; + } - if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE) + if ((GNUNET_GNS_RECORD_A == clh->type) && + (GNUNET_OK != v4_enabled)) { - GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "LOOKUP: Query for A record but AF_INET not supported!"); + clh->name = NULL; + send_lookup_response (clh, 0, NULL); return; } - GNUNET_STRINGS_utf8_tolower((char*)&sh_msg[1], &nameptr); - namelen = strlen(name)+1; - clh = GNUNET_malloc(sizeof(struct ClientLookupHandle)); - clh->client = client; - clh->name = GNUNET_malloc(namelen); - strcpy(clh->name, name); - clh->unique_id = sh_msg->id; - clh->type = ntohl(sh_msg->type); - clh->zone_key = NULL; - - if (strlen (name) > MAX_DNS_NAME_LENGTH) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "LOOKUP: %s is too long", name); + if ((GNUNET_GNS_RECORD_AAAA == clh->type) && + (GNUNET_OK != v6_enabled)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "LOOKUP: Query for AAAA record but AF_INET6 not supported!"); clh->name = NULL; - send_lookup_response(clh, 0, NULL); + send_lookup_response (clh, 0, NULL); return; } - - if (1 == ntohl(sh_msg->use_default_zone)) - zone = zone_hash; //Default zone + + if (1 == ntohl (sh_msg->use_default_zone)) + clh->zone = zone_hash; /* Default zone */ else - zone = sh_msg->zone; + clh->zone = sh_msg->zone; if (GNUNET_YES == auto_import_pkey) { - if (1 == ntohl(sh_msg->use_default_zone)) - key = zone_key; - else - { - key = lookup_private_key(&zone); - clh->zone_key = key; - } - - gns_resolver_lookup_record(zone, zone, clh->type, name, - key, - default_lookup_timeout, - &send_lookup_response, clh); + gns_resolver_lookup_record (clh->zone, clh->zone, clh->type, clh->name, + clh->shorten_key, + default_lookup_timeout, + clh->only_cached, + &send_lookup_response, clh); } else { - gns_resolver_lookup_record(zone, zone, clh->type, name, - NULL, - default_lookup_timeout, - &send_lookup_response, clh); + gns_resolver_lookup_record (clh->zone, clh->zone, clh->type, name, + NULL, + default_lookup_timeout, + only_cached, + &send_lookup_response, clh); } + GNUNET_STATISTICS_update (statistics, + "Record lookup attempts", 1, GNUNET_NO); } - /** * Process GNS requests. * - * @param cls closure) + * @param cls closure * @param server the initialized server * @param c configuration to use */ @@ -907,25 +1178,21 @@ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Initializing GNS\n"); - - char* keyfile; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; - unsigned long long max_parallel_bg_queries = 0; - unsigned long long default_lookup_timeout_secs = 0; - int ignore_pending = GNUNET_NO; - static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_shorten, NULL, GNUNET_MESSAGE_TYPE_GNS_SHORTEN, 0}, {&handle_lookup, NULL, GNUNET_MESSAGE_TYPE_GNS_LOOKUP, 0}, {&handle_get_authority, NULL, GNUNET_MESSAGE_TYPE_GNS_GET_AUTH, 0} }; + char* keyfile; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; + unsigned long long max_parallel_bg_queries = 0; + int ignore_pending = GNUNET_NO; - GNS_cfg = c; + v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6); + v4_enabled = GNUNET_NETWORK_test_pf (PF_INET); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "gns", - "ZONEKEY", &keyfile)) + "ZONEKEY", &keyfile)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No private key for root zone specified!\n"); @@ -938,114 +1205,87 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, zone_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); GNUNET_CRYPTO_rsa_key_get_public (zone_key, &pkey); - GNUNET_CRYPTO_short_hash(&pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_hash); GNUNET_free(keyfile); - - /** - * handle to our local namestore - */ - namestore_handle = GNUNET_NAMESTORE_connect(c); - + namestore_handle = GNUNET_NAMESTORE_connect (c); if (NULL == namestore_handle) { - //FIXME do error handling; - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Failed to connect to the namestore!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to connect to the namestore!\n")); GNUNET_SCHEDULER_shutdown (); return; } - - auto_import_pkey = GNUNET_NO; - if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (c, "gns", "AUTO_IMPORT_PKEY")) { - GNUNET_log(GNUNET_ERROR_TYPE_INFO, - "Automatic PKEY import is enabled.\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Automatic PKEY import is enabled.\n"); auto_import_pkey = GNUNET_YES; - } - - dht_max_update_interval = GNUNET_GNS_DHT_MAX_UPDATE_INTERVAL; + put_interval = INITIAL_PUT_INTERVAL; + zone_publish_time_window = DEFAULT_ZONE_PUBLISH_TIME_WINDOW; if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (c, "gns", - "ZONE_PUT_INTERVAL", - &dht_max_update_interval)) + GNUNET_CONFIGURATION_get_value_time (c, "gns", + "ZONE_PUBLISH_TIME_WINDOW", + &zone_publish_time_window)) { - GNUNET_log(GNUNET_ERROR_TYPE_INFO, - "DHT zone update interval: %d\n", - dht_max_update_interval); - } - - max_record_put_interval = 1; - - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (c, "gns", - "RECORD_PUT_INTERVAL", - &max_record_put_interval)) - { - GNUNET_log(GNUNET_ERROR_TYPE_INFO, - "Record put interval: %d\n", - max_record_put_interval); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Time window for zone iteration: %s\n", + GNUNET_STRINGS_relative_time_to_string (zone_publish_time_window, GNUNET_YES)); } - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (c, "gns", "MAX_PARALLEL_BACKGROUND_QUERIES", &max_parallel_bg_queries)) { - GNUNET_log(GNUNET_ERROR_TYPE_INFO, - "Number of allowed parallel background queries: %d\n", - max_parallel_bg_queries); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Number of allowed parallel background queries: %llu\n", + max_parallel_bg_queries); } if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (c, "gns", "AUTO_IMPORT_CONFIRMATION_REQ")) { - GNUNET_log(GNUNET_ERROR_TYPE_INFO, - "Auto import requires user confirmation\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Auto import requires user confirmation\n"); ignore_pending = GNUNET_YES; } if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number(c, "gns", - "DEFAULT_LOOKUP_TIMEOUT", - &default_lookup_timeout_secs)) + GNUNET_CONFIGURATION_get_value_time (c, "gns", + "DEFAULT_LOOKUP_TIMEOUT", + &default_lookup_timeout)) { - GNUNET_log(GNUNET_ERROR_TYPE_INFO, - "Default lookup timeout: %ds\n", default_lookup_timeout_secs); - default_lookup_timeout = GNUNET_TIME_relative_multiply( - GNUNET_TIME_UNIT_SECONDS, - default_lookup_timeout_secs); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Default lookup timeout: %s\n", + GNUNET_STRINGS_relative_time_to_string (default_lookup_timeout, + GNUNET_YES)); } - /** - * handle to the dht - */ - dht_handle = GNUNET_DHT_connect(c, - //max_parallel_bg_queries); //FIXME get ht_len from cfg - 1024); - + dht_handle = GNUNET_DHT_connect (c, + (unsigned int) max_parallel_bg_queries); if (NULL == dht_handle) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not connect to DHT!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Could not connect to DHT!\n")); + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); + return; } - if (gns_resolver_init(namestore_handle, dht_handle, zone_hash, - max_parallel_bg_queries, - ignore_pending) - == GNUNET_SYSERR) + if (GNUNET_SYSERR == + gns_resolver_init (namestore_handle, dht_handle, zone_hash, c, + max_parallel_bg_queries, + ignore_pending)) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Unable to initialize resolver!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Unable to initialize resolver!\n")); GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); return; } @@ -1053,13 +1293,14 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (c, "gns", "HIJACK_DNS")) { - GNUNET_log(GNUNET_ERROR_TYPE_INFO, - "DNS hijacking enabled... connecting to service.\n"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "DNS hijacking enabled. Connecting to DNS service.\n"); - if (gns_interceptor_init(zone_hash, zone_key, c) == GNUNET_SYSERR) + if (GNUNET_SYSERR == + gns_interceptor_init (zone_hash, zone_key, c)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Failed to enable the dns interceptor!\n"); + "Failed to enable the DNS interceptor!\n"); } } @@ -1068,19 +1309,11 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, * for our records * We have roughly an hour for all records; */ - record_put_interval = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, - 1); - zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_start, NULL); - + first_zone_iteration = GNUNET_YES; + zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, NULL); GNUNET_SERVER_add_handlers (server, handlers); - - //FIXME - //GNUNET_SERVER_disconnect_notify (server, - // &client_disconnect_notification, - // NULL); - + statistics = GNUNET_STATISTICS_create ("gns", c); nc = GNUNET_SERVER_notification_context_create (server, 1); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } diff --git a/src/gns/gnunet-service-gns_interceptor.c b/src/gns/gnunet-service-gns_interceptor.c index adb09ca..cbacc31 100644 --- a/src/gns/gnunet-service-gns_interceptor.c +++ b/src/gns/gnunet-service-gns_interceptor.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) + (C) 2009, 2010, 2011, 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 @@ -17,9 +17,7 @@ Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - /** - * * @file gns/gnunet-service-gns_interceptor.c * @brief GNUnet GNS interceptor logic * @author Martin Schanzenbach @@ -32,21 +30,25 @@ #include "gnunet-service-gns_resolver.h" #include "gns.h" -#define MAX_DNS_LABEL_LENGTH 63 - /** * Handle to a DNS intercepted * reslution request */ struct InterceptLookupHandle { - /* the request handle to reply to */ + /** + * the request handle to reply to + */ struct GNUNET_DNS_RequestHandle *request_handle; - /* the dns parser packet received */ + /** + * the dns parser packet received + */ struct GNUNET_DNSPARSER_Packet *packet; - /* the query parsed from the packet */ + /** + * the query parsed from the packet + */ struct GNUNET_DNSPARSER_Query *query; }; @@ -71,6 +73,7 @@ static struct GNUNET_CRYPTO_RsaPrivateKey *our_key; */ static struct GNUNET_TIME_Relative default_lookup_timeout; + /** * Reply to dns request with the result from our lookup. * @@ -79,10 +82,10 @@ static struct GNUNET_TIME_Relative default_lookup_timeout; * @param rd the record data */ static void -reply_to_dns(void* cls, uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +reply_to_dns (void* cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { - int i; + uint32_t i; size_t len; int ret; char *buf; @@ -120,12 +123,12 @@ reply_to_dns(void* cls, uint32_t rd_count, answer_records[i].type = rd[i].record_type; switch(rd[i].record_type) { - case GNUNET_GNS_RECORD_TYPE_NS: - case GNUNET_GNS_RECORD_TYPE_CNAME: - case GNUNET_GNS_RECORD_TYPE_PTR: + case GNUNET_GNS_RECORD_NS: + case GNUNET_GNS_RECORD_CNAME: + case GNUNET_GNS_RECORD_PTR: answer_records[i].data.hostname = (char*)rd[i].data; break; - case GNUNET_GNS_RECORD_TYPE_SOA: + case GNUNET_GNS_RECORD_SOA: answer_records[i].data.soa = (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data; break; @@ -137,7 +140,8 @@ reply_to_dns(void* cls, uint32_t rd_count, answer_records[i].data.raw.data_len = rd[i].data_size; answer_records[i].data.raw.data = (char*)rd[i].data; } - answer_records[i].expiration_time = rd[i].expiration; + GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)); + answer_records[i].expiration_time.abs_value = rd[i].expiration_time; answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn } else @@ -146,12 +150,12 @@ reply_to_dns(void* cls, uint32_t rd_count, additional_records[i].type = rd[i].record_type; switch(rd[i].record_type) { - case GNUNET_GNS_RECORD_TYPE_NS: - case GNUNET_GNS_RECORD_TYPE_CNAME: - case GNUNET_GNS_RECORD_TYPE_PTR: + case GNUNET_GNS_RECORD_NS: + case GNUNET_GNS_RECORD_CNAME: + case GNUNET_GNS_RECORD_PTR: additional_records[i].data.hostname = (char*)rd[i].data; break; - case GNUNET_GNS_RECORD_TYPE_SOA: + case GNUNET_GNS_RECORD_SOA: additional_records[i].data.soa = (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data; break; @@ -163,7 +167,8 @@ reply_to_dns(void* cls, uint32_t rd_count, additional_records[i].data.raw.data_len = rd[i].data_size; additional_records[i].data.raw.data = (char*)rd[i].data; } - additional_records[i].expiration_time = rd[i].expiration; + GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)); + additional_records[i].expiration_time.abs_value = rd[i].expiration_time; additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn } } @@ -190,23 +195,25 @@ reply_to_dns(void* cls, uint32_t rd_count, 1024, /* FIXME magic from dns redirector */ &buf, &len); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Built DNS response! (ret=%d,len=%d)\n", ret, len); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Built DNS response! (ret=%d,len=%d)\n", + ret, len); if (ret == GNUNET_OK) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Answering DNS request\n"); - GNUNET_DNS_request_answer(ilh->request_handle, - len, - buf); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Answering DNS request\n"); + GNUNET_DNS_request_answer (ilh->request_handle, + len, + buf); - GNUNET_free(buf); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Answered DNS request\n"); + GNUNET_free (buf); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Answered DNS request\n"); } else { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Error building DNS response! (ret=%d)", ret); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Error building DNS response! (ret=%d)", ret); } packet->num_answers = 0; @@ -227,8 +234,8 @@ reply_to_dns(void* cls, uint32_t rd_count, * @param q the DNS query we received parsed from p */ static void -start_resolution_for_dns(struct GNUNET_DNS_RequestHandle *request, - struct GNUNET_DNSPARSER_Packet *p, +start_resolution_for_dns (struct GNUNET_DNS_RequestHandle *request, + struct GNUNET_DNSPARSER_Packet *p, struct GNUNET_DNSPARSER_Query *q) { struct InterceptLookupHandle* ilh; @@ -236,7 +243,6 @@ start_resolution_for_dns(struct GNUNET_DNS_RequestHandle *request, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting resolution for %s (type=%d)!\n", q->name, q->type); - ilh = GNUNET_malloc(sizeof(struct InterceptLookupHandle)); ilh->packet = p; ilh->query = q; @@ -246,11 +252,11 @@ start_resolution_for_dns(struct GNUNET_DNS_RequestHandle *request, gns_resolver_lookup_record(our_zone, our_zone, q->type, q->name, our_key, default_lookup_timeout, + GNUNET_NO, &reply_to_dns, ilh); } - /** * The DNS request handler * Called for every incoming DNS request. @@ -261,17 +267,16 @@ start_resolution_for_dns(struct GNUNET_DNS_RequestHandle *request, * @param request udp payload of the DNS request */ static void -handle_dns_request(void *cls, - struct GNUNET_DNS_RequestHandle *rh, - size_t request_length, - const char *request) +handle_dns_request (void *cls, + struct GNUNET_DNS_RequestHandle *rh, + size_t request_length, + const char *request) { struct GNUNET_DNSPARSER_Packet *p; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacked a DNS request...processing\n"); - p = GNUNET_DNSPARSER_parse (request, request_length); - - if (NULL == p) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Hijacked a DNS request...processing\n"); + if (NULL == (p = GNUNET_DNSPARSER_parse (request, request_length))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received malformed DNS packet, leaving it untouched\n"); @@ -292,7 +297,7 @@ handle_dns_request(void *cls, * The way it is implemented here now is buggy and will lead to erratic * behaviour (if multiple queries are present). */ - if (p->num_queries == 0) + if (0 == p->num_queries) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No Queries in DNS packet... forwarding\n"); @@ -301,35 +306,31 @@ handle_dns_request(void *cls, return; } - if (p->num_queries > 1) - { - /* Note: We could also look for .gnunet */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - ">1 queriy in DNS packet... odd. We only process #1\n"); - } - - /** - * Check for .gnunet/.zkey + * Check for .gads/.zkey */ - if ((is_gnunet_tld(p->queries[0].name) == GNUNET_YES) || + if ((is_gads_tld(p->queries[0].name) == GNUNET_YES) || (is_zkey_tld(p->queries[0].name) == GNUNET_YES) || (strcmp(p->queries[0].name, GNUNET_GNS_TLD) == 0)) { - start_resolution_for_dns(rh, p, p->queries); - } - else - { - /** - * This request does not concern us. Forward to real DNS. - */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Request for %s is forwarded to DNS\n", p->queries[0].name); - GNUNET_DNS_request_forward (rh); - GNUNET_DNSPARSER_free_packet (p); + if (p->num_queries > 1) + { + /* Note: We could also look for .gads */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + ">1 queriy in DNS packet... odd. We only process #1\n"); + } + start_resolution_for_dns (rh, p, p->queries); + return; } - + /** + * This request does not concern us. Forward to real DNS. + */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Request for %s is forwarded to DNS\n", + p->queries[0].name); + GNUNET_DNS_request_forward (rh); + GNUNET_DNSPARSER_free_packet (p); } @@ -342,53 +343,48 @@ handle_dns_request(void *cls, * @return GNUNET_OK on success */ int -gns_interceptor_init(struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_RsaPrivateKey *key, - const struct GNUNET_CONFIGURATION_Handle *c) +gns_interceptor_init (struct GNUNET_CRYPTO_ShortHashCode zone, + struct GNUNET_CRYPTO_RsaPrivateKey *key, + const struct GNUNET_CONFIGURATION_Handle *c) { - unsigned long long default_lookup_timeout_secs = 0; - GNUNET_log(GNUNET_ERROR_TYPE_INFO, "DNS hijacking enabled... connecting to service.\n"); - our_zone = zone; our_key = key; /** * Do gnunet dns init here */ - dns_handle = GNUNET_DNS_connect(c, - GNUNET_DNS_FLAG_PRE_RESOLUTION, - &handle_dns_request, /* rh */ - NULL); /* Closure */ - - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number(c, "gns", - "DEFAULT_LOOKUP_TIMEOUT", - &default_lookup_timeout_secs)) - { - default_lookup_timeout = GNUNET_TIME_relative_multiply( - GNUNET_TIME_UNIT_SECONDS, - default_lookup_timeout_secs); - } - + dns_handle = GNUNET_DNS_connect (c, + GNUNET_DNS_FLAG_PRE_RESOLUTION, + &handle_dns_request, /* rh */ + NULL); /* Closure */ + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (c, "gns", + "DEFAULT_LOOKUP_TIMEOUT", + &default_lookup_timeout)) + default_lookup_timeout = GNUNET_TIME_UNIT_ZERO; if (NULL == dns_handle) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to the dnsservice!\n"); return GNUNET_SYSERR; } - return GNUNET_YES; } + /** * Disconnect from interceptor */ void -gns_interceptor_stop(void) +gns_interceptor_stop () { - if (dns_handle) + if (NULL != dns_handle) + { GNUNET_DNS_disconnect(dns_handle); + dns_handle = NULL; + } } /* end of gns_interceptor.c */ diff --git a/src/gns/gnunet-service-gns_interceptor.h b/src/gns/gnunet-service-gns_interceptor.h index dc39aec..613ce8c 100644 --- a/src/gns/gnunet-service-gns_interceptor.h +++ b/src/gns/gnunet-service-gns_interceptor.h @@ -1,6 +1,32 @@ +/* + This file is part of GNUnet. + (C) 2009, 2010, 2011, 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 gns/gnunet-service-gns_interceptor.h + * @brief GNUnet GNS service + * @author Martin Schanzenbach + */ #ifndef GNUNET_GNS_INTERCEPTOR_H #define GNUNET_GNS_INTERCEPTOR_H +#include "gnunet_util_lib.h" + /** * Initialize dns interceptor * @@ -10,14 +36,14 @@ * @return GNUNET_YES on success GNUNET_SYSERR on error */ int -gns_interceptor_init(struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_RsaPrivateKey *key, - const struct GNUNET_CONFIGURATION_Handle *c); +gns_interceptor_init (struct GNUNET_CRYPTO_ShortHashCode zone, + struct GNUNET_CRYPTO_RsaPrivateKey *key, + const struct GNUNET_CONFIGURATION_Handle *c); /** * Stops the interceptor */ void -gns_interceptor_stop(void); +gns_interceptor_stop (void); #endif diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c index cf12e4b..627be0b 100644 --- a/src/gns/gnunet-service-gns_resolver.c +++ b/src/gns/gnunet-service-gns_resolver.c @@ -19,8 +19,6 @@ */ /** - * - * * @file gns/gnunet-service-gns_resolver.c * @brief GNUnet GNS resolver logic * @author Martin Schanzenbach @@ -32,15 +30,28 @@ #include "gnunet_dht_service.h" #include "gnunet_namestore_service.h" #include "gnunet_dns_service.h" +#include "gnunet_resolver_service.h" #include "gnunet_dnsparser_lib.h" +#include "gns_protocol.h" #include "gnunet_gns_service.h" +#include "gns_common.h" #include "block_gns.h" #include "gns.h" #include "gnunet-service-gns_resolver.h" +#ifndef WINDOWS +#include "gnunet_vpn_service.h" +#endif + +/** + * Default DHT timeout + */ #define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT + +/** + * DHT replication level + */ #define DHT_GNS_REPLICATION_LEVEL 5 -#define MAX_DNS_LABEL_LENGTH 63 /** @@ -48,6 +59,13 @@ */ static struct GNUNET_NAMESTORE_Handle *namestore_handle; +#ifndef WINDOWS +/** + * Our handle to the vpn service + */ +static struct GNUNET_VPN_Handle *vpn_handle; +#endif + /** * Resolver handle to the dht */ @@ -59,11 +77,21 @@ static struct GNUNET_DHT_Handle *dht_handle; static struct GNUNET_CONTAINER_Heap *dht_lookup_heap; /** + * Heap for namestore queues + */ +static struct GNUNET_CONTAINER_Heap *ns_task_heap; + +/** * Maximum amount of parallel queries in background */ static unsigned long long max_allowed_background_queries; /** + * Maximum amount of parallel namestore tasks in background + */ +static unsigned long long max_allowed_ns_tasks; + +/** * Wheather or not to ignore pending records */ static int ignore_pending_records; @@ -74,11 +102,158 @@ static int ignore_pending_records; static struct GNUNET_CRYPTO_ShortHashCode local_zone; /** + * Background shortening handles + */ +static struct GetPseuAuthorityHandle *gph_head; + +/** + * Background shortening handles + */ +static struct GetPseuAuthorityHandle *gph_tail; + +/** + * Resolver lookup list + */ +static struct ResolverHandle *rlh_head; + +/** + * Resolver lookup list + */ +static struct ResolverHandle *rlh_tail; + +/** + * Resolver shorten list + */ +static struct ResolverHandle *nsh_head; + +/** + * Resolver shorten list + */ +static struct ResolverHandle *nsh_tail; + +/** + * Resolver get auth list + */ +static struct ResolverHandle *nah_head; + +/** + * Resolver get auth list + */ +static struct ResolverHandle *nah_tail; + +/** + * Global configuration. + */ +static const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** * a resolution identifier pool variable - * FIXME overflow? * This is a non critical identifier useful for debugging */ -static unsigned long long rid = 0; +static unsigned long long rid_gen; + + +/** + * Check if name is in srv format (_x._y.xxx) + * + * @param name + * @return GNUNET_YES if true + */ +static int +is_srv (const char *name) +{ + char *ndup; + int ret; + + if (*name != '_') + return GNUNET_NO; + if (NULL == strstr (name, "._")) + return GNUNET_NO; + ret = GNUNET_YES; + ndup = GNUNET_strdup (name); + strtok (ndup, "."); + if (NULL == strtok (NULL, ".")) + ret = GNUNET_NO; + if (NULL == strtok (NULL, ".")) + ret = GNUNET_NO; + if (NULL != strtok (NULL, ".")) + ret = GNUNET_NO; + GNUNET_free (ndup); + return ret; +} + + +/** + * Determine if this name is canonical (is a legal name in a zone, without delegation); + * note that we do not test that the name does not contain illegal characters, we only + * test for delegation. Note that service records (i.e. _foo._srv) are canonical names + * even though they consist of multiple labels. + * + * Examples: + * a.b.gads = not canonical + * a = canonical + * _foo._srv = canonical + * _f.bar = not canonical + * + * @param name the name to test + * @return GNUNET_YES if canonical + */ +static int +is_canonical (const char *name) +{ + const char *pos; + const char *dot; + + if (NULL == strchr (name, '.')) + return GNUNET_YES; + if ('_' != name[0]) + return GNUNET_NO; + pos = &name[1]; + while (NULL != (dot = strchr (pos, '.'))) + if ('_' != dot[1]) + return GNUNET_NO; + else + pos = dot + 1; + return GNUNET_YES; +} + + +static void +free_get_pseu_authority_handle (struct GetPseuAuthorityHandle *gph) +{ + gph->namestore_task = NULL; + GNUNET_free (gph->auth); + GNUNET_CRYPTO_rsa_key_free (gph->key); + GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph); + GNUNET_free (gph); +} + + +/** + * Callback that shortens authorities + * + * @param gph the handle containing the name to shorten + */ +static void +shorten_authority_chain (struct GetPseuAuthorityHandle *gph); + + +/** + * Continuation for pkey record creation (shorten) + * + * @param cls a GetPseuAuthorityHandle + * @param success unused + * @param emsg unused + */ +static void +create_pkey_cont (void* cls, int32_t success, const char* emsg) +{ + //FIXME do sth with error + struct GetPseuAuthorityHandle* gph = cls; + + free_get_pseu_authority_handle (gph); +} + /** * Namestore calls this function if we have record for this name. @@ -93,62 +268,46 @@ static unsigned long long rid = 0; * @param signature the signature of the authority for the record data */ static void -process_pseu_lookup_ns(void* cls, - const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, - struct GNUNET_TIME_Absolute expiration, - const char *name, unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_RsaSignature *signature) +process_pseu_lookup_ns (void* cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, + struct GNUNET_TIME_Absolute expiration, + const char *name, unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) { - struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls; + struct GetPseuAuthorityHandle* gph = cls; struct GNUNET_NAMESTORE_RecordData new_pkey; + gph->namestore_task = NULL; if (rd_count > 0) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_AUTO_PSEU: Name %s already taken in NS!\n", name); - if (0 == strcmp(gph->name, name)) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_AUTO_PSEU: Intelligent replacement not implemented\n", - name); - GNUNET_free(gph); - return; - } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_AUTO_PSEU: Trying delegated name %s\n", gph->name); - memcpy(gph->new_name, gph->name, strlen(gph->name)+1); - GNUNET_NAMESTORE_lookup_record(namestore_handle, - &gph->zone, - gph->new_name, - GNUNET_NAMESTORE_TYPE_ANY, - &process_pseu_lookup_ns, - gph); + free_get_pseu_authority_handle (gph); return; } - /** name is free */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_AUTO_PSEU: Name %s not taken in NS! Adding\n", gph->new_name); + /* name is free */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_AUTO_PSEU: Name %s not taken in NS! Adding\n", + gph->test_name); - new_pkey.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; - new_pkey.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); - new_pkey.data = &gph->new_zone; + new_pkey.expiration_time = UINT64_MAX; + new_pkey.data_size = sizeof (struct GNUNET_CRYPTO_ShortHashCode); + new_pkey.data = &gph->auth->zone; new_pkey.record_type = GNUNET_GNS_RECORD_PKEY; new_pkey.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE | GNUNET_NAMESTORE_RF_PENDING; - GNUNET_NAMESTORE_record_create (namestore_handle, - gph->key, - gph->new_name, - &new_pkey, - NULL, //cont - NULL); //cls - GNUNET_free(gph); - + gph->namestore_task = GNUNET_NAMESTORE_record_create (namestore_handle, + gph->key, + gph->test_name, + &new_pkey, + &create_pkey_cont, + gph); } + /** * process result of a dht pseu lookup * @@ -156,31 +315,33 @@ process_pseu_lookup_ns(void* cls, * @param name the pseu result or NULL */ static void -process_pseu_result(struct GetPseuAuthorityHandle* gph, char* name) +process_pseu_result (struct GetPseuAuthorityHandle* gph, + const char* name) { if (NULL == name) { - memcpy(gph->new_name, gph->name, strlen(gph->name)+1); - } - else - { - memcpy(gph->new_name, name, strlen(name)+1); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_AUTO_PSEU: No PSEU, no shorten. Finished.\n"); + free_get_pseu_authority_handle (gph); + return; } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_AUTO_PSEU: Checking %s for collision in NS\n", gph->new_name); - + + memcpy (gph->test_name, name, strlen(name) + 1); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_AUTO_PSEU: Checking %s for collision in NS\n", + gph->test_name); /** * Check for collision */ - GNUNET_NAMESTORE_lookup_record(namestore_handle, - &gph->zone, - gph->new_name, - GNUNET_NAMESTORE_TYPE_ANY, - &process_pseu_lookup_ns, - gph); + gph->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle, + &gph->our_zone, + gph->test_name, + GNUNET_NAMESTORE_TYPE_ANY, + &process_pseu_lookup_ns, + gph); } + /** * Handle timeout for dht request * @@ -188,18 +349,19 @@ process_pseu_result(struct GetPseuAuthorityHandle* gph, char* name) * @param tc the task context */ static void -handle_auth_discovery_timeout(void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +handle_auth_discovery_timeout (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls; + struct GetPseuAuthorityHandle* gph = cls; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_GET_AUTH: dht lookup for query PSEU timed out.\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_GET_AUTH: dht lookup for query PSEU timed out.\n"); GNUNET_DHT_get_stop (gph->get_handle); gph->get_handle = NULL; - process_pseu_result(gph, NULL); + process_pseu_result (gph, NULL); } + /** * Function called when we find a PSEU entry in the DHT * @@ -215,145 +377,150 @@ handle_auth_discovery_timeout(void *cls, * @param data the record data */ static void -process_auth_discovery_dht_result(void* cls, - struct GNUNET_TIME_Absolute exp, - const GNUNET_HashCode * key, - const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length, - enum GNUNET_BLOCK_Type type, - size_t size, const void *data) +process_auth_discovery_dht_result (void* cls, + struct GNUNET_TIME_Absolute exp, + const struct GNUNET_HashCode * key, + const struct GNUNET_PeerIdentity *get_path, + unsigned int get_path_length, + const struct GNUNET_PeerIdentity *put_path, + unsigned int put_path_length, + enum GNUNET_BLOCK_Type type, + size_t size, + const void *data) { - struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls; + struct GetPseuAuthorityHandle* gph = cls; struct GNSNameRecordBlock *nrb; - char* rd_data = (char*)data; + const char* rd_data = data; char* name; int num_records; size_t rd_size; int i; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_GET_AUTH: got dht result (size=%d)\n", size); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_GET_AUTH: got dht result (size=%d)\n", size); - if (data == NULL) + /* stop lookup and timeout task */ + GNUNET_DHT_get_stop (gph->get_handle); + gph->get_handle = NULL; + GNUNET_SCHEDULER_cancel (gph->timeout); + + if (NULL == data) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "GNS_GET_AUTH: got dht result null!\n", size); - GNUNET_break(0); - GNUNET_free(gph); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "GNS_GET_AUTH: got dht result null!\n", size); + free_get_pseu_authority_handle (gph); return; } nrb = (struct GNSNameRecordBlock*)data; - - /* stop lookup and timeout task */ - GNUNET_DHT_get_stop (gph->get_handle); - gph->get_handle = NULL; - GNUNET_SCHEDULER_cancel(gph->timeout); - - gph->get_handle = NULL; - - nrb = (struct GNSNameRecordBlock*)data; - name = (char*)&nrb[1]; - num_records = ntohl(nrb->rd_count); + num_records = ntohl (nrb->rd_count); { struct GNUNET_NAMESTORE_RecordData rd[num_records]; - rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); - rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); + rd_data += strlen (name) + 1 + sizeof (struct GNSNameRecordBlock); + rd_size = size - strlen (name) - 1 - sizeof (struct GNSNameRecordBlock); if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, rd_data, num_records, rd)) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "GNS_GET_AUTH: Error deserializing data!\n"); - GNUNET_break(0); - GNUNET_free(gph); - return; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "GNS_GET_AUTH: Error deserializing data!\n"); } - - for (i=0; i<num_records; i++) + else { - if ((strcmp(name, "+") == 0) && - (rd[i].record_type == GNUNET_GNS_RECORD_PSEU)) + for (i=0; i < num_records; i++) { - /* found pseu */ - process_pseu_result(gph, (char*)rd[i].data); - return; + if ((strcmp (name, GNUNET_GNS_MASTERZONE_STR) == 0) && + (rd[i].record_type == GNUNET_GNS_RECORD_PSEU)) + { + /* found pseu */ + process_pseu_result (gph, (char*)rd[i].data); + return; + } } } } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: no pseu in dht!\n"); - process_pseu_result(gph, NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_GET_AUTH: finished shorten, no results!\n"); + process_pseu_result (gph, NULL); } + +/** + * Process PSEU discovery for shorten via namestore + * + * @param cls the GetPseuAuthorityHandle + * @param key the public key + * @param expiration recorddata expiration + * @param name the looked up name + * @param rd_count number of records in set + * @param rd record data + * @param signature the signature + */ static void -process_auth_discovery_ns_result(void* cls, +process_auth_discovery_ns_result (void* cls, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, struct GNUNET_TIME_Absolute expiration, - const char *name, unsigned int rd_count, + const char *name, + unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature) { + struct GetPseuAuthorityHandle* gph = cls; + struct GNUNET_HashCode lookup_key; + unsigned int i; uint32_t xquery; - struct GNUNET_CRYPTO_ShortHashCode name_hash; - GNUNET_HashCode lookup_key; - struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string; - GNUNET_HashCode name_hash_double; - GNUNET_HashCode zone_hash_double; - int i; - struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls; + gph->namestore_task = NULL; /* no pseu found */ - if (rd_count == 0) + if (0 == rd_count) { - /** - * check dht - */ - GNUNET_CRYPTO_short_hash("+", strlen("+"), &name_hash); - GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double); - GNUNET_CRYPTO_short_hash_double (&gph->new_zone, &zone_hash_double); - GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key); - GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n", - "+", (char*)&lookup_key_string); + GNUNET_GNS_get_key_for_record (GNUNET_GNS_TLD_PLUS, &gph->auth->zone, &lookup_key); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n", + GNUNET_GNS_TLD_PLUS, + GNUNET_h2s (&lookup_key)); - gph->timeout = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT, - &handle_auth_discovery_timeout, gph); + gph->timeout = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, + &handle_auth_discovery_timeout, gph); - xquery = htonl(GNUNET_GNS_RECORD_PSEU); + xquery = htonl (GNUNET_GNS_RECORD_PSEU); - GNUNET_assert(gph->get_handle == NULL); - gph->get_handle = GNUNET_DHT_get_start(dht_handle, + GNUNET_assert (gph->get_handle == NULL); + + gph->get_handle = GNUNET_DHT_get_start (dht_handle, GNUNET_BLOCK_TYPE_GNS_NAMERECORD, &lookup_key, DHT_GNS_REPLICATION_LEVEL, - GNUNET_DHT_RO_NONE, + GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, &xquery, sizeof(xquery), &process_auth_discovery_dht_result, gph); return; } - for (i=0; i<rd_count; i++) + + for (i=0; i < rd_count; i++) { - if ((strcmp(name, "+") == 0) && - (rd[i].record_type == GNUNET_GNS_RECORD_PSEU)) - { - /* found pseu */ - process_pseu_result(gph, (char*)rd[i].data); - return; - } + if (0 != (strcmp (name, GNUNET_GNS_TLD_PLUS))) + continue; + + if (rd[i].record_type != GNUNET_GNS_RECORD_PSEU) + continue; + + /* found pseu */ + process_pseu_result (gph, (char*)rd[i].data); + return; } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: no pseu in namestore!\n"); + process_pseu_result (gph, NULL); } + /** * Callback called by namestore for a zone to name * result @@ -367,7 +534,7 @@ process_auth_discovery_ns_result(void* cls, * @param signature the signature for the record data */ static void -process_zone_to_name_discover(void *cls, +process_zone_to_name_discover (void *cls, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, struct GNUNET_TIME_Absolute expire, const char *name, @@ -375,176 +542,268 @@ process_zone_to_name_discover(void *cls, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature) { - struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls; - - /* we found a match in our own zone */ - if (rd_len != 0) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_AUTO_PSEU: name for zone in our root %s\n", name); - GNUNET_free(gph); - } - else + struct GetPseuAuthorityHandle* gph = cls; + + gph->namestore_task = NULL; + if (0 == rd_len) { - - GNUNET_NAMESTORE_lookup_record(namestore_handle, - &gph->new_zone, - "+", - GNUNET_GNS_RECORD_PSEU, - &process_auth_discovery_ns_result, - gph); + gph->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle, + &gph->auth->zone, + GNUNET_GNS_MASTERZONE_STR, + GNUNET_GNS_RECORD_PSEU, + &process_auth_discovery_ns_result, + gph); + return; } - - + /* we found a match in our own zone */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_AUTO_PSEU: name for zone in our root %s\n", name); + free_get_pseu_authority_handle (gph); } /** - * Callback for new authories + * Callback that shortens authorities * - * @param name the name given by delegation - * @param zone the authority - * @param our_zone our local zone - * @param key the private key of our authority - */ -static void process_discovered_authority(char* name, - struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_ShortHashCode our_zone, - struct GNUNET_CRYPTO_RsaPrivateKey *key) + * @param gph the handle to the shorten request + */ +static void +shorten_authority_chain (struct GetPseuAuthorityHandle *gph) { - struct GetPseuAuthorityHandle *gph; - size_t namelen; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_AUTO_PSEU: New authority %s discovered\n", - name); - - gph = GNUNET_malloc(sizeof(struct GetPseuAuthorityHandle)); - namelen = strlen(name) + 1; - memcpy(gph->name, name, namelen); - - gph->new_zone = zone; - gph->zone = our_zone; - gph->key = key; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_AUTO_PSEU: New authority %s discovered\n", + gph->auth->name); - GNUNET_NAMESTORE_zone_to_name (namestore_handle, - &our_zone, - &gph->new_zone, + gph->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + &gph->our_zone, + &gph->auth->zone, &process_zone_to_name_discover, gph); +} + +/** + * Start shortening algorithm using auth as + * authority chain + * + * @param auth the authorities that were resolved + * @param key the private key for PKEY import + */ +static void +start_shorten (struct AuthorityChain *auth, + const struct GNUNET_CRYPTO_RsaPrivateKey *key) +{ + struct GetPseuAuthorityHandle *gph; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; + struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *pb_key; + + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); + if (NULL == (pb_key = GNUNET_CRYPTO_rsa_encode_key (key))) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to encode RSA key on shorten\n"); + return; + } + gph = GNUNET_malloc (sizeof (struct GetPseuAuthorityHandle)); + gph->key = GNUNET_CRYPTO_rsa_decode_key ((const char*) pb_key, ntohs (pb_key->len)); + GNUNET_free (pb_key); + if (NULL == gph->key) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to decode RSA key on shorten\n"); + GNUNET_free (gph); + return; + } + GNUNET_CRYPTO_short_hash (&pkey, + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &gph->our_zone); + gph->auth = GNUNET_malloc (sizeof (struct AuthorityChain)); + memcpy (gph->auth, auth, sizeof (struct AuthorityChain)); + GNUNET_CONTAINER_DLL_insert (gph_head, gph_tail, gph); + shorten_authority_chain (gph); } + /** * Initialize the resolver * * @param nh the namestore handle * @param dh the dht handle * @param lz the local zone's hash + * @param c configuration handle * @param max_bg_queries maximum number of parallel background queries in dht * @param ignore_pending ignore records that still require user confirmation * on lookup * @return GNUNET_OK on success */ int -gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh, - struct GNUNET_DHT_Handle *dh, - struct GNUNET_CRYPTO_ShortHashCode lz, - unsigned long long max_bg_queries, - int ignore_pending) +gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, + struct GNUNET_DHT_Handle *dh, + struct GNUNET_CRYPTO_ShortHashCode lz, + const struct GNUNET_CONFIGURATION_Handle *c, + unsigned long long max_bg_queries, + int ignore_pending) { + if ( (NULL == nh) || + (NULL == dh) ) + return GNUNET_SYSERR; + + cfg = c; namestore_handle = nh; dht_handle = dh; local_zone = lz; dht_lookup_heap = - GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN); + GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); + ns_task_heap = + GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); max_allowed_background_queries = max_bg_queries; - ignore_pending_records = ignore_pending; - - if ((namestore_handle != NULL) && (dht_handle != NULL)) - { - return GNUNET_OK; - } - return GNUNET_SYSERR; + max_allowed_ns_tasks = GNUNET_GNS_MAX_NS_TASKS; + ignore_pending_records = ignore_pending; + GNUNET_RESOLVER_connect (cfg); + return GNUNET_OK; } /** - * Cleanup background lookups + * finish lookup * - * @param cls closure to iterator - * @param node heap nodes - * @param element the resolver handle - * @param cost heap cost - * @return always GNUNET_YES + * @param rh resolver handle + * @param rlh record lookup handle + * @param rd_count number of results + * @param rd results */ -static int -cleanup_pending_background_queries(void* cls, - struct GNUNET_CONTAINER_HeapNode *node, - void *element, - GNUNET_CONTAINER_HeapCostType cost) -{ - struct ResolverHandle *rh = (struct ResolverHandle *)element; - ResolverCleanupContinuation cont = cls; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_CLEANUP-%llu: Terminating background lookup for %s\n", - rh->id, rh->name); - GNUNET_DHT_get_stop(rh->get_handle); - rh->get_handle = NULL; - rh->proc(rh->proc_cls, rh, 0, NULL); +static void +finish_lookup (struct ResolverHandle *rh, + struct RecordLookupHandle* rlh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); - GNUNET_CONTAINER_heap_remove_node(node); - if (GNUNET_CONTAINER_heap_get_size(dht_lookup_heap) == 0) - cont(); +/** + * Helper function to free resolver handle + * + * @param rh the handle to free + */ +static void +free_resolver_handle (struct ResolverHandle* rh) +{ + struct AuthorityChain *ac; + struct AuthorityChain *ac_next; + if (NULL == rh) + return; - return GNUNET_YES; + ac_next = rh->authority_chain_head; + while (NULL != (ac = ac_next)) + { + ac_next = ac->next; + GNUNET_free (ac); + } + + if (NULL != rh->get_handle) + GNUNET_DHT_get_stop (rh->get_handle); + if (NULL != rh->dns_raw_packet) + GNUNET_free (rh->dns_raw_packet); + if (NULL != rh->namestore_task) + { + GNUNET_NAMESTORE_cancel (rh->namestore_task); + rh->namestore_task = NULL; + } + if (GNUNET_SCHEDULER_NO_TASK != rh->dns_read_task) + GNUNET_SCHEDULER_cancel (rh->dns_read_task); + if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task) + GNUNET_SCHEDULER_cancel (rh->timeout_task); + if (NULL != rh->dns_sock) + GNUNET_NETWORK_socket_close (rh->dns_sock); + if (NULL != rh->dns_resolver_handle) + GNUNET_RESOLVER_request_cancel (rh->dns_resolver_handle); + if (NULL != rh->rd.data) + GNUNET_free ((void*)(rh->rd.data)); + if (NULL != rh->dht_heap_node) + GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node); + GNUNET_free (rh); } /** - * Shutdown resolver + * finish shorten + * + * @param rh resolver handle + * @param nsh name shorten handle */ -void -gns_resolver_cleanup(ResolverCleanupContinuation cont) -{ - unsigned int s = GNUNET_CONTAINER_heap_get_size(dht_lookup_heap); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_CLEANUP: %d pending background queries to terminate\n", s); - - if (0 != s) - GNUNET_CONTAINER_heap_iterate (dht_lookup_heap, - &cleanup_pending_background_queries, - cont); - else - cont(); -} +static void +finish_shorten (struct ResolverHandle *rh, + struct NameShortenHandle *nsh); /** - * Helper function to free resolver handle + * finish get auth * - * @param rh the handle to free + * @param rh resolver handle + * @param nah get name authority handle */ static void -free_resolver_handle(struct ResolverHandle* rh) +finish_get_auth (struct ResolverHandle *rh, + struct GetNameAuthorityHandle* rlh); + + +/** + * Shutdown resolver + */ +void +gns_resolver_cleanup () { - struct AuthorityChain *ac; - struct AuthorityChain *ac_next; + struct GetPseuAuthorityHandle *tmp; + struct ResolverHandle *rh; + struct NamestoreBGTask *nbg; - if (NULL == rh) - return; + while (NULL != (tmp = gph_head)) + { + if (tmp->get_handle != NULL) + { + GNUNET_DHT_get_stop (tmp->get_handle); + tmp->get_handle = NULL; + } + if (tmp->timeout != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (tmp->timeout); + tmp->timeout = GNUNET_SCHEDULER_NO_TASK; + } + if (NULL != tmp->namestore_task) + { + GNUNET_NAMESTORE_cancel (tmp->namestore_task); + tmp->namestore_task = NULL; + } + free_get_pseu_authority_handle (tmp); + } - ac = rh->authority_chain_head; + while (NULL != rlh_head) + { + finish_lookup (rlh_head, rlh_head->proc_cls, 0, NULL); + } + while (NULL != nsh_head) + { + finish_shorten (nsh_head, nsh_head->proc_cls); + } + while (NULL != nah_head) + { + finish_get_auth (nah_head, nah_head->proc_cls); + } - while (NULL != ac) + while (NULL != (rh = GNUNET_CONTAINER_heap_remove_root(dht_lookup_heap))) { - ac_next = ac->next; - GNUNET_free(ac); - ac = ac_next; + GNUNET_free (rh); + } + GNUNET_CONTAINER_heap_destroy (dht_lookup_heap); + dht_lookup_heap = NULL; + + while (NULL != (nbg = GNUNET_CONTAINER_heap_remove_root(ns_task_heap))) + { + GNUNET_NAMESTORE_cancel (nbg->qe); + GNUNET_free (nbg); } - GNUNET_free(rh); + GNUNET_CONTAINER_heap_destroy (ns_task_heap); + ns_task_heap = NULL; + } @@ -556,10 +815,15 @@ free_resolver_handle(struct ResolverHandle* rh) * @param emsg the error message. NULL if SUCCESS==GNUNET_OK */ void -on_namestore_record_put_result(void *cls, - int32_t success, - const char *emsg) +on_namestore_record_put_result (void *cls, + int32_t success, + const char *emsg) { + struct NamestoreBGTask *nbg = cls; + + GNUNET_CONTAINER_heap_remove_node (nbg->node); + GNUNET_free (nbg); + if (GNUNET_NO == success) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, @@ -577,15 +841,26 @@ on_namestore_record_put_result(void *cls, "GNS_NS: Error putting records into namestore: %s\n", emsg); } + +/** + * Lookup timeout task + * + * @param cls the ResolverHandle for the task that timed out + * @param tc the task context + */ static void -handle_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +handle_lookup_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ResolverHandle *rh = cls; - - if (rh->timeout_cont) - rh->timeout_cont(rh->timeout_cont_cls, tc); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Lookup timeout for request %llu triggered\n", + rh->id); + if (NULL != rh->timeout_cont) + rh->timeout_cont (rh->timeout_cont_cls, tc); } + /** * Processor for background lookups in the DHT * @@ -594,16 +869,17 @@ handle_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * @param rd record data */ static void -background_lookup_result_processor(void *cls, +background_lookup_result_processor (void *cls, uint32_t rd_count, const struct GNUNET_NAMESTORE_RecordData *rd) { //We could do sth verbose/more useful here but it doesn't make any difference - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_BG: background dht lookup for finished. (%d results)\n", - rd_count); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_BG: background dht lookup finished. (%d results)\n", + rd_count); } + /** * Handle timeout for DHT requests * @@ -611,40 +887,40 @@ background_lookup_result_processor(void *cls, * @param tc the task context */ static void -dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +dht_lookup_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ResolverHandle *rh = cls; - struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls; - char new_name[MAX_DNS_NAME_LENGTH]; + struct RecordLookupHandle *rlh = rh->proc_cls; + char new_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: dht lookup for query %s (%ds)timed out.\n", - rh->id, rh->name, rh->timeout.rel_value); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: dht lookup for query %s (%llus) timed out.\n", + rh->id, rh->name, rh->timeout.rel_value); /** * Start resolution in bg */ - //strcpy(new_name, rh->name); - //memcpy(new_name+strlen(new_name), GNUNET_GNS_TLD, strlen(GNUNET_GNS_TLD)); - GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s", - rh->name, GNUNET_GNS_TLD); + GNUNET_snprintf (new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s", + rh->name, GNUNET_GNS_TLD); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Starting background lookup for %s type %d\n", - rh->id, new_name, rlh->record_type); - - gns_resolver_lookup_record(rh->authority, - rh->private_local_zone, - rlh->record_type, - new_name, - rh->priv_key, - GNUNET_TIME_UNIT_FOREVER_REL, - &background_lookup_result_processor, - NULL); - rh->timeout_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Starting background lookup for %s type %d\n", + rh->id, new_name, rlh->record_type); + gns_resolver_lookup_record (rh->authority, + rh->private_local_zone, + rlh->record_type, + new_name, + NULL, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_NO, + &background_lookup_result_processor, + NULL); + + rh->timeout_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_DHT_get_stop (rh->get_handle); rh->get_handle = NULL; - rh->proc(rh->proc_cls, rh, 0, NULL); + rh->proc (rh->proc_cls, rh, 0, NULL); } @@ -664,93 +940,79 @@ dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * @param data the record data */ static void -process_record_result_dht(void* cls, - struct GNUNET_TIME_Absolute exp, - const GNUNET_HashCode * key, - const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length, - enum GNUNET_BLOCK_Type type, - size_t size, const void *data) +process_record_result_dht (void* cls, + struct GNUNET_TIME_Absolute exp, + const struct GNUNET_HashCode * key, + const struct GNUNET_PeerIdentity *get_path, + unsigned int get_path_length, + const struct GNUNET_PeerIdentity *put_path, + unsigned int put_path_length, + enum GNUNET_BLOCK_Type type, + size_t size, const void *data) { - struct ResolverHandle *rh; - struct RecordLookupHandle *rlh; - struct GNSNameRecordBlock *nrb; + struct ResolverHandle *rh = cls; + struct RecordLookupHandle *rlh = rh->proc_cls; + const struct GNSNameRecordBlock *nrb = data; uint32_t num_records; - char* name = NULL; - char* rd_data = (char*)data; - int i; - int rd_size; - - rh = (struct ResolverHandle *)cls; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: got dht result (size=%d)\n", rh->id, size); - - if (data == NULL) - return; + const char* name; + const char* rd_data; + uint32_t i; + size_t rd_size; - //FIXME maybe check expiration here, check block type - - - rlh = (struct RecordLookupHandle *) rh->proc_cls; - nrb = (struct GNSNameRecordBlock*)data; - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: got dht result (size=%d)\n", rh->id, size); /* stop lookup and timeout task */ GNUNET_DHT_get_stop (rh->get_handle); rh->get_handle = NULL; - if (rh->dht_heap_node != NULL) { - GNUNET_CONTAINER_heap_remove_node(rh->dht_heap_node); + GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node); rh->dht_heap_node = NULL; } - if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK) { - GNUNET_SCHEDULER_cancel(rh->timeout_task); + GNUNET_SCHEDULER_cancel (rh->timeout_task); rh->timeout_task = GNUNET_SCHEDULER_NO_TASK; } - rh->get_handle = NULL; - name = (char*)&nrb[1]; - num_records = ntohl(nrb->rd_count); + name = (const char*) &nrb[1]; + num_records = ntohl (nrb->rd_count); { struct GNUNET_NAMESTORE_RecordData rd[num_records]; - - rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); - rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); - - if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, - rd_data, - num_records, - rd)) + struct NamestoreBGTask *ns_heap_root; + struct NamestoreBGTask *namestore_bg_task; + + rd_data = &name[strlen (name) + 1]; + rd_size = size - strlen (name) - 1 - sizeof (struct GNSNameRecordBlock); + if (GNUNET_SYSERR == + GNUNET_NAMESTORE_records_deserialize (rd_size, + rd_data, + num_records, + rd)) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "GNS_PHASE_REC-%d: Error deserializing data!\n", rh->id); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "GNS_PHASE_REC-%llu: Error deserializing data!\n", rh->id); + rh->proc (rh->proc_cls, rh, 0, NULL); return; } - - for (i=0; i<num_records; i++) + for (i = 0; i < num_records; i++) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Got name: %s (wanted %s)\n", - rh->id, name, rh->name); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Got type: %d\n", - rh->id, rd[i].record_type); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Got data length: %d\n", - rh->id, rd[i].data_size); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Got flag %d\n", - rh->id, rd[i].flags); - - if ((strcmp(name, rh->name) == 0) && - (rd[i].record_type == rlh->record_type)) - { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Got name: %s (wanted %s)\n", + rh->id, name, rh->name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Got type: %d (wanted %d)\n", + rh->id, rd[i].record_type, rlh->record_type); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Got data length: %d\n", + rh->id, rd[i].data_size); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Got flag %d\n", + rh->id, rd[i].flags); + + if ((strcmp (name, rh->name) == 0) && + (rd[i].record_type == rlh->record_type)) rh->answered++; - } } @@ -758,9 +1020,23 @@ process_record_result_dht(void* cls, * FIXME check pubkey against existing key in namestore? * https://gnunet.org/bugs/view.php?id=2179 */ + if (max_allowed_ns_tasks <= + GNUNET_CONTAINER_heap_get_size (ns_task_heap)) + { + ns_heap_root = GNUNET_CONTAINER_heap_remove_root (ns_task_heap); + GNUNET_NAMESTORE_cancel (ns_heap_root->qe); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Replacing oldest background ns task\n", + rh->id); + } + /* Save to namestore */ - GNUNET_NAMESTORE_record_put (namestore_handle, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Caching record for %s\n", + rh->id, name); + namestore_bg_task = GNUNET_malloc (sizeof (struct NamestoreBGTask)); + namestore_bg_task->qe = GNUNET_NAMESTORE_record_put (namestore_handle, &nrb->public_key, name, exp, @@ -768,15 +1044,16 @@ process_record_result_dht(void* cls, rd, &nrb->signature, &on_namestore_record_put_result, //cont - NULL); //cls + namestore_bg_task); - - if (rh->answered) - rh->proc(rh->proc_cls, rh, num_records, rd); + namestore_bg_task->node = GNUNET_CONTAINER_heap_insert (ns_task_heap, + namestore_bg_task, + GNUNET_TIME_absolute_get().abs_value); + if (0 < rh->answered) + rh->proc (rh->proc_cls, rh, num_records, rd); else - rh->proc(rh->proc_cls, rh, 0, NULL); + rh->proc (rh->proc_cls, rh, 0, NULL); } - } @@ -787,51 +1064,39 @@ process_record_result_dht(void* cls, * @param rh the pending gns query context */ static void -resolve_record_dht(struct ResolverHandle *rh) +resolve_record_dht (struct ResolverHandle *rh) { + struct RecordLookupHandle *rlh = rh->proc_cls; uint32_t xquery; - struct GNUNET_CRYPTO_ShortHashCode name_hash; - GNUNET_HashCode lookup_key; - GNUNET_HashCode name_hash_double; - GNUNET_HashCode zone_hash_double; - struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string; - struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls; + struct GNUNET_HashCode lookup_key; struct ResolverHandle *rh_heap_root; - - GNUNET_CRYPTO_short_hash(rh->name, strlen(rh->name), &name_hash); - GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double); - GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double); - GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key); - GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: starting dht lookup for %s with key: %s\n", - rh->id, rh->name, (char*)&lookup_key_string); - //rh->timeout_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_GNS_get_key_for_record (rh->name, &rh->authority, &lookup_key); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: starting dht lookup for %s with key: %s\n", + rh->id, rh->name, GNUNET_h2s (&lookup_key)); + rh->dht_heap_node = NULL; - if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value) + if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value != rh->timeout.rel_value) { /** * Update timeout if necessary */ - if (rh->timeout_task == GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK == rh->timeout_task) { - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Adjusting timeout\n", rh->id); - /* - * Set timeout for authority lookup phase to 1/2 - */ - rh->timeout_task = GNUNET_SCHEDULER_add_delayed( - GNUNET_TIME_relative_divide(rh->timeout, 2), - &handle_lookup_timeout, - rh); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Adjusting timeout to %s/2\n", + rh->id, + GNUNET_STRINGS_relative_time_to_string (rh->timeout, GNUNET_YES)); + /* + * Set timeout for authority lookup phase to 1/2 + */ + rh->timeout_task = GNUNET_SCHEDULER_add_delayed ( + GNUNET_TIME_relative_divide (rh->timeout, 2), + &handle_lookup_timeout, + rh); } - //rh->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, - // &dht_lookup_timeout, - // rh); rh->timeout_cont = &dht_lookup_timeout; rh->timeout_cont_cls = rh; } @@ -841,35 +1106,35 @@ resolve_record_dht(struct ResolverHandle *rh) GNUNET_CONTAINER_heap_get_size (dht_lookup_heap)) { rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap); - GNUNET_DHT_get_stop(rh_heap_root->get_handle); + GNUNET_DHT_get_stop (rh_heap_root->get_handle); rh_heap_root->get_handle = NULL; rh_heap_root->dht_heap_node = NULL; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Replacing oldest background query for %s\n", + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Replacing oldest background query for %s\n", rh->id, rh_heap_root->name); - rh_heap_root->proc(rh_heap_root->proc_cls, - rh_heap_root, - 0, - NULL); + rh_heap_root->proc (rh_heap_root->proc_cls, + rh_heap_root, + 0, + NULL); } rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap, rh, - GNUNET_TIME_absolute_get().abs_value); + GNUNET_TIME_absolute_get ().abs_value); } - - xquery = htonl(rlh->record_type); - - GNUNET_assert(rh->get_handle == NULL); - rh->get_handle = GNUNET_DHT_get_start(dht_handle, - GNUNET_BLOCK_TYPE_GNS_NAMERECORD, - &lookup_key, - DHT_GNS_REPLICATION_LEVEL, - GNUNET_DHT_RO_NONE, - &xquery, - sizeof(xquery), - &process_record_result_dht, - rh); + + xquery = htonl (rlh->record_type); + + GNUNET_assert (rh->get_handle == NULL); + rh->get_handle = GNUNET_DHT_get_start (dht_handle, + GNUNET_BLOCK_TYPE_GNS_NAMERECORD, + &lookup_key, + DHT_GNS_REPLICATION_LEVEL, + GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, + &xquery, + sizeof (xquery), + &process_record_result_dht, + rh); } @@ -887,50 +1152,43 @@ resolve_record_dht(struct ResolverHandle *rh) * @param signature the signature of the authority for the record data */ static void -process_record_result_ns(void* cls, - const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, - struct GNUNET_TIME_Absolute expiration, - const char *name, unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_RsaSignature *signature) +process_record_result_ns (void* cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, + struct GNUNET_TIME_Absolute expiration, + const char *name, unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) { - struct ResolverHandle *rh; - struct RecordLookupHandle *rlh; + struct ResolverHandle *rh = cls; + struct RecordLookupHandle *rlh = rh->proc_cls; struct GNUNET_TIME_Relative remaining_time; struct GNUNET_CRYPTO_ShortHashCode zone; + struct GNUNET_TIME_Absolute et; + unsigned int i; - rh = (struct ResolverHandle *) cls; - rlh = (struct RecordLookupHandle *)rh->proc_cls; - GNUNET_CRYPTO_short_hash(key, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &zone); + rh->namestore_task = NULL; + GNUNET_CRYPTO_short_hash (key, + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &zone); remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); - - - rh->status = 0; - - if (name != NULL) + if (NULL != name) { rh->status |= RSL_RECORD_EXISTS; + if (remaining_time.rel_value == 0) + rh->status |= RSL_RECORD_EXPIRED; } - - if (remaining_time.rel_value == 0) - { - rh->status |= RSL_RECORD_EXPIRED; - } - - if (rd_count == 0) + if (0 == rd_count) { /** * Lookup terminated and no results */ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Namestore lookup for %s terminated without results\n", - rh->id, name); + "GNS_PHASE_REC-%llu: Namestore lookup for %s terminated without results\n", + rh->id, name); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Record %s unknown in namestore\n", + "GNS_PHASE_REC-%llu: Record %s unknown in namestore\n", rh->id, rh->name); /** * Our zone and no result? Cannot resolve TT @@ -939,58 +1197,647 @@ process_record_result_ns(void* cls, return; } - else + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Processing additional result %s from namestore\n", + rh->id, name); + for (i = 0; i < rd_count;i++) { + if (rd[i].record_type != rlh->record_type) + continue; + + if (ignore_pending_records && + (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING)) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Record %s is awaiting user confirmation. Skipping\n", + rh->id, name); + continue; + } + //FIXME: eh? do I have to handle this here? + GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)); + et.abs_value = rd[i].expiration_time; + if (0 == (GNUNET_TIME_absolute_get_remaining (et)).rel_value) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: This record is expired. Skipping\n", + rh->id); + continue; + } + rh->answered++; + } + + /** + * no answers found + */ + if (0 == rh->answered) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: No answers found. This is odd!\n", rh->id); + rh->proc(rh->proc_cls, rh, 0, NULL); + return; + } + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Found %d answer(s) to query in %d records!\n", + rh->id, rh->answered, rd_count); + rh->proc(rh->proc_cls, rh, rd_count, rd); +} + + +#ifndef WINDOWS +/** + * VPN redirect result callback + * + * @param cls the resolver handle + * @param af the requested address family + * @param address in_addr(6) respectively + */ +static void +process_record_result_vpn (void* cls, int af, const void *address) +{ + struct ResolverHandle *rh = cls; + struct RecordLookupHandle *rlh = rh->proc_cls; + struct GNUNET_NAMESTORE_RecordData rd; + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC_VPN-%llu: Got answer from VPN to query!\n", + rh->id); + if (AF_INET == af) + { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Processing additional result %s from namestore\n", - rh->id, name); - int i; - for (i=0; i<rd_count;i++) + "GNS_PHASE_REC-%llu: Answer is IPv4!\n", + rh->id); + if (GNUNET_GNS_RECORD_A != rlh->record_type) { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Requested record is not IPv4!\n", + rh->id); + rh->proc (rh->proc_cls, rh, 0, NULL); + return; + } + rd.record_type = GNUNET_GNS_RECORD_A; + rd.expiration_time = UINT64_MAX; /* FIXME: should probably pick something shorter... */ + rd.data = address; + rd.data_size = sizeof (struct in_addr); + rd.flags = 0; + rh->proc (rh->proc_cls, rh, 1, &rd); + return; + } + else if (AF_INET6 == af) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Answer is IPv6!\n", + rh->id); + if (GNUNET_GNS_RECORD_AAAA != rlh->record_type) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Requested record is not IPv6!\n", + rh->id); + rh->proc (rh->proc_cls, rh, 0, NULL); + return; + } + rd.record_type = GNUNET_GNS_RECORD_AAAA; + rd.expiration_time = UINT64_MAX; /* FIXME: should probably pick something shorter... */ + rd.data = address; + rd.data_size = sizeof (struct in6_addr); + rd.flags = 0; + rh->proc (rh->proc_cls, rh, 1, &rd); + return; + } - if (rd[i].record_type != rlh->record_type) - continue; + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Got garbage from VPN!\n", + rh->id); + rh->proc (rh->proc_cls, rh, 0, NULL); +} +#endif - if (ignore_pending_records && - (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING)) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Record %s is awaiting user confirmation. Skipping\n", - rh->id, name); - continue; - } - - if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value - == 0) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: This record is expired. Skipping\n", - rh->id); - continue; - } - - rh->answered++; - + +/** + * Process VPN lookup result for record + * + * @param cls the record lookup handle + * @param rh resolver handle + * @param rd_count number of results (1) + * @param rd record data containing the result + */ +static void +handle_record_vpn (void* cls, struct ResolverHandle *rh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct RecordLookupHandle* rlh = cls; + + if (0 == rd_count) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC_VPN-%llu: VPN returned no records. (status: %d)!\n", + rh->id, + rh->status); + /* give up, cannot resolve */ + finish_lookup(rh, rlh, 0, NULL); + return; + } + + /* results found yay */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC_VPN-%llu: Record resolved from VPN!\n", + rh->id); + + finish_lookup(rh, rlh, rd_count, rd); +} + + +/** + * Sends a UDP dns query to a nameserver specified in the rh + * + * @param rh the resolver handle + */ +static void +send_dns_packet (struct ResolverHandle *rh); + + +/** + * Read DNS response + * + * @param cls the ResolverHandle for this lookup + * @param addr the sockaddr + * @param addrlen the socket address length + */ +static void +handle_dns_resolver (void *cls, + const struct sockaddr *addr, + socklen_t addrlen) +{ + struct ResolverHandle *rh = cls; + struct RecordLookupHandle *rlh = rh->proc_cls; + struct GNUNET_NAMESTORE_RecordData rd; + struct sockaddr_in *sai; + struct sockaddr_in6 *sai6; + + if (NULL == addr) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No address found in DNS!\n"); + finish_lookup (rh, rlh, 0, NULL); + return; + } + + if (sizeof (struct sockaddr_in) == addrlen) + { + sai = (struct sockaddr_in*) addr; + rd.record_type = GNUNET_GNS_RECORD_A; + rd.data_size = sizeof (struct in_addr); + rd.data = &sai->sin_addr; + } + else if (sizeof (struct sockaddr_in6) == addrlen) + { + sai6 = (struct sockaddr_in6*) addr; + rd.record_type = GNUNET_GNS_RECORD_AAAA; + rd.data_size = sizeof (struct in6_addr); + rd.data = &sai6->sin6_addr; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Address length is garbage!\n"); + finish_lookup (rh, rlh, 0, NULL); + return; + } + rd.expiration_time = UINT64_MAX; /* FIXME: should probably pick something shorter */ + rd.flags = 0; + finish_lookup (rh, rlh, 1, &rd); +} + + +/** + * Resolve DNS name via local stub resolver + * + * @param rh the resolver handle + */ +static void +resolve_dns_name (struct ResolverHandle *rh) +{ + struct RecordLookupHandle *rlh = rh->proc_cls; + int af; + + if ((GNUNET_GNS_RECORD_A != rlh->record_type) && + (GNUNET_GNS_RECORD_AAAA != rlh->record_type)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Can only resolve A/AAAA via stub... abort\n"); + finish_lookup (rh, rlh, 0, NULL); + return; + } + + if (GNUNET_GNS_RECORD_A == rlh->record_type) + af = AF_INET; + else + af = AF_INET6; + + rh->dns_resolver_handle = GNUNET_RESOLVER_ip_get (rh->dns_name, + af, + rh->timeout, + &handle_dns_resolver, + rh); +} + + +/** + * Read DNS udp packet from socket + * + * @param cls the resolver handle + * @param tc task context + */ +static void +read_dns_response (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct ResolverHandle *rh = cls; + struct RecordLookupHandle *rlh = rh->proc_cls; + char buf[UINT16_MAX]; + ssize_t r; + struct sockaddr_in addr; + socklen_t addrlen; + struct GNUNET_DNSPARSER_Packet *packet; + struct GNUNET_NAMESTORE_RecordData rd; + int found_delegation = GNUNET_NO; + int found_cname = GNUNET_NO; + char* delegation_name = NULL; + int zone_offset = 0; + int i; + + rh->dns_read_task = GNUNET_SCHEDULER_NO_TASK; + if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) + { + /* timeout or shutdown */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Terminating DNS query %d\n", tc->reason); + finish_lookup (rh, rlh, 0, NULL); + return; + } + + addrlen = sizeof (addr); + r = GNUNET_NETWORK_socket_recvfrom (rh->dns_sock, + buf, sizeof (buf), + (struct sockaddr*) &addr, + &addrlen); + + if (-1 == r) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom"); + finish_lookup (rh, rlh, 0, NULL); + return; + } + if (NULL == (packet = GNUNET_DNSPARSER_parse (buf, r))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Failed to parse DNS reply!\n"); + finish_lookup (rh, rlh, 0, NULL); + return; + } + + for (i = 0; i < packet->num_answers; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got record type %d (want %d)\n", + packet->answers[i].type, + rlh->record_type); + /* http://tools.ietf.org/html/rfc1034#section-3.6.2 */ + if (packet->answers[i].type == GNUNET_GNS_RECORD_CNAME) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CNAME... restarting query with %s\n", + packet->answers[i].data.hostname + ); + strcpy (rh->dns_name, packet->answers[i].data.hostname); + found_cname = GNUNET_YES; + continue; } - /** - * no answers found - */ - if (rh->answered == 0) + if ((packet->answers[i].type == rlh->record_type) && + (0 == strcmp (packet->answers[i].name, rh->dns_name))) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: No answers found. This is odd!\n", rh->id); - rh->proc(rh->proc_cls, rh, 0, NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Found record!\n"); + rd.data = packet->answers[i].data.raw.data; + rd.data_size = packet->answers[i].data.raw.data_len; + rd.record_type = packet->answers[i].type; + rd.flags = 0; + rd.expiration_time = packet->answers[i].expiration_time.abs_value; + finish_lookup (rh, rlh, 1, &rd); + GNUNET_DNSPARSER_free_packet (packet); return; } + } + + if (GNUNET_YES == found_cname) + { + zone_offset = strlen (rh->dns_name) - strlen (rh->dns_zone) - 1; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Found %d answer(s) to query in %d records!\n", - rh->id, rh->answered, rd_count); + if (0 > zone_offset) + zone_offset = 0; + + /* restart query with CNAME */ + if (0 == strcmp (rh->dns_name+zone_offset, rh->dns_zone)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Asking same server for %s\n", rh->dns_name); + send_dns_packet (rh); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying system resolver for %s\n", rh->dns_name); + resolve_dns_name (rh); + } + + GNUNET_DNSPARSER_free_packet (packet); + return; + } - rh->proc(rh->proc_cls, rh, rd_count, rd); + for (i = 0; i < packet->num_authority_records; i++) + { + if (packet->authority_records[i].type == GNUNET_GNS_RECORD_NS) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Found NS delegation!\n"); + found_delegation = GNUNET_YES; + delegation_name = packet->authority_records[i].data.hostname; + break; + } } + + for (i = 0; i < packet->num_additional_records; i++) + { + if (GNUNET_NO == found_delegation) + break; + + if ((packet->additional_records[i].type == GNUNET_GNS_RECORD_A) && + (0 == strcmp (packet->additional_records[i].name, delegation_name))) + { + GNUNET_assert (sizeof (struct in_addr) == + packet->authority_records[i].data.raw.data_len); + + rh->dns_addr.sin_addr = + *((struct in_addr*)packet->authority_records[i].data.raw.data); + send_dns_packet (rh); + GNUNET_DNSPARSER_free_packet (packet); + return; + } + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Nothing useful in DNS reply!\n"); + finish_lookup (rh, rlh, 0, NULL); + GNUNET_DNSPARSER_free_packet (packet); +} + + +/** + * Sends a UDP dns query to a nameserver specified in the rh + * + * @param rh the request handle + */ +static void +send_dns_packet (struct ResolverHandle *rh) +{ + struct GNUNET_NETWORK_FDSet *rset; + + rset = GNUNET_NETWORK_fdset_create (); + GNUNET_NETWORK_fdset_set (rset, rh->dns_sock); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending %d byte DNS query\n", + (int) rh->dns_raw_packet_size); + + if (GNUNET_SYSERR == + GNUNET_NETWORK_socket_sendto (rh->dns_sock, + rh->dns_raw_packet, + rh->dns_raw_packet_size, + (struct sockaddr*)&rh->dns_addr, + sizeof (struct sockaddr_in))) + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Failed to send DNS request to %s\n"), + GNUNET_a2s ((const struct sockaddr *)&rh->dns_addr, + sizeof (struct sockaddr_in))); + + rh->dns_read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, + rh->timeout, //FIXME less? + rset, + NULL, + &read_dns_response, + rh); + GNUNET_NETWORK_fdset_destroy (rset); +} + + +/** + * The final phase of resoution. + * We found a NS RR and want to resolve via DNS + * + * @param rh the pending lookup handle + * @param rd_count length of record data + * @param rd record data containing VPN RR + */ +static void +resolve_record_dns (struct ResolverHandle *rh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct RecordLookupHandle *rlh = rh->proc_cls; + struct GNUNET_DNSPARSER_Query query; + struct GNUNET_DNSPARSER_Packet packet; + struct GNUNET_DNSPARSER_Flags flags; + struct in_addr dnsip; + struct sockaddr_in addr; + struct sockaddr *sa; + unsigned int i; + + memset (&packet, 0, sizeof (struct GNUNET_DNSPARSER_Packet)); + memset (rh->dns_name, 0, sizeof (rh->dns_name)); + + /* We cancel here as to not include the ns lookup in the timeout */ + if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task) + { + GNUNET_SCHEDULER_cancel(rh->timeout_task); + rh->timeout_task = GNUNET_SCHEDULER_NO_TASK; + } + /* Start shortening */ + if ((NULL != rh->priv_key) && + (GNUNET_YES == is_canonical (rh->name))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC_DNS-%llu: Trying to shorten authority chain\n", + rh->id); + start_shorten (rh->authority_chain_head, + rh->priv_key); + } + + for (i = 0; i < rd_count; i++) + { + /* Synthesize dns name */ + if (GNUNET_GNS_RECORD_NS == rd[i].record_type) + { + strcpy (rh->dns_zone, (char*)rd[i].data); + if (0 == strcmp (rh->name, "")) + strcpy (rh->dns_name, (char*)rd[i].data); + else + sprintf (rh->dns_name, "%s.%s", rh->name, (char*)rd[i].data); + } + /* The glue */ + if (GNUNET_GNS_RECORD_A == rd[i].record_type) + /* need to use memcpy as .data may be unaligned */ + memcpy (&dnsip, rd[i].data, sizeof (dnsip)); + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC_DNS-%llu: Looking up %s from %s\n", + rh->id, + rh->dns_name, + inet_ntoa (dnsip)); + rh->dns_sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0); + if (NULL == rh->dns_sock) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC_DNS-%llu: Error creating udp socket for dns!\n", + rh->id); + finish_lookup (rh, rlh, 0, NULL); + return; + } + + memset (&addr, 0, sizeof (struct sockaddr_in)); + sa = (struct sockaddr *) &addr; + sa->sa_family = AF_INET; + if (GNUNET_OK != GNUNET_NETWORK_socket_bind (rh->dns_sock, + sa, + sizeof (struct sockaddr_in))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC_DNS-%llu: Error binding udp socket for dns!\n", + rh->id); + finish_lookup (rh, rlh, 0, NULL); + return; + } + query.name = rh->dns_name; + query.type = rlh->record_type; + query.class = GNUNET_DNSPARSER_CLASS_INTERNET; + memset (&flags, 0, sizeof (flags)); + flags.recursion_desired = 1; + flags.checking_disabled = 1; + packet.queries = &query; + packet.answers = NULL; + packet.authority_records = NULL; + packet.num_queries = 1; + packet.num_answers = 0; + packet.num_authority_records = 0; + packet.num_additional_records = 0; + packet.flags = flags; + packet.id = rh->id; + if (GNUNET_OK != GNUNET_DNSPARSER_pack (&packet, + UINT16_MAX, + &rh->dns_raw_packet, + &rh->dns_raw_packet_size)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC_DNS-%llu: Creating raw dns packet!\n", + rh->id); + GNUNET_NETWORK_socket_close (rh->dns_sock); + finish_lookup (rh, rlh, 0, NULL); + return; + } + + rh->dns_addr.sin_family = AF_INET; + rh->dns_addr.sin_port = htons (53); //domain + rh->dns_addr.sin_addr = dnsip; +#if HAVE_SOCKADDR_IN_SIN_LEN + rh->dns_addr.sin_len = (u_char) sizeof (struct sockaddr_in); +#endif + send_dns_packet (rh); +} + + +/** + * The final phase of resoution. + * We found a VPN RR and want to request an IPv4/6 address + * + * @param rh the pending lookup handle + * @param rd_count length of record data + * @param rd record data containing VPN RR + */ +static void +resolve_record_vpn (struct ResolverHandle *rh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct RecordLookupHandle *rlh = rh->proc_cls; + struct GNUNET_HashCode serv_desc; + struct vpn_data* vpn; + int af; + + /* We cancel here as to not include the ns lookup in the timeout */ + if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task) + { + GNUNET_SCHEDULER_cancel(rh->timeout_task); + rh->timeout_task = GNUNET_SCHEDULER_NO_TASK; + } + /* Start shortening */ + if ((NULL != rh->priv_key) && + (GNUNET_YES == is_canonical (rh->name))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC_VPN-%llu: Trying to shorten authority chain\n", + rh->id); + start_shorten (rh->authority_chain_head, + rh->priv_key); + } + + vpn = (struct vpn_data*)rd->data; + GNUNET_CRYPTO_hash ((char*)&vpn[1], + strlen ((char*)&vpn[1]) + 1, + &serv_desc); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC_VPN-%llu: proto %hu peer %s!\n", + rh->id, + ntohs (vpn->proto), + GNUNET_h2s (&vpn->peer)); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC_VPN-%llu: service %s -> %s!\n", + rh->id, + (char*)&vpn[1], + GNUNET_h2s (&serv_desc)); + rh->proc = &handle_record_vpn; + if (GNUNET_GNS_RECORD_A == rlh->record_type) + af = AF_INET; + else + af = AF_INET6; +#ifndef WINDOWS + if (NULL == vpn_handle) + { + vpn_handle = GNUNET_VPN_connect (cfg); + if (NULL == vpn_handle) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_INIT: Error connecting to VPN!\n"); + finish_lookup (rh, rh->proc_cls, 0, NULL); + return; + } + } + + rh->vpn_handle = GNUNET_VPN_redirect_to_peer (vpn_handle, + af, ntohs (vpn->proto), + (struct GNUNET_PeerIdentity *)&vpn->peer, + &serv_desc, + GNUNET_NO, //nac + GNUNET_TIME_UNIT_FOREVER_ABS, //FIXME + &process_record_result_vpn, + rh); +#else + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Error connecting to VPN (not available on W32 yet)\n"); + finish_lookup (rh, rh->proc_cls, 0, NULL); +#endif } @@ -999,19 +1846,29 @@ process_record_result_ns(void* cls, * rh->name is a name that is canonical and we do not have a delegation. * Query namestore for this record * - * @param rh the pending lookup + * @param rh the pending lookup handle */ static void resolve_record_ns(struct ResolverHandle *rh) { - struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls; + struct RecordLookupHandle *rlh = rh->proc_cls; /* We cancel here as to not include the ns lookup in the timeout */ - if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task) { GNUNET_SCHEDULER_cancel(rh->timeout_task); rh->timeout_task = GNUNET_SCHEDULER_NO_TASK; } + /* Start shortening */ + if ((NULL != rh->priv_key) && + (GNUNET_YES == is_canonical (rh->name))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Trying to shorten authority chain\n", + rh->id); + start_shorten (rh->authority_chain_head, + rh->priv_key); + } /** * Try to resolve this record in our namestore. @@ -1019,7 +1876,7 @@ resolve_record_ns(struct ResolverHandle *rh) * since we tried to resolve it to an authority * and failed. **/ - GNUNET_NAMESTORE_lookup_record(namestore_handle, + rh->namestore_task = GNUNET_NAMESTORE_lookup_record(namestore_handle, &rh->authority, rh->name, rlh->record_type, @@ -1028,7 +1885,6 @@ resolve_record_ns(struct ResolverHandle *rh) } - /** * Handle timeout for DHT requests * @@ -1036,66 +1892,84 @@ resolve_record_ns(struct ResolverHandle *rh) * @param tc the task context */ static void -dht_authority_lookup_timeout(void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +dht_authority_lookup_timeout (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ResolverHandle *rh = cls; struct RecordLookupHandle *rlh = rh->proc_cls; - char new_name[MAX_DNS_NAME_LENGTH]; + char new_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_DHT-%llu: dht lookup for query %s (%ds)timed out.\n", - rh->id, rh->authority_name, rh->timeout.rel_value); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_DHT-%llu: dht lookup for query %s (%llus) timed out.\n", + rh->id, rh->authority_name, + rh->timeout.rel_value); rh->status |= RSL_TIMED_OUT; - rh->timeout_task = GNUNET_SCHEDULER_NO_TASK; - - GNUNET_DHT_get_stop (rh->get_handle); - rh->get_handle = NULL; - - if (strcmp(rh->name, "") == 0) + if (NULL != rh->get_handle) + { + GNUNET_DHT_get_stop (rh->get_handle); + rh->get_handle = NULL; + } + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_DHT-%llu: Got shutdown\n", + rh->id); + rh->proc (rh->proc_cls, rh, 0, NULL); + return; + } + if (0 == strcmp (rh->name, "")) { /* * promote authority back to name and try to resolve record */ - strcpy(rh->name, rh->authority_name); - rh->proc(rh->proc_cls, rh, 0, NULL); + strcpy (rh->name, rh->authority_name); + rh->proc (rh->proc_cls, rh, 0, NULL); return; } /** * Start resolution in bg */ - GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, - "%s.%s.%s", rh->name, rh->authority_name, GNUNET_GNS_TLD); - //strcpy(new_name, rh->name); - //strcpy(new_name+strlen(new_name), "."); - //memcpy(new_name+strlen(new_name), GNUNET_GNS_TLD, strlen(GNUNET_GNS_TLD)); - - strcpy(rh->name, new_name); + GNUNET_snprintf (new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, + "%s.%s.%s", + rh->name, rh->authority_name, GNUNET_GNS_TLD); + strcpy (rh->name, new_name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_DHT-%llu: Starting background query for %s type %d\n", + rh->id, rh->name, + rlh->record_type); + gns_resolver_lookup_record (rh->authority, + rh->private_local_zone, + rlh->record_type, + new_name, + NULL, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_NO, + &background_lookup_result_processor, + NULL); + rh->proc (rh->proc_cls, rh, 0, NULL); +} - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_DHT-%llu: Starting background query for %s type %d\n", - rh->id, rh->name, rlh->record_type); - - gns_resolver_lookup_record(rh->authority, - rh->private_local_zone, - rlh->record_type, - new_name, - rh->priv_key, - GNUNET_TIME_UNIT_FOREVER_REL, - &background_lookup_result_processor, - NULL); - rh->proc(rh->proc_cls, rh, 0, NULL); -} +/** + * Start DHT lookup for a name -> PKEY (compare NS) record in + * rh->authority's zone + * + * @param rh the pending gns query + */ +static void +resolve_delegation_dht (struct ResolverHandle *rh); -/* Prototype */ -static void resolve_delegation_dht(struct ResolverHandle *rh); -/* Prototype */ -static void resolve_delegation_ns(struct ResolverHandle *rh); +/** + * Resolve the delegation chain for the request in our namestore + * + * @param rh the resolver handle + */ +static void +resolve_delegation_ns (struct ResolverHandle *rh); /** @@ -1107,9 +1981,122 @@ static void resolve_delegation_ns(struct ResolverHandle *rh); * @param rd record data (always NULL) */ static void -handle_delegation_ns(void* cls, struct ResolverHandle *rh, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd); +handle_delegation_ns (void* cls, struct ResolverHandle *rh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); + + +/** + * This is a callback function that checks for key revocation + * + * @param cls the pending query + * @param key the key of the zone we did the lookup + * @param expiration expiration date of the record data set in the namestore + * @param name the name for which we need an authority + * @param rd_count the number of records with 'name' + * @param rd the record data + * @param signature the signature of the authority for the record data + */ +static void +process_pkey_revocation_result_ns (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, + struct GNUNET_TIME_Absolute expiration, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct ResolverHandle *rh = cls; + struct GNUNET_TIME_Relative remaining_time; + int i; + + rh->namestore_task = NULL; + remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); + + for (i = 0; i < rd_count; i++) + { + if (GNUNET_GNS_RECORD_REV == rd[i].record_type) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_REV-%llu: Zone has been revoked.\n", + rh->id); + rh->status |= RSL_PKEY_REVOKED; + rh->proc (rh->proc_cls, rh, 0, NULL); + return; + } + } + + if ((NULL == name) || + (0 == remaining_time.rel_value)) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_REV-%llu: + Records don't exist or are expired.\n", + rh->id, name); + + if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value != rh->timeout.rel_value) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_REV-%llu: Starting background lookup for %s type %d\n", + rh->id, "+.gads", GNUNET_GNS_RECORD_REV); + + gns_resolver_lookup_record(rh->authority, + rh->private_local_zone, + GNUNET_GNS_RECORD_REV, + GNUNET_GNS_TLD, + NULL, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_NO, + &background_lookup_result_processor, + NULL); + } + } + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_REV-%llu: Revocation check passed\n", + rh->id); + /** + * We are done with PKEY resolution if name is empty + * else resolve again with new authority + */ + if (strcmp (rh->name, "") == 0) + rh->proc (rh->proc_cls, rh, rh->rd_count, &rh->rd); + else + resolve_delegation_ns (rh); +} + + +/** + * Callback when record data is put into namestore + * + * @param cls the closure + * @param success GNUNET_OK on success + * @param emsg the error message. NULL if SUCCESS==GNUNET_OK + */ +void +on_namestore_delegation_put_result(void *cls, + int32_t success, + const char *emsg) +{ + struct NamestoreBGTask *nbg = cls; + + GNUNET_CONTAINER_heap_remove_node (nbg->node); + GNUNET_free (nbg); + + if (GNUNET_NO == success) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_NS: records already in namestore\n"); + return; + } + else if (GNUNET_YES == success) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_NS: records successfully put in namestore\n"); + return; + } + + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "GNS_NS: Error putting records into namestore: %s\n", emsg); +} /** @@ -1129,41 +2116,33 @@ handle_delegation_ns(void* cls, struct ResolverHandle *rh, * @param data the record data */ static void -process_delegation_result_dht(void* cls, - struct GNUNET_TIME_Absolute exp, - const GNUNET_HashCode * key, - const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length, - enum GNUNET_BLOCK_Type type, - size_t size, const void *data) +process_delegation_result_dht (void* cls, + struct GNUNET_TIME_Absolute exp, + const struct GNUNET_HashCode * key, + const struct GNUNET_PeerIdentity *get_path, + unsigned int get_path_length, + const struct GNUNET_PeerIdentity *put_path, + unsigned int put_path_length, + enum GNUNET_BLOCK_Type type, + size_t size, const void *data) { - struct ResolverHandle *rh; - struct GNSNameRecordBlock *nrb; + struct ResolverHandle *rh = cls; + const struct GNSNameRecordBlock *nrb = data; + const char* rd_data; uint32_t num_records; - char* name = NULL; - char* rd_data = (char*) data; - int i; + const char* name; + uint32_t i; int rd_size; - struct GNUNET_CRYPTO_ShortHashCode zone, name_hash; - GNUNET_HashCode zone_hash_double, name_hash_double; - - rh = (struct ResolverHandle *)cls; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_DHT-%llu: Got DHT result\n", rh->id); + struct GNUNET_CRYPTO_ShortHashCode zone; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_DHT-%llu: Got DHT result\n", + rh->id); if (data == NULL) return; - - nrb = (struct GNSNameRecordBlock*)data; - - /* stop dht lookup and timeout task */ + /* stop dht lookup and timeout task */ GNUNET_DHT_get_stop (rh->get_handle); - rh->get_handle = NULL; - if (rh->dht_heap_node != NULL) { GNUNET_CONTAINER_heap_remove_node(rh->dht_heap_node); @@ -1171,13 +2150,14 @@ process_delegation_result_dht(void* cls, } num_records = ntohl(nrb->rd_count); - name = (char*)&nrb[1]; + name = (const char*) &nrb[1]; { struct GNUNET_NAMESTORE_RecordData rd[num_records]; + struct NamestoreBGTask *ns_heap_root; + struct NamestoreBGTask *namestore_bg_task; - rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); - rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); - + rd_data = name + strlen(name) + 1; + rd_size = size - strlen(name) - 1 - sizeof (struct GNSNameRecordBlock); if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, rd_data, num_records, @@ -1194,10 +2174,9 @@ process_delegation_result_dht(void* cls, rh->id, name, rh->authority_name); for (i=0; i<num_records; i++) { - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n", - rh->id, name, rh->authority_name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n", + rh->id, name, rh->authority_name); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_PHASE_DELEGATE_DHT-%llu: Got type: %d (wanted %d)\n", rh->id, rd[i].record_type, GNUNET_GNS_RECORD_PKEY); @@ -1207,9 +2186,25 @@ process_delegation_result_dht(void* cls, GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_PHASE_DELEGATE_DHT-%llu: Got flag %d\n", rh->id, rd[i].flags); + + if ((GNUNET_GNS_RECORD_VPN == rd[i].record_type) || + (GNUNET_GNS_RECORD_NS == rd[i].record_type) || + (GNUNET_GNS_RECORD_CNAME == rd[i].record_type)) + { + /** + * This is a VPN,NS,CNAME entry. Let namestore handle this after caching + */ + if (0 == strcmp(rh->name, "")) + strcpy(rh->name, rh->authority_name); + else + GNUNET_snprintf(rh->name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s", + rh->name, rh->authority_name); //FIXME ret + rh->answered = 1; + break; + } - if ((strcmp(name, rh->authority_name) == 0) && - (rd[i].record_type == GNUNET_GNS_RECORD_PKEY)) + if ((0 == strcmp(name, rh->authority_name)) && + (GNUNET_GNS_RECORD_PKEY == rd[i].record_type)) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_PHASE_DELEGATE_DHT-%llu: Authority found in DHT\n", @@ -1225,38 +2220,60 @@ process_delegation_result_dht(void* cls, rh->authority_chain_tail, auth); + if (NULL != rh->rd.data) + GNUNET_free ((void*)rh->rd.data); + + memcpy (&rh->rd, &rd[i], sizeof (struct GNUNET_NAMESTORE_RecordData)); + rh->rd.data = GNUNET_malloc (rd[i].data_size); + memcpy ((void*)(rh->rd.data), rd[i].data, rd[i].data_size); + rh->rd_count = 1; + /** try to import pkey if private key available */ - if (rh->priv_key) - process_discovered_authority(name, auth->zone, - rh->authority_chain_tail->zone, - rh->priv_key); + //if (rh->priv_key && is_canonical (rh->name)) + // process_discovered_authority(name, auth->zone, + // rh->authority_chain_tail->zone, + // rh->priv_key); } } + GNUNET_GNS_get_zone_from_key (name, key, &zone); - GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash); - GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double); - GNUNET_CRYPTO_hash_xor(key, &name_hash_double, &zone_hash_double); - GNUNET_CRYPTO_short_hash_from_truncation (&zone_hash_double, &zone); - - /* Save to namestore */ - if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_tail->zone, + /* Save to namestore + if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, &zone)) - { - GNUNET_NAMESTORE_record_put (namestore_handle, + {*/ + if (max_allowed_ns_tasks <= + GNUNET_CONTAINER_heap_get_size (ns_task_heap)) + { + ns_heap_root = GNUNET_CONTAINER_heap_remove_root (ns_task_heap); + GNUNET_NAMESTORE_cancel (ns_heap_root->qe); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_DHT-%llu: Replacing oldest background ns task\n", + rh->id); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_DHT-%llu: Caching record for %s\n", + rh->id, name); + namestore_bg_task = GNUNET_malloc (sizeof (struct NamestoreBGTask)); + + namestore_bg_task->node = GNUNET_CONTAINER_heap_insert (ns_task_heap, + namestore_bg_task, + GNUNET_TIME_absolute_get().abs_value); + namestore_bg_task->qe = GNUNET_NAMESTORE_record_put (namestore_handle, &nrb->public_key, name, exp, num_records, rd, &nrb->signature, - &on_namestore_record_put_result, //cont - NULL); //cls + &on_namestore_delegation_put_result, //cont + namestore_bg_task); //cls } - } - - if (rh->answered) + //} + + if (0 != rh->answered) { rh->answered = 0; /** @@ -1264,17 +2281,34 @@ process_delegation_result_dht(void* cls, * FIXME in this case. should we ask namestore again? */ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_DHT-%llu: Answer from DHT for %s. Yet to resolve: %s\n", - rh->id, rh->authority_name, rh->name); - if (strcmp(rh->name, "") == 0) + "GNS_PHASE_DELEGATE_DHT-%llu: Answer from DHT for %s. Yet to resolve: %s\n", + rh->id, rh->authority_name, rh->name); + + if (0 == strcmp(rh->name, "")) { - rh->proc(rh->proc_cls, rh, 0, NULL); + /* Start shortening */ + if ((NULL != rh->priv_key) && + (GNUNET_YES == is_canonical (rh->name))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_DHT-%llu: Trying to shorten authority chain\n", + rh->id); + start_shorten (rh->authority_chain_head, + rh->priv_key); + } } else - { rh->proc = &handle_delegation_ns; - resolve_delegation_ns(rh); - } + + + /* Check for key revocation and delegate */ + rh->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle, + &rh->authority, + GNUNET_GNS_MASTERZONE_STR, + GNUNET_GNS_RECORD_REV, + &process_pkey_revocation_result_ns, + rh); + return; } @@ -1285,96 +2319,119 @@ process_delegation_result_dht(void* cls, GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_PHASE_DELEGATE_DHT-%llu: Adding %s back to %s\n", rh->id, rh->authority_name, rh->name); - if (strcmp(rh->name, "") == 0) + if (0 == strcmp(rh->name, "")) strcpy(rh->name, rh->authority_name); else - GNUNET_snprintf(rh->name, MAX_DNS_NAME_LENGTH, "%s.%s", + GNUNET_snprintf(rh->name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s", rh->name, rh->authority_name); //FIXME ret GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_PHASE_DELEGATE_DHT-%llu: %s restored\n", rh->id, rh->name); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_DHT-%llu: DHT authority lookup found no match!\n", + "GNS_PHASE_DELEGATE_DHT-%llu: DHT authority lookup found no match!\n", rh->id); rh->proc(rh->proc_cls, rh, 0, NULL); } +//FIXME maybe define somewhere else? #define MAX_SOA_LENGTH sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)\ - +(MAX_DNS_NAME_LENGTH*2) -#define MAX_MX_LENGTH sizeof(uint16_t)+MAX_DNS_NAME_LENGTH + +(GNUNET_DNSPARSER_MAX_NAME_LENGTH*2) +#define MAX_MX_LENGTH sizeof(uint16_t)+GNUNET_DNSPARSER_MAX_NAME_LENGTH +#define MAX_SRV_LENGTH (sizeof(uint16_t)*3)+GNUNET_DNSPARSER_MAX_NAME_LENGTH +/** + * Exands a name ending in .+ with the zone of origin. + * FIXME: funky api: 'dest' must be large enough to hold + * the result; this is a bit yucky... + * + * @param dest destination buffer + * @param src the .+ name + * @param repl the string to replace the + with + */ static void -expand_plus(char** dest, char* src, char* repl) +expand_plus (char* dest, + const char* src, + const char* repl) { char* pos; - unsigned int s_len = strlen(src)+1; + size_t s_len = strlen (src) + 1; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_POSTPROCESS: Got %s to expand with %s\n", src, repl); - - if (s_len < 3) + //Eh? I guess this is at least strlen ('x.+') == 3 FIXME + if (3 > s_len) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_POSTPROCESS: %s to short\n", src); - /* no postprocessing */ - memcpy(*dest, src, s_len+1); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_POSTPROCESS: %s too short\n", src); + memcpy (dest, src, s_len); return; } - - if (0 == strcmp(src+s_len-3, ".+")) + if (0 == strcmp (src + s_len - 3, ".+")) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_POSTPROCESS: Expanding .+ in %s\n", src); - memset(*dest, 0, s_len+strlen(repl)+strlen(GNUNET_GNS_TLD)); - strcpy(*dest, src); - pos = *dest+s_len-2; - strcpy(pos, repl); - pos += strlen(repl); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_POSTPROCESS: Expanded to %s\n", *dest); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_POSTPROCESS: Expanding .+ in %s\n", + src); + memset (dest, 0, s_len + strlen (repl) + strlen(GNUNET_GNS_TLD)); + strcpy (dest, src); + pos = dest + s_len - 2; + strcpy (pos, repl); + pos += strlen (repl); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_POSTPROCESS: Expanded to %s\n", + dest); } else { - memcpy(*dest, src, s_len+1); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_POSTPROCESS: No postprocessing for %s\n", src); + memcpy (dest, src, s_len); } } + /** * finish lookup */ static void -finish_lookup(struct ResolverHandle *rh, - struct RecordLookupHandle* rlh, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +finish_lookup (struct ResolverHandle *rh, + struct RecordLookupHandle* rlh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { - int i; - char new_rr_data[MAX_DNS_NAME_LENGTH]; + unsigned int i; + char new_rr_data[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; char new_mx_data[MAX_MX_LENGTH]; char new_soa_data[MAX_SOA_LENGTH]; + char new_srv_data[MAX_SRV_LENGTH]; + struct srv_data *old_srv; + struct srv_data *new_srv; + struct soa_data *old_soa; + struct soa_data *new_soa; struct GNUNET_NAMESTORE_RecordData p_rd[rd_count]; char* repl_string; char* pos; unsigned int offset; - if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task) { GNUNET_SCHEDULER_cancel(rh->timeout_task); rh->timeout_task = GNUNET_SCHEDULER_NO_TASK; } - if (rd_count > 0) + GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh); + + if (0 < rd_count) memcpy(p_rd, rd, rd_count*sizeof(struct GNUNET_NAMESTORE_RecordData)); for (i = 0; i < rd_count; i++) { - if (rd[i].record_type != GNUNET_GNS_RECORD_TYPE_NS && - rd[i].record_type != GNUNET_GNS_RECORD_TYPE_CNAME && - rd[i].record_type != GNUNET_GNS_RECORD_MX && - rd[i].record_type != GNUNET_GNS_RECORD_TYPE_SOA) + if ((GNUNET_GNS_RECORD_NS != rd[i].record_type) && + (GNUNET_GNS_RECORD_PTR != rd[i].record_type) && + (GNUNET_GNS_RECORD_CNAME != rd[i].record_type) && + (GNUNET_GNS_RECORD_MX != rd[i].record_type) && + (GNUNET_GNS_RECORD_SOA != rd[i].record_type) && + (GNUNET_GNS_RECORD_SRV != rd[i].record_type)) { p_rd[i].data = rd[i].data; continue; @@ -1388,43 +2445,63 @@ finish_lookup(struct ResolverHandle *rh, GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_POSTPROCESS: Postprocessing\n"); - - if (strcmp(rh->name, "+") == 0) + if (0 == strcmp(rh->name, GNUNET_GNS_MASTERZONE_STR)) repl_string = rlh->name; else repl_string = rlh->name+strlen(rh->name)+1; offset = 0; - if (rd[i].record_type == GNUNET_GNS_RECORD_MX) + if (GNUNET_GNS_RECORD_MX == rd[i].record_type) { - memcpy(new_mx_data, (char*)rd[i].data, sizeof(uint16_t)); - offset = sizeof(uint16_t); - pos = new_mx_data+offset; - expand_plus(&pos, (char*)rd[i].data+sizeof(uint16_t), - repl_string); - offset += strlen(new_mx_data+sizeof(uint16_t))+1; + memcpy (new_mx_data, (char*)rd[i].data, sizeof(uint16_t)); + offset = sizeof (uint16_t); + pos = new_mx_data + offset; + // FIXME: how do we know that 'pos' has enough space for the new name? + expand_plus (pos, (char*)rd[i].data+sizeof(uint16_t), + repl_string); + offset += strlen(new_mx_data+sizeof(uint16_t)) + 1; p_rd[i].data = new_mx_data; p_rd[i].data_size = offset; } - else if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_SOA) + else if (GNUNET_GNS_RECORD_SRV == rd[i].record_type) + { + /* + * Prio, weight and port + */ + new_srv = (struct srv_data*)new_srv_data; + old_srv = (struct srv_data*)rd[i].data; + new_srv->prio = old_srv->prio; + new_srv->weight = old_srv->weight; + new_srv->port = old_srv->port; + // FIXME: how do we know that '&new_srv[1]' has enough space for the new name? + expand_plus((char*)&new_srv[1], (char*)&old_srv[1], + repl_string); + p_rd[i].data = new_srv_data; + p_rd[i].data_size = sizeof (struct srv_data) + strlen ((char*)&new_srv[1]) + 1; + } + else if (GNUNET_GNS_RECORD_SOA == rd[i].record_type) { /* expand mname and rname */ - pos = new_soa_data; - expand_plus(&pos, (char*)rd[i].data, repl_string); - offset = strlen(new_soa_data)+1; - pos = new_soa_data+offset; - expand_plus(&pos, (char*)rd[i].data+offset, repl_string); - offset += strlen(new_soa_data+offset)+1; - /* cpy the 4 numbers serial refresh retry and expire */ - memcpy(new_soa_data+offset, (char*)rd[i].data+offset, sizeof(uint32_t)*5); - offset += sizeof(uint32_t)*5; - p_rd[i].data_size = offset; + old_soa = (struct soa_data*)rd[i].data; + new_soa = (struct soa_data*)new_soa_data; + memcpy (new_soa, old_soa, sizeof (struct soa_data)); + // FIXME: how do we know that 'new_soa[1]' has enough space for the new name? + expand_plus((char*)&new_soa[1], (char*)&old_soa[1], repl_string); + offset = strlen ((char*)&new_soa[1]) + 1; + // FIXME: how do we know that 'new_soa[1]' has enough space for the new name? + expand_plus((char*)&new_soa[1] + offset, + (char*)&old_soa[1] + strlen ((char*)&old_soa[1]) + 1, + repl_string); + p_rd[i].data_size = sizeof (struct soa_data) + + offset + + strlen ((char*)&new_soa[1] + offset); p_rd[i].data = new_soa_data; } else { pos = new_rr_data; - expand_plus(&pos, (char*)rd[i].data, repl_string); + // FIXME: how do we know that 'rd[i].data' has enough space for the new name? + expand_plus(pos, (char*)rd[i].data, repl_string); p_rd[i].data_size = strlen(new_rr_data)+1; p_rd[i].data = new_rr_data; } @@ -1433,9 +2510,10 @@ finish_lookup(struct ResolverHandle *rh, rlh->proc(rlh->proc_cls, rd_count, p_rd); GNUNET_free(rlh); - + free_resolver_handle (rh); } + /** * Process DHT lookup result for record. * @@ -1445,31 +2523,25 @@ finish_lookup(struct ResolverHandle *rh, * @param rd record data */ static void -handle_record_dht(void* cls, struct ResolverHandle *rh, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +handle_record_dht (void* cls, struct ResolverHandle *rh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { - struct RecordLookupHandle* rlh; + struct RecordLookupHandle* rlh = cls; - rlh = (struct RecordLookupHandle*)cls; - if (rd_count == 0) + if (0 == rd_count) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: No records for %s found in DHT. Aborting\n", + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: No records for %s found in DHT. Aborting\n", rh->id, rh->name); /* give up, cannot resolve */ - finish_lookup(rh, rlh, 0, NULL); - free_resolver_handle(rh); + finish_lookup (rh, rlh, 0, NULL); return; } - /* results found yay */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Record resolved from DHT!", rh->id); - - finish_lookup(rh, rlh, rd_count, rd); - free_resolver_handle(rh); - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Record resolved from DHT!", rh->id); + finish_lookup (rh, rlh, rd_count, rd); } @@ -1482,105 +2554,103 @@ handle_record_dht(void* cls, struct ResolverHandle *rh, * @param rd record data */ static void -handle_record_ns(void* cls, struct ResolverHandle *rh, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +handle_record_ns (void* cls, struct ResolverHandle *rh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { - struct RecordLookupHandle* rlh; - rlh = (struct RecordLookupHandle*) cls; - if (rd_count == 0) + struct RecordLookupHandle* rlh = cls; + int check_dht = GNUNET_YES; + + if (0 != rd_count) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: NS returned no records. (status: %d)!\n", - rh->id, - rh->status); - - /** - * There are 4 conditions that have to met for us to consult the DHT: - * 1. The entry in the DHT is RSL_RECORD_EXPIRED AND - * 2. No entry in the NS existed AND - * 3. The zone queried is not the local resolver's zone AND - * 4. The name that was looked up is '+' - * because if it was any other canonical name we either already queried - * the DHT for the authority in the authority lookup phase (and thus - * would already have an entry in the NS for the record) - */ - if (rh->status & (RSL_RECORD_EXPIRED | !RSL_RECORD_EXISTS) && - GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - &rh->private_local_zone) && - (strcmp(rh->name, "+") == 0)) - { - rh->proc = &handle_record_dht; - resolve_record_dht(rh); - return; - } - /* give up, cannot resolve */ - finish_lookup(rh, rlh, 0, NULL); - free_resolver_handle(rh); + /* results found yay */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Record resolved from namestore!\n", rh->id); + finish_lookup (rh, rlh, rd_count, rd); return; } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: NS returned no records. (status: %d)!\n", + rh->id, + rh->status); + /** + * There are 5 conditions that have to met for us to consult the DHT: + * 1. The entry in the DHT is RSL_RECORD_EXPIRED OR + * 2. No entry in the NS existed AND + * 3. The zone queried is not the local resolver's zone AND + * 4. The name that was looked up is '+' + * because if it was any other canonical name we either already queried + * the DHT for the authority in the authority lookup phase (and thus + * would already have an entry in the NS for the record) + * 5. We are not in cache only mode + */ + if ((0 != (rh->status & RSL_RECORD_EXPIRED)) && + (0 == (rh->status & RSL_RECORD_EXISTS)) ) + { + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Not expired and exists!\n", + rh->id); + check_dht = GNUNET_NO; + } + + if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, + &rh->private_local_zone)) + { - /* results found yay */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_REC-%d: Record resolved from namestore!", rh->id); - - finish_lookup(rh, rlh, rd_count, rd); - - free_resolver_handle(rh); - -} - - -/** - * Determine if this name is canonical. - * i.e. - * a.b.gnunet = not canonical - * a = canonical - * - * @param name the name to test - * @return 1 if canonical - */ -static int -is_canonical(char* name) -{ - uint32_t len = strlen(name); - int i; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_REC-%llu: Our zone!\n", + rh->id); + check_dht = GNUNET_NO; + } + + if ((0 != strcmp (rh->name, GNUNET_GNS_MASTERZONE_STR)) && (GNUNET_YES == is_srv (rh->name))) + check_dht = GNUNET_NO; - for (i=0; i<len; i++) + if (GNUNET_YES == rh->only_cached) + check_dht = GNUNET_NO; + + if (GNUNET_YES == check_dht) { - if (*(name+i) == '.') - return 0; + rh->proc = &handle_record_dht; + resolve_record_dht(rh); + return; } - return 1; + /* give up, cannot resolve */ + finish_lookup (rh, rlh, 0, NULL); } + /** * Move one level up in the domain hierarchy and return the * passed top level domain. * + * FIXME: funky API: not only 'dest' is updated, so is 'name'! + * * @param name the domain * @param dest the destination where the tld will be put */ -void -pop_tld(char* name, char* dest) +static void +pop_tld (char* name, char* dest) { uint32_t len; - if (is_canonical(name)) + if (GNUNET_YES == is_canonical (name)) { - strcpy(dest, name); - strcpy(name, ""); + strcpy (dest, name); + strcpy (name, ""); return; } - for (len = strlen(name); len > 0; len--) + for (len = strlen(name); 0 < len; len--) { if (*(name+len) == '.') break; } //Was canonical? - if (len == 0) + if (0 == len) return; name[len] = '\0'; @@ -1588,32 +2658,6 @@ pop_tld(char* name, char* dest) strcpy(dest, (name+len+1)); } -/** - * Checks if name is in tld - * - * @param name the name to check - * @param tld the TLD to check for - * @return GNUNET_YES or GNUNET_NO - */ -int -is_tld(const char* name, const char* tld) -{ - int offset = 0; - - if (strlen(name) <= strlen(tld)) - { - return GNUNET_NO; - } - - offset = strlen(name)-strlen(tld); - if (strcmp(name+offset, tld) != 0) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "%s is not in .%s TLD\n", name, tld); - return GNUNET_NO; - } - return GNUNET_YES; -} /** * DHT resolution for delegation finished. Processing result. @@ -1628,19 +2672,16 @@ handle_delegation_dht(void* cls, struct ResolverHandle *rh, unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd) { - struct RecordLookupHandle* rlh; - rlh = (struct RecordLookupHandle*) cls; + struct RecordLookupHandle* rlh = cls; - - if (strcmp(rh->name, "") == 0) + if (0 == strcmp(rh->name, "")) { - if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY)) + if (GNUNET_GNS_RECORD_PKEY == rlh->record_type) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_PHASE_DELEGATE_DHT-%llu: Resolved queried PKEY via DHT.\n", rh->id); finish_lookup(rh, rlh, rd_count, rd); - free_resolver_handle(rh); return; } /* We resolved full name for delegation. resolving record */ @@ -1656,7 +2697,7 @@ handle_delegation_dht(void* cls, struct ResolverHandle *rh, /** * we still have some left **/ - if (is_canonical(rh->name)) + if (GNUNET_YES == is_canonical (rh->name)) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_PHASE_DELEGATE_DHT-%llu: Resolving canonical record %s in ns\n", @@ -1671,7 +2712,6 @@ handle_delegation_dht(void* cls, struct ResolverHandle *rh, "GNS_PHASE_DELEGATE_DHT-%llu: Cannot fully resolve delegation for %s via DHT!\n", rh->id, rh->name); finish_lookup(rh, rlh, 0, NULL); - free_resolver_handle(rh); } @@ -1682,30 +2722,19 @@ handle_delegation_dht(void* cls, struct ResolverHandle *rh, * @param rh the pending gns query */ static void -resolve_delegation_dht(struct ResolverHandle *rh) +resolve_delegation_dht (struct ResolverHandle *rh) { uint32_t xquery; - struct GNUNET_CRYPTO_ShortHashCode name_hash; - GNUNET_HashCode name_hash_double; - GNUNET_HashCode zone_hash_double; - GNUNET_HashCode lookup_key; + struct GNUNET_HashCode lookup_key; struct ResolverHandle *rh_heap_root; - pop_tld(rh->name, rh->authority_name); - GNUNET_CRYPTO_short_hash(rh->authority_name, - strlen(rh->authority_name), - &name_hash); - GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double); - GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double); - GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key); - + pop_tld (rh->name, rh->authority_name); + GNUNET_GNS_get_key_for_record (rh->authority_name, + &rh->authority, + &lookup_key); rh->dht_heap_node = NULL; - if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value) { - //rh->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, - // &dht_authority_lookup_timeout, - // rh); rh->timeout_cont = &dht_authority_lookup_timeout; rh->timeout_cont_cls = rh; } @@ -1716,36 +2745,64 @@ resolve_delegation_dht(struct ResolverHandle *rh) { /* terminate oldest lookup */ rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap); - GNUNET_DHT_get_stop(rh_heap_root->get_handle); + GNUNET_DHT_get_stop (rh_heap_root->get_handle); + rh_heap_root->get_handle = NULL; rh_heap_root->dht_heap_node = NULL; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_DHT-%llu: Replacing oldest background query for %s\n", - rh->id, rh_heap_root->authority_name); - - rh_heap_root->proc(rh_heap_root->proc_cls, - rh_heap_root, - 0, - NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_DHT-%llu: Replacing oldest background query for %s\n", + rh->id, + rh_heap_root->authority_name); + rh_heap_root->proc (rh_heap_root->proc_cls, + rh_heap_root, + 0, + NULL); } rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap, - rh, - GNUNET_TIME_absolute_get().abs_value); + rh, + GNUNET_TIME_absolute_get().abs_value); } - - xquery = htonl(GNUNET_GNS_RECORD_PKEY); - - GNUNET_assert(rh->get_handle == NULL); - rh->get_handle = GNUNET_DHT_get_start(dht_handle, - GNUNET_BLOCK_TYPE_GNS_NAMERECORD, - &lookup_key, - DHT_GNS_REPLICATION_LEVEL, - GNUNET_DHT_RO_NONE, - &xquery, - sizeof(xquery), - &process_delegation_result_dht, - rh); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Beginning DHT lookup for %s in zone %s for request %llu\n", + rh->authority_name, + GNUNET_short_h2s (&rh->authority), + rh->id); + xquery = htonl (GNUNET_GNS_RECORD_PKEY); + GNUNET_assert (rh->get_handle == NULL); + rh->get_handle = GNUNET_DHT_get_start (dht_handle, + GNUNET_BLOCK_TYPE_GNS_NAMERECORD, + &lookup_key, + DHT_GNS_REPLICATION_LEVEL, + GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, + &xquery, + sizeof(xquery), + &process_delegation_result_dht, + rh); +} + + +/** + * Checks if name is in tld + * + * @param name the name to check + * @param tld the TLD to check for + * @return GNUNET_YES or GNUNET_NO + */ +int +is_tld (const char* name, const char* tld) +{ + size_t offset = 0; + if (strlen (name) <= strlen (tld)) + return GNUNET_NO; + + offset = strlen (name) - strlen (tld); + if (0 != strcmp (name + offset, tld)) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "%s is not in .%s TLD\n", name, tld); + return GNUNET_NO; + } + return GNUNET_YES; } @@ -1758,80 +2815,211 @@ resolve_delegation_dht(struct ResolverHandle *rh) * @param rd record data (always NULL) */ static void -handle_delegation_ns(void* cls, struct ResolverHandle *rh, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +handle_delegation_ns (void* cls, struct ResolverHandle *rh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { - struct RecordLookupHandle* rlh; - rlh = (struct RecordLookupHandle*) cls; + struct RecordLookupHandle* rlh = cls; + int check_dht; + size_t s_len; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_PHASE_DELEGATE_NS-%llu: Resolution status: %d.\n", rh->id, rh->status); + + if (rh->status & RSL_PKEY_REVOKED) + { + finish_lookup (rh, rlh, 0, NULL); + return; + } - if (strcmp(rh->name, "") == 0) + if (0 == strcmp(rh->name, "")) { - if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY)) + + /* We resolved full name for delegation. resolving record */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Resolved full name for delegation.\n", + rh->id); + if (rh->status & RSL_CNAME_FOUND) { - GNUNET_assert(rd_count == 1); + if (GNUNET_GNS_RECORD_CNAME == rlh->record_type) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried CNAME in NS.\n", + rh->id); + strcpy (rh->name, rh->authority_name); + finish_lookup (rh, rlh, rd_count, rd); + return; + } + + /* A .+ CNAME */ + if (GNUNET_YES == is_tld ((char*)rd->data, GNUNET_GNS_TLD_PLUS)) + { + s_len = strlen (rd->data) - 2; + memcpy (rh->name, rd->data, s_len); + rh->name[s_len] = '\0'; + resolve_delegation_ns (rh); + return; + } + else if (GNUNET_YES == is_tld ((char*)rd->data, GNUNET_GNS_TLD_ZKEY)) + { + gns_resolver_lookup_record (rh->authority, + rh->private_local_zone, + rlh->record_type, + (char*)rd->data, + rh->priv_key, + rh->timeout, + rh->only_cached, + rlh->proc, + rlh->proc_cls); + GNUNET_free (rlh); + GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh); + free_resolver_handle (rh); + return; + } + else + { + //Try DNS resolver + strcpy (rh->dns_name, (char*)rd->data); + resolve_dns_name (rh); + return; + } + + } + else if (rh->status & RSL_DELEGATE_VPN) + { + if (GNUNET_GNS_RECORD_VPN == rlh->record_type) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried VPNRR in NS.\n", + rh->id); + finish_lookup(rh, rlh, rd_count, rd); + return; + } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried PKEY in NS.\n", + "GNS_PHASE_DELEGATE_NS-%llu: VPN delegation starting.\n", + rh->id); + GNUNET_assert (NULL != rd); + rh->proc = &handle_record_vpn; + resolve_record_vpn (rh, rd_count, rd); + return; + } + else if (rh->status & RSL_DELEGATE_NS) + { + if (GNUNET_GNS_RECORD_NS == rlh->record_type) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n", + rh->id); + finish_lookup(rh, rlh, rd_count, rd); + return; + } + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: NS delegation starting.\n", rh->id); - finish_lookup(rh, rlh, rd_count, rd); - free_resolver_handle(rh); + GNUNET_assert (NULL != rd); + rh->proc = &handle_record_ns; + resolve_record_dns (rh, rd_count, rd); return; } - /* We resolved full name for delegation. resolving record */ + else if (rh->status & RSL_DELEGATE_PKEY) + { + if (rh->status & RSL_PKEY_REVOKED) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Resolved PKEY is revoked.\n", + rh->id); + finish_lookup (rh, rlh, 0, NULL); + return; + } + else if (GNUNET_GNS_RECORD_PKEY == rlh->record_type) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried PKEY in NS.\n", + rh->id); + finish_lookup(rh, rlh, rd_count, rd); + return; + } + } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Resolved full name for delegation.\n", - rh->id); + "GNS_PHASE_DELEGATE_NS-%llu: Resolving record +\n", + rh->id); strcpy(rh->name, "+\0"); rh->proc = &handle_record_ns; resolve_record_ns(rh); return; } - + + if (rh->status & RSL_DELEGATE_NS) + { + if (GNUNET_GNS_RECORD_NS == rlh->record_type) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n", + rh->id); + finish_lookup(rh, rlh, rd_count, rd); + return; + } + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: NS delegation starting.\n", + rh->id); + GNUNET_assert (NULL != rd); + rh->proc = &handle_record_ns; + resolve_record_dns (rh, rd_count, rd); + return; + } + /** * we still have some left * check if authority in ns is fresh * and exists * or we are authority **/ - if (((rh->status & RSL_RECORD_EXISTS) && (!(rh->status & RSL_RECORD_EXPIRED))) - || !GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - &rh->private_local_zone)) + + check_dht = GNUNET_YES; + if ((rh->status & RSL_RECORD_EXISTS) && + !(rh->status & RSL_RECORD_EXPIRED)) + check_dht = GNUNET_NO; + + if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, + &rh->private_local_zone)) + check_dht = GNUNET_NO; + + if (GNUNET_YES == rh->only_cached) + check_dht = GNUNET_NO; + + if (GNUNET_YES == check_dht) { - if (is_canonical(rh->name)) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Resolving canonical record %s\n", - rh->id, - rh->name); - rh->proc = &handle_record_ns; - resolve_record_ns(rh); - } - else - { - /* give up, cannot resolve */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Cannot fully resolve delegation for %s!\n", - rh->id, - rh->name); - finish_lookup(rh, rlh, rd_count, rd); - //rlh->proc(rlh->proc_cls, 0, NULL); - } + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Trying to resolve delegation for %s via DHT\n", + rh->id, rh->name); + rh->proc = &handle_delegation_dht; + resolve_delegation_dht(rh); return; } + if (GNUNET_NO == is_canonical (rh->name)) + { + /* give up, cannot resolve */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Cannot fully resolve delegation for %s!\n", + rh->id, + rh->name); + finish_lookup(rh, rlh, rd_count, rd); + return; + } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Trying to resolve delegation for %s via DHT\n", - rh->id, rh->name); - rh->proc = &handle_delegation_dht; - resolve_delegation_dht(rh); + "GNS_PHASE_DELEGATE_NS-%llu: Resolving canonical record %s\n", + rh->id, + rh->name); + rh->proc = &handle_record_ns; + resolve_record_ns(rh); } - /** * This is a callback function that should give us only PKEY * records. Used to query the namestore for the authority (PKEY) @@ -1847,45 +3035,47 @@ handle_delegation_ns(void* cls, struct ResolverHandle *rh, * @param signature the signature of the authority for the record data */ static void -process_delegation_result_ns(void* cls, - const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, - struct GNUNET_TIME_Absolute expiration, - const char *name, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_RsaSignature *signature) +process_delegation_result_ns (void* cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, + struct GNUNET_TIME_Absolute expiration, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) { - struct ResolverHandle *rh; + struct ResolverHandle *rh = cls; struct GNUNET_TIME_Relative remaining_time; struct GNUNET_CRYPTO_ShortHashCode zone; - char new_name[MAX_DNS_NAME_LENGTH]; + char new_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + unsigned int i; + struct GNUNET_TIME_Absolute et; - rh = (struct ResolverHandle *)cls; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup\n", - rh->id, rd_count); + rh->namestore_task = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup\n", + rh->id, rd_count); - GNUNET_CRYPTO_short_hash(key, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &zone); + GNUNET_CRYPTO_short_hash (key, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &zone); remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); rh->status = 0; if (name != NULL) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Records with name %s exist.\n", - rh->id, name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Records with name %s exist.\n", + rh->id, name); rh->status |= RSL_RECORD_EXISTS; - } - if (remaining_time.rel_value == 0) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n", - rh->id, name); - rh->status |= RSL_RECORD_EXPIRED; + if (remaining_time.rel_value == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n", + rh->id, name); + rh->status |= RSL_RECORD_EXPIRED; + } } /** @@ -1902,31 +3092,29 @@ process_delegation_result_ns(void* cls, * Promote this authority back to a name maybe it is * our record. */ - if (strcmp(rh->name, "") == 0) + if (strcmp (rh->name, "") == 0) { /* simply promote back */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n", - rh->id, rh->authority_name); - strcpy(rh->name, rh->authority_name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n", + rh->id, rh->authority_name); + strcpy (rh->name, rh->authority_name); } else { /* add back to existing name */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n", - rh->id, rh->authority_name, rh->name); - //memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2); - GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s", - rh->name, rh->authority_name); - //strcpy(new_name, rh->name); - //strcpy(new_name+strlen(new_name), "."); - //strcpy(new_name+strlen(new_name), rh->authority_name); - strcpy(rh->name, new_name); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n", rh->id, rh->name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n", + rh->id, rh->authority_name, rh->name); + GNUNET_snprintf (new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s", + rh->name, rh->authority_name); + strcpy (rh->name, new_name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n", + rh->id, rh->name); } - rh->proc(rh->proc_cls, rh, 0, NULL); + + rh->proc (rh->proc_cls, rh, 0, NULL); return; } @@ -1935,36 +3123,81 @@ process_delegation_result_ns(void* cls, * move on with query * Note only 1 pkey should have been returned.. anything else would be strange */ - int i; - for (i=0; i<rd_count;i++) + for (i=0; i < rd_count;i++) { + + /** + * A CNAME. Like regular DNS this means the is no other record for this + * name. + */ + if (rd[i].record_type == GNUNET_GNS_RECORD_CNAME) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: CNAME found.\n", + rh->id); + + rh->status |= RSL_CNAME_FOUND; + rh->proc (rh->proc_cls, rh, rd_count, rd); + return; + } + + /** + * Redirect via VPN + */ + if (rd[i].record_type == GNUNET_GNS_RECORD_VPN) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: VPN found.\n", + rh->id); + rh->status |= RSL_DELEGATE_VPN; + rh->proc (rh->proc_cls, rh, rd_count, rd); + return; + } + + /** + * Redirect via NS + * FIXME make optional + */ + if (rd[i].record_type == GNUNET_GNS_RECORD_NS) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: NS found.\n", + rh->id); + rh->status |= RSL_DELEGATE_NS; + rh->proc (rh->proc_cls, rh, rd_count, rd); + return; + } if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY) continue; - if (ignore_pending_records && + rh->status |= RSL_DELEGATE_PKEY; + + if ((ignore_pending_records != 0) && (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING)) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n", - name, - rh->id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n", + rh->id, + name); continue; } - if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value + GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)); + et.abs_value = rd[i].expiration_time; + if ((GNUNET_TIME_absolute_get_remaining (et)).rel_value == 0) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n", - rh->id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n", + rh->id); if (remaining_time.rel_value == 0) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n", - rh->id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n", + rh->id); rh->authority_chain_head->fresh = 0; - rh->proc(rh->proc_cls, rh, 0, NULL); + rh->proc (rh->proc_cls, rh, 0, NULL); return; } @@ -1974,35 +3207,33 @@ process_delegation_result_ns(void* cls, /** * Resolve rest of query with new authority */ - GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY); - memcpy(&rh->authority, rd[i].data, - sizeof(struct GNUNET_CRYPTO_ShortHashCode)); - struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain)); + GNUNET_assert (rd[i].record_type == GNUNET_GNS_RECORD_PKEY); + memcpy (&rh->authority, rd[i].data, + sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + struct AuthorityChain *auth = GNUNET_malloc(sizeof (struct AuthorityChain)); auth->zone = rh->authority; - memset(auth->name, 0, strlen(rh->authority_name)+1); - strcpy(auth->name, rh->authority_name); + memset (auth->name, 0, strlen (rh->authority_name)+1); + strcpy (auth->name, rh->authority_name); GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head, rh->authority_chain_tail, auth); + if (NULL != rh->rd.data) + GNUNET_free ((void*)(rh->rd.data)); - /** try to import pkey if private key available - * TODO: Only import last one? - */ - if (rh->priv_key && (name != NULL)) - process_discovered_authority((char*)name, auth->zone, - rh->authority_chain_tail->zone, - rh->priv_key); - /** - * We are done with PKEY resolution if name is empty - * else resolve again with new authority - */ - if (strcmp(rh->name, "") == 0) - rh->proc(rh->proc_cls, rh, rd_count, rd); - else - resolve_delegation_ns(rh); + memcpy (&rh->rd, &rd[i], sizeof (struct GNUNET_NAMESTORE_RecordData)); + rh->rd.data = GNUNET_malloc (rd[i].data_size); + memcpy ((void*)rh->rd.data, rd[i].data, rd[i].data_size); + rh->rd_count = 1; + /* Check for key revocation and delegate */ + rh->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle, + &rh->authority, + GNUNET_GNS_MASTERZONE_STR, + GNUNET_GNS_RECORD_REV, + &process_pkey_revocation_result_ns, + rh); return; } - + /** * no answers found */ @@ -2012,18 +3243,31 @@ process_delegation_result_ns(void* cls, * If we have found some records for the LAST label * we return the results. Else null. */ - if (strcmp(rh->name, "") == 0) + if (strcmp (rh->name, "") == 0) { + /* Start shortening */ + if ((rh->priv_key != NULL) && + (is_canonical (rh->name) == GNUNET_YES)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Trying to shorten authority chain\n", + rh->id); + start_shorten (rh->authority_chain_head, + rh->priv_key); + } /* simply promote back */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n", - rh->id, rh->authority_name); - strcpy(rh->name, rh->authority_name); - rh->proc(rh->proc_cls, rh, rd_count, rd); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n", + rh->id, rh->authority_name); + strcpy (rh->name, rh->authority_name); + rh->proc (rh->proc_cls, rh, rd_count, rd); } else { - rh->proc(rh->proc_cls, rh, 0, NULL); + GNUNET_snprintf (new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, + "%s.%s", rh->name, rh->authority_name); + strcpy (rh->name, new_name); + rh->proc (rh->proc_cls, rh, 0, NULL); } } @@ -2034,19 +3278,19 @@ process_delegation_result_ns(void* cls, * @param rh the resolver handle */ static void -resolve_delegation_ns(struct ResolverHandle *rh) +resolve_delegation_ns (struct ResolverHandle *rh) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Resolving delegation for %s\n", - rh->id, rh->name); - pop_tld(rh->name, rh->authority_name); - GNUNET_NAMESTORE_lookup_record(namestore_handle, - &rh->authority, - rh->authority_name, - GNUNET_GNS_RECORD_ANY, - &process_delegation_result_ns, - rh); - + pop_tld (rh->name, rh->authority_name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Resolving delegation for %s by looking up %s\n", + rh->id, rh->name, + rh->authority_name); + rh->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle, + &rh->authority, + rh->authority_name, + GNUNET_GNS_RECORD_ANY, + &process_delegation_result_ns, + rh); } @@ -2060,31 +3304,34 @@ resolve_delegation_ns(struct ResolverHandle *rh) * @param name the name to look up * @param key a private key for use with PSEU import (can be NULL) * @param timeout timeout for resolution + * @param only_cached GNUNET_NO to only check locally not DHT for performance * @param proc the processor to call on result * @param cls the closure to pass to proc */ void -gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_ShortHashCode pzone, - uint32_t record_type, - const char* name, - struct GNUNET_CRYPTO_RsaPrivateKey *key, - struct GNUNET_TIME_Relative timeout, - RecordLookupProcessor proc, - void* cls) +gns_resolver_lookup_record (struct GNUNET_CRYPTO_ShortHashCode zone, + struct GNUNET_CRYPTO_ShortHashCode pzone, + uint32_t record_type, + const char* name, + struct GNUNET_CRYPTO_RsaPrivateKey *key, + struct GNUNET_TIME_Relative timeout, + int only_cached, + RecordLookupProcessor proc, + void* cls) { struct ResolverHandle *rh; struct RecordLookupHandle* rlh; - char string_hash[MAX_DNS_LABEL_LENGTH]; - char nzkey[MAX_DNS_LABEL_LENGTH]; + char string_hash[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; + char nzkey[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; char* nzkey_ptr = nzkey; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting resolution for %s (type=%d)!\n", - name, record_type); + "Starting resolution for %s (type=%d) with timeout %s!\n", + name, record_type, + GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_YES)); - - if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0)) + if ((is_canonical ((char*)name) == GNUNET_YES) && + (strcmp(GNUNET_GNS_TLD, name) != 0)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s is canonical and not gnunet -> cannot resolve!\n", name); @@ -2092,16 +3339,21 @@ gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone, return; } - rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle)); - rh = GNUNET_malloc(sizeof (struct ResolverHandle)); - + rlh = GNUNET_malloc (sizeof(struct RecordLookupHandle)); + rh = GNUNET_malloc (sizeof (struct ResolverHandle)); rh->authority = zone; - rh->id = rid++; + rh->id = rid_gen++; rh->proc_cls = rlh; rh->priv_key = key; rh->timeout = timeout; - rh->get_handle = NULL; rh->private_local_zone = pzone; + rh->only_cached = only_cached; + + GNUNET_CONTAINER_DLL_insert (rlh_head, rlh_tail, rh); + + if (NULL == key) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No shorten key for resolution\n"); if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value) { @@ -2109,8 +3361,9 @@ gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone, * Set timeout for authority lookup phase to 1/2 */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Timeout for lookup set to %ds\n", rh->timeout.rel_value); - rh->timeout_task = GNUNET_SCHEDULER_add_delayed( + "Timeout for lookup set to %s/2\n", + GNUNET_STRINGS_relative_time_to_string (rh->timeout, GNUNET_YES)); + rh->timeout_task = GNUNET_SCHEDULER_add_delayed ( GNUNET_TIME_relative_divide(timeout, 2), &handle_lookup_timeout, rh); @@ -2157,36 +3410,51 @@ gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone, &rh->authority)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Cannot convert ZKEY %s to hash!\n", string_hash); - GNUNET_free(rh); - GNUNET_free(rlh); - proc(cls, 0, NULL); + "Cannot convert ZKEY `%s' to hash!\n", string_hash); + + if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task) + GNUNET_SCHEDULER_cancel (rh->timeout_task); + GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh); + GNUNET_free (rh); + GNUNET_free (rlh); + proc (cls, 0, NULL); return; } } - else + else if (is_gads_tld (name) == GNUNET_YES) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "TLD is gnunet\n"); + "TLD is gads\n"); /** - * Presumably GNUNET tld + * Presumably GADS tld */ - memset(rh->name, 0, - strlen(name)-strlen(GNUNET_GNS_TLD)); - memcpy(rh->name, name, - strlen(name)-strlen(GNUNET_GNS_TLD) - 1); + memcpy (rh->name, name, + strlen (name) - strlen(GNUNET_GNS_TLD) - 1); + rh->name[strlen (name) - strlen(GNUNET_GNS_TLD) - 1] = '\0'; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Not a GADS TLD: `%s'\n"), + name); + if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task) + GNUNET_SCHEDULER_cancel (rh->timeout_task); + GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh); + GNUNET_free (rh); + GNUNET_free (rlh); + proc (cls, 0, NULL); + return; } } /** * Initialize authority chain */ - rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); - rh->authority_chain_head->prev = NULL; - rh->authority_chain_head->next = NULL; + rh->authority_chain_head = GNUNET_malloc (sizeof(struct AuthorityChain)); rh->authority_chain_tail = rh->authority_chain_head; rh->authority_chain_head->zone = rh->authority; + strcpy (rh->authority_chain_head->name, ""); /** * Copy original query into lookup handle @@ -2203,6 +3471,18 @@ gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone, /******** END Record Resolver ***********/ +static void +finish_shorten (struct ResolverHandle *rh, + struct NameShortenHandle *nsh) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending %s as shorten result\n", nsh->result); + nsh->proc (nsh->proc_cls, nsh->result); + GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh); + GNUNET_free (nsh); + free_resolver_handle (rh); +} + /** * Callback calles by namestore for a zone to name @@ -2217,7 +3497,29 @@ gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone, * @param signature the signature for the record data */ static void -process_zone_to_name_shorten(void *cls, +process_zone_to_name_shorten_root (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); + + +/** + * Callback called by namestore for a zone to name + * result + * + * @param cls the closure + * @param zone_key the zone we queried + * @param expire the expiration time of the name + * @param name the name found or NULL + * @param rd_len number of records for the name + * @param rd the record data (PKEY) for the name + * @param signature the signature for the record data + */ +static void +process_zone_to_name_shorten_shorten (void *cls, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, struct GNUNET_TIME_Absolute expire, const char *name, @@ -2225,65 +3527,195 @@ process_zone_to_name_shorten(void *cls, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature) { - struct ResolverHandle *rh = (struct ResolverHandle *)cls; - struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls; + struct ResolverHandle *rh = cls; + struct NameShortenHandle* nsh = rh->proc_cls; struct AuthorityChain *next_authority; - char result[MAX_DNS_NAME_LENGTH]; - char tmp_name[MAX_DNS_NAME_LENGTH]; + char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + char tmp_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; size_t answer_len; - /* we found a match in our own zone */ + rh->namestore_task = NULL; + /* we found a match in our own root zone */ if (rd_len != 0) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "result strlen %d\n", strlen(name)); answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3; memset(result, 0, answer_len); + if (strlen(rh->name) > 0) { - strcpy(result, rh->name); - strcpy(result+strlen(rh->name), "."); + sprintf (result, "%s.%s.%s.%s", + rh->name, name, + nsh->shorten_zone_name, + GNUNET_GNS_TLD); + } + else + { + sprintf (result, "%s.%s.%s", name, + nsh->shorten_zone_name, + GNUNET_GNS_TLD); } - - strcpy(result+strlen(result), name); - strcpy(result+strlen(result), "."); - strcpy(result+strlen(result), GNUNET_GNS_TLD); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Sending shorten result %s\n", result); - - nsh->proc(nsh->proc_cls, result); - GNUNET_free(nsh); - free_resolver_handle(rh); + "Found shorten result %s\n", result); + if (strlen (nsh->result) > strlen (result)) + strcpy (nsh->result, result); } else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - &rh->private_local_zone) == 0) + nsh->shorten_zone) == 0) + { + /** + * This is our zone append .gads unless name is empty + * (it shouldn't be, usually FIXME what happens if we + * shorten to our zone to a "" record??) + */ + + sprintf (result, "%s.%s.%s", + rh->name, + nsh->shorten_zone_name, + GNUNET_GNS_TLD); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Our zone: Found %s as shorten result\n", result); + + if (strlen (nsh->result) > strlen (result)) + strcpy (nsh->result, result); + //nsh->proc(nsh->proc_cls, result); + //GNUNET_free(nsh); + //free_resolver_handle(rh); + //return; + } + + + /** + * No PSEU found. + * continue with next authority if exists + */ + if (NULL == rh->authority_chain_head->next) { - /* our zone, just append .gnunet */ - answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2; + finish_shorten (rh, nsh); + return; + } + next_authority = rh->authority_chain_head; + + if (0 == strcmp (rh->name, "")) + strcpy (tmp_name, next_authority->name); + else + GNUNET_snprintf(tmp_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, + "%s.%s", rh->name, next_authority->name); + + strcpy(rh->name, tmp_name); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "No PSEU found for authority %s. Promoting back: %s\n", + next_authority->name, rh->name); + + GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, + rh->authority_chain_tail, + next_authority); + + GNUNET_free (next_authority); + + rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + &rh->authority_chain_tail->zone, + &rh->authority_chain_head->zone, + &process_zone_to_name_shorten_root, + rh); +} + + +/** + * Callback calles by namestore for a zone to name + * result + * + * @param cls the closure + * @param zone_key the zone we queried + * @param expire the expiration time of the name + * @param name the name found or NULL + * @param rd_len number of records for the name + * @param rd the record data (PKEY) for the name + * @param signature the signature for the record data + */ +static void +process_zone_to_name_shorten_private (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 ResolverHandle *rh = cls; + struct NameShortenHandle* nsh = rh->proc_cls; + struct AuthorityChain *next_authority; + + char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + char tmp_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + size_t answer_len; + + rh->namestore_task = NULL; + /* we found a match in our own root zone */ + if (rd_len != 0) + { + answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3; memset(result, 0, answer_len); - strcpy(result, rh->name); - strcpy(result+strlen(rh->name), "."); - strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD); + if (strlen(rh->name) > 0) + { + sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD); + } + else + { + sprintf (result, "%s.%s", name, GNUNET_GNS_TLD); + } + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Our zone: Sending name as shorten result %s\n", rh->name); + "Found shorten result %s\n", result); + if (strlen (nsh->result) > strlen (result)) + strcpy (nsh->result, result); + } + else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, + nsh->private_zone) == 0) + { + /** + * This is our zone append .gads unless name is empty + * (it shouldn't be, usually FIXME what happens if we + * shorten to our zone to a "" record??) + */ - nsh->proc(nsh->proc_cls, result); - GNUNET_free(nsh); - free_resolver_handle(rh); + sprintf (result, "%s.%s.%s", + rh->name, nsh->private_zone_name, GNUNET_GNS_TLD); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Our private zone: Found %s as shorten result %s\n", result); + if (strlen (nsh->result) > strlen (result)) + strcpy (nsh->result, result); + } + + if (0 != strcmp (nsh->shorten_zone_name, "")) + { + /* backtrack authorities for names in priv zone */ + rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + nsh->shorten_zone, + &rh->authority_chain_head->zone, + &process_zone_to_name_shorten_shorten, + rh); } else { /** * No PSEU found. - * continue with next authority + * continue with next authority if exists */ + if (NULL == rh->authority_chain_head->next) + { + finish_shorten (rh, nsh); + return; + } next_authority = rh->authority_chain_head; - GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH, - "%s.%s", rh->name, next_authority->name); + if (0 == strcmp (rh->name, "")) + strcpy (tmp_name, next_authority->name); + else + GNUNET_snprintf(tmp_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, + "%s.%s", rh->name, next_authority->name); strcpy(rh->name, tmp_name); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, @@ -2294,35 +3726,139 @@ process_zone_to_name_shorten(void *cls, rh->authority_chain_tail, next_authority); - GNUNET_NAMESTORE_zone_to_name (namestore_handle, + GNUNET_free (next_authority); + + rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, &rh->authority_chain_tail->zone, &rh->authority_chain_head->zone, - &process_zone_to_name_shorten, + &process_zone_to_name_shorten_root, rh); } } + /** - * DHT resolution for delegation. Processing result. + * Callback calles by namestore for a zone to name + * result * * @param cls the closure - * @param rh resolver handle - * @param rd_count number of results - * @param rd record data + * @param zone_key the zone we queried + * @param expire the expiration time of the name + * @param name the name found or NULL + * @param rd_len number of records for the name + * @param rd the record data (PKEY) for the name + * @param signature the signature for the record data */ static void -handle_delegation_dht_bg_shorten(void* cls, struct ResolverHandle *rh, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +process_zone_to_name_shorten_root (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 ResolverHandle *rh = cls; + struct NameShortenHandle* nsh = rh->proc_cls; + struct AuthorityChain *next_authority; + char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + char tmp_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + size_t answer_len; - /* We resolved full name for delegation. resolving record */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_SHORTEN: Resolved up to %s for delegation via DHT in background.\n", - rh->name); - free_resolver_handle(rh); + rh->namestore_task = NULL; + /* we found a match in our own root zone */ + if (rd_len != 0) + { + answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3; + memset(result, 0, answer_len); + + if (strlen(rh->name) > 0) + { + sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD); + } + else + { + sprintf (result, "%s.%s", name, GNUNET_GNS_TLD); + } + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Found shorten result %s\n", result); + if (strlen (nsh->result) > strlen (result)) + strcpy (nsh->result, result); + } + else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, + nsh->root_zone) == 0) + { + /** + * This is our zone append .gads unless name is empty + * (it shouldn't be, usually FIXME what happens if we + * shorten to our zone to a "" record??) + */ + + sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Our zone: Found %s as shorten result\n", result); + if (strlen (nsh->result) > strlen (result)) + strcpy (nsh->result, result); + } + + if (NULL != nsh->private_zone) + { + /* backtrack authorities for names in priv zone */ + rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + nsh->private_zone, + &rh->authority_chain_head->zone, + &process_zone_to_name_shorten_private, + rh); + } + else if (NULL != nsh->shorten_zone) + { + /* backtrack authorities for names in shorten zone */ + rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + nsh->shorten_zone, + &rh->authority_chain_head->zone, + &process_zone_to_name_shorten_shorten, + rh); + } + else + { + /** + * No PSEU found. + * continue with next authority if exists + */ + if (NULL == rh->authority_chain_head->next) + { + finish_shorten (rh, nsh); + return; + } + next_authority = rh->authority_chain_head; + + if (0 == strcmp (rh->name, "")) + strcpy (tmp_name, next_authority->name); + else + GNUNET_snprintf(tmp_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, + "%s.%s", rh->name, next_authority->name); + + strcpy(rh->name, tmp_name); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "No PSEU found for authority %s. Promoting back: %s\n", + next_authority->name, rh->name); + + GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, + rh->authority_chain_tail, + next_authority); + + GNUNET_free (next_authority); + + rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + &rh->authority_chain_tail->zone, + &rh->authority_chain_head->zone, + &process_zone_to_name_shorten_root, + rh); + } } + /** * Process result from namestore delegation lookup * for shorten operation @@ -2332,19 +3868,17 @@ handle_delegation_dht_bg_shorten(void* cls, struct ResolverHandle *rh, * @param rd_count number of results (0) * @param rd data (NULL) */ -void -handle_delegation_ns_shorten(void* cls, +static void +handle_delegation_ns_shorten (void* cls, struct ResolverHandle *rh, uint32_t rd_count, const struct GNUNET_NAMESTORE_RecordData *rd) { struct NameShortenHandle *nsh; - char result[MAX_DNS_NAME_LENGTH]; - size_t answer_len; - struct ResolverHandle *rh_bg; + char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; nsh = (struct NameShortenHandle *)cls; - + rh->namestore_task = NULL; /** * At this point rh->name contains the part of the name * that we do not have a PKEY in our namestore to resolve. @@ -2354,73 +3888,75 @@ handle_delegation_ns_shorten(void* cls, GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "PKEY resolved as far as possible in ns up to %s!\n", rh->name); + memset(result, 0, sizeof (result)); - if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - &rh->private_local_zone) == 0) + if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, + nsh->root_zone)) { /** - * This is our zone append .gnunet unless name is empty + * This is our zone append .gads unless name is empty * (it shouldn't be, usually FIXME what happens if we * shorten to our zone to a "" record??) */ - answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2; - memset(result, 0, answer_len); - strcpy(result, rh->name); - strcpy(result+strlen(rh->name), "."); - strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD); - + sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Our zone: Sending name as shorten result %s\n", rh->name); + "Our zone: Found %s as shorten result\n", result); - nsh->proc(nsh->proc_cls, result); - GNUNET_free(nsh); - free_resolver_handle(rh); - return; + if (strlen (nsh->result) > strlen (result)) + strcpy (nsh->result, result); + } - - /** - * we have to this before zone to name for rh might - * be freed by then - */ - rh_bg = NULL; - if (!is_canonical(rh->name)) + else if (NULL != nsh->private_zone) { - rh_bg = GNUNET_malloc(sizeof(struct ResolverHandle)); - memcpy(rh_bg, rh, sizeof(struct ResolverHandle)); - rh_bg->id = rid++; + /** + * This is our zone append .gads unless name is empty + * (it shouldn't be, usually FIXME what happens if we + * shorten to our zone to a "" record??) + */ + if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, + nsh->private_zone) == 0) + { + + sprintf (result, "%s.%s.%s", + rh->name, nsh->private_zone_name, GNUNET_GNS_TLD); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Our zone: Found %s as shorten result in private zone %s\n", + result); + + if (strlen (nsh->result) > strlen (result)) + strcpy (nsh->result, result); + } } - - /* backtrack authorities for names */ - GNUNET_NAMESTORE_zone_to_name (namestore_handle, - &rh->authority_chain_tail->zone, //ours - &rh->authority_chain_head->zone, - &process_zone_to_name_shorten, - rh); - - if (rh_bg == NULL) + else if (NULL != nsh->shorten_zone) { - return; + /** + * This is our zone append .gads unless name is empty + * (it shouldn't be, usually FIXME what happens if we + * shorten to our zone to a "" record??) + */ + if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, + nsh->shorten_zone) == 0) + { + sprintf (result, "%s.%s.%s", + rh->name, nsh->private_zone_name, GNUNET_GNS_TLD); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Our zone: Found %s as shorten result in shorten zone\n", + result); + + if (strlen (nsh->result) > strlen (result)) + strcpy (nsh->result, result); + } } - - /** - * If authority resolution is incomplete we can do a background lookup - * of the full name so that next time we can (likely) fully or at least - * further shorten the name - */ - rh_bg->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); - rh_bg->authority_chain_tail = rh_bg->authority_chain_head; - rh_bg->authority_chain_head->zone = rh_bg->authority; - rh_bg->proc = &handle_delegation_dht_bg_shorten; - rh_bg->proc_cls = NULL; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_SHORTEN: Starting background lookup for %s\n", - rh_bg->name); - - resolve_delegation_dht(rh_bg); - + /* backtrack authorities for names */ + rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + nsh->root_zone, + &rh->authority_chain_head->zone, + &process_zone_to_name_shorten_root, + rh); + } @@ -2447,8 +3983,9 @@ process_zone_to_name_zkey(void *cls, { struct ResolverHandle *rh = cls; struct NameShortenHandle *nsh = rh->proc_cls; - struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc; - char new_name[MAX_DNS_NAME_LENGTH]; + char new_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + + rh->namestore_task = NULL; /* zkey not in our zone */ if (name == NULL) @@ -2460,24 +3997,23 @@ process_zone_to_name_zkey(void *cls, * because PKEY import will happen if the user follows the zkey * link. */ - GNUNET_CRYPTO_short_hash_to_enc ((struct GNUNET_CRYPTO_ShortHashCode*)rd, - &enc); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "No name found for zkey %s returning verbatim!\n", enc); - if (strcmp(rh->name, "") != 0) - GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s.%s", + "No name found for zkey %s returning verbatim!\n", nsh->result); + /*if (strcmp(rh->name, "") != 0) + GNUNET_snprintf(new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s.%s", rh->name, enc, GNUNET_GNS_TLD_ZKEY); else - GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s", + GNUNET_snprintf(new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s", enc, GNUNET_GNS_TLD_ZKEY); - nsh->proc(nsh->proc_cls, new_name); - GNUNET_free(nsh); - free_resolver_handle(rh); + + strcpy (nsh->result, new_name);*/ + + finish_shorten (rh, nsh); return; } if (strcmp(rh->name, "") != 0) - GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s", + GNUNET_snprintf(new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s", rh->name, name); else strcpy(new_name, name); @@ -2493,64 +4029,71 @@ process_zone_to_name_zkey(void *cls, /* Start delegation resolution in our namestore */ - resolve_delegation_ns(rh); + resolve_delegation_ns (rh); } /** * Shorten api from resolver * - * @param zone the zone to use - * @param pzone the private local zone + * @param zone the root zone to use + * @param pzone the private zone to use + * @param szone the shorten zone to use * @param name the name to shorten - * @param key optional private key for background lookups and PSEU import + * @param private_zone_name name of the private zone + * @param shorten_zone_name name of the shorten zone * @param proc the processor to call with result * @param proc_cls closure to pass to proc */ void -gns_resolver_shorten_name(struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_ShortHashCode pzone, - const char* name, - struct GNUNET_CRYPTO_RsaPrivateKey *key, - ShortenResultProcessor proc, - void* proc_cls) +gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone, + struct GNUNET_CRYPTO_ShortHashCode *pzone, + struct GNUNET_CRYPTO_ShortHashCode *szone, + const char* name, + const char* private_zone_name, + const char* shorten_zone_name, + ShortenResultProcessor proc, + void* proc_cls) { struct ResolverHandle *rh; struct NameShortenHandle *nsh; - char string_hash[MAX_DNS_LABEL_LENGTH]; + char string_hash[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; struct GNUNET_CRYPTO_ShortHashCode zkey; - char nzkey[MAX_DNS_LABEL_LENGTH]; + char nzkey[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; char* nzkey_ptr = nzkey; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting shorten for %s!\n", name); - if (is_canonical((char*)name)) + if (is_canonical ((char*)name) == GNUNET_YES) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s is canonical. Returning verbatim\n", name); - proc(proc_cls, name); + proc (proc_cls, name); return; } - nsh = GNUNET_malloc(sizeof (struct NameShortenHandle)); - + nsh = GNUNET_malloc (sizeof (struct NameShortenHandle)); nsh->proc = proc; nsh->proc_cls = proc_cls; + nsh->root_zone = zone; + nsh->private_zone = pzone; + nsh->shorten_zone = szone; + strcpy (nsh->private_zone_name, private_zone_name); + strcpy (nsh->shorten_zone_name, shorten_zone_name); + strcpy (nsh->result, name); - rh = GNUNET_malloc(sizeof (struct ResolverHandle)); - rh->authority = zone; - rh->id = rid++; - rh->priv_key = key; + rh = GNUNET_malloc (sizeof (struct ResolverHandle)); + rh->authority = *zone; + rh->id = rid_gen++; rh->proc = &handle_delegation_ns_shorten; rh->proc_cls = nsh; - rh->id = rid++; - rh->private_local_zone = pzone; - + rh->private_local_zone = *zone; + + GNUNET_CONTAINER_DLL_insert (nsh_head, nsh_tail, rh); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Checking for TLD...\n"); - if (is_zkey_tld(name) == GNUNET_YES) + "Checking for TLD...\n"); + if (is_zkey_tld (name) == GNUNET_YES) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TLD is zkey\n"); @@ -2559,60 +4102,87 @@ gns_resolver_shorten_name(struct GNUNET_CRYPTO_ShortHashCode zone, * build hash and use as initial authority * FIXME sscanf */ - memset(rh->name, 0, - strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY)); - memcpy(rh->name, name, - strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1); - pop_tld(rh->name, string_hash); + memset (rh->name, 0, + strlen (name)-strlen (GNUNET_GNS_TLD_ZKEY)); + memcpy (rh->name, name, + strlen(name)-strlen (GNUNET_GNS_TLD_ZKEY) - 1); + pop_tld (rh->name, string_hash); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ZKEY is %s!\n", string_hash); - GNUNET_STRINGS_utf8_toupper(string_hash, &nzkey_ptr); + GNUNET_STRINGS_utf8_toupper (string_hash, &nzkey_ptr); - if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(nzkey, - &zkey)) + if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string (nzkey, + &zkey)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot convert ZKEY %s to hash!\n", nzkey); - GNUNET_free(rh); - GNUNET_free(nsh); - proc(proc_cls, name); + GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh); + GNUNET_free (rh); + GNUNET_free (nsh); + proc (proc_cls, name); return; } - - GNUNET_NAMESTORE_zone_to_name (namestore_handle, - &zone, //ours + rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, + zone, //ours &zkey, &process_zone_to_name_zkey, rh); return; } - else + else if (is_gads_tld (name) == GNUNET_YES) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TLD is gnunet\n"); /** * Presumably GNUNET tld */ - memset(rh->name, 0, - strlen(name)-strlen(GNUNET_GNS_TLD)); - memcpy(rh->name, name, - strlen(name)-strlen(GNUNET_GNS_TLD) - 1); + memset (rh->name, 0, + strlen (name)-strlen (GNUNET_GNS_TLD)); + memcpy (rh->name, name, + strlen (name)-strlen (GNUNET_GNS_TLD) - 1); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown TLD in %s\n", name); + GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh); + GNUNET_free (rh); + GNUNET_free (nsh); + proc (proc_cls, name); + return; } - rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); + rh->authority_chain_head = GNUNET_malloc (sizeof (struct AuthorityChain)); rh->authority_chain_tail = rh->authority_chain_head; - rh->authority_chain_head->zone = zone; - + rh->authority_chain_head->zone = *zone; /* Start delegation resolution in our namestore */ - resolve_delegation_ns(rh); + resolve_delegation_ns (rh); } /*********** END NAME SHORTEN ********************/ +/** + * Conclude get authority lookup + * + * @param rh resolver handle + * @param nah get authority lookup handle + */ +static void +finish_get_auth (struct ResolverHandle *rh, + struct GetNameAuthorityHandle *nah) +{ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got authority result %s\n", nah->result); + + nah->proc (nah->proc_cls, nah->result); + GNUNET_CONTAINER_DLL_remove (nah_head, nah_tail, rh); + GNUNET_free (nah); + free_resolver_handle (rh); +} + /** * Process result from namestore delegation lookup @@ -2623,18 +4193,15 @@ gns_resolver_shorten_name(struct GNUNET_CRYPTO_ShortHashCode zone, * @param rd_count number of results (0) * @param rd data (NULL) */ -void +static void handle_delegation_result_ns_get_auth(void* cls, struct ResolverHandle *rh, uint32_t rd_count, const struct GNUNET_NAMESTORE_RecordData *rd) { - struct GetNameAuthorityHandle* nah; - char result[MAX_DNS_NAME_LENGTH]; + struct GetNameAuthorityHandle* nah = rh->proc_cls; size_t answer_len; - nah = (struct GetNameAuthorityHandle*) rh->proc_cls; - /** * At this point rh->name contains the part of the name * that we do not have a PKEY in our namestore to resolve. @@ -2647,7 +4214,7 @@ handle_delegation_result_ns_get_auth(void* cls, GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Building response!\n"); - if (is_canonical(rh->name)) + if (is_canonical (rh->name) == GNUNET_YES) { /** * We successfully resolved the authority in the ns @@ -2664,26 +4231,21 @@ handle_delegation_result_ns_get_auth(void* cls, answer_len = strlen(nah->name) - strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 1; - memset(result, 0, answer_len); - strcpy(result, nah->name + strlen(rh->name) + 1); + memset(nah->result, 0, answer_len); + if (0 != strcmp (rh->name, "")) + strcpy(nah->result, nah->name + strlen(rh->name) + 1); + else + strcpy(nah->result, nah->name); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got authority result %s\n", result); - - nah->proc(nah->proc_cls, result); - GNUNET_free(nah); - free_resolver_handle(rh); + finish_get_auth (rh, nah); } else { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Unable to resolve authority for remaining %s!\n", rh->name); - nah->proc(nah->proc_cls, ""); - GNUNET_free(nah); - free_resolver_handle(rh); + strcpy(nah->result, ""); + finish_get_auth (rh, nah); } - - } @@ -2713,8 +4275,10 @@ gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone, nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle)); rh = GNUNET_malloc(sizeof (struct ResolverHandle)); rh->authority = zone; - rh->id = rid++; + rh->id = rid_gen++; rh->private_local_zone = pzone; + + GNUNET_CONTAINER_DLL_insert (nah_head, nah_tail, rh); if (strcmp(GNUNET_GNS_TLD, name) == 0) { @@ -2740,6 +4304,7 @@ gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone, nah->proc = proc; nah->proc_cls = proc_cls; + strcpy (nah->result, ""); /* Start delegation resolution in our namestore */ resolve_delegation_ns(rh); diff --git a/src/gns/gnunet-service-gns_resolver.h b/src/gns/gnunet-service-gns_resolver.h index 8222397..650c5c5 100644 --- a/src/gns/gnunet-service-gns_resolver.h +++ b/src/gns/gnunet-service-gns_resolver.h @@ -1,3 +1,27 @@ +/* + This file is part of GNUnet. + (C) 2009, 2010, 2011, 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 gns/gnunet-service-gns_resolver.h + * @brief GNUnet GNS service + * @author Martin Schanzenbach + */ #ifndef GNS_RESOLVER_H #define GNS_RESOLVER_H @@ -5,13 +29,18 @@ #include "gnunet_dht_service.h" #define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) + #define GNUNET_GNS_DEFAULT_LOOKUP_TIMEOUT \ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + #define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT + #define DHT_GNS_REPLICATION_LEVEL 5 #define GNUNET_GNS_MAX_PARALLEL_LOOKUPS 500 +#define GNUNET_GNS_MAX_NS_TASKS 500 + /* * DLL to hold the authority chain * we had to pass in the resolution process @@ -22,23 +51,28 @@ struct AuthorityChain struct AuthorityChain *next; - /* the zone hash of the authority */ + /** + * the zone hash of the authority + */ struct GNUNET_CRYPTO_ShortHashCode zone; - /* (local) name of the authority */ - char name[MAX_DNS_LABEL_LENGTH]; + /** + * (local) name of the authority + */ + char name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; - /* was the ns entry fresh */ + /** + * was the ns entry fresh + */ int fresh; }; -/* handle to a resolution process */ -struct ResolverHandle; /** - * continuation called when cleanup of resolver finishes + * handle to a resolution process */ -typedef void (*ResolverCleanupContinuation) (void); +struct ResolverHandle; + /** * processor for a record lookup result @@ -48,8 +82,8 @@ typedef void (*ResolverCleanupContinuation) (void); * @param rd result data */ typedef void (*RecordLookupProcessor) (void *cls, - uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd); + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); /** @@ -58,16 +92,18 @@ typedef void (*RecordLookupProcessor) (void *cls, * @param cls the closure * @param name shortened name */ -typedef void (*ShortenResultProcessor) (void *cls, const char* name); +typedef void (*ShortenResultProcessor) (void *cls, + const char* name); /** * processor for an authority result * * @param cls the closure - * @param name name + * @param name name of the authority */ -typedef void (*GetAuthorityResultProcessor) (void *cls, const char* name); +typedef void (*GetAuthorityResultProcessor) (void *cls, + const char* name); /** * processor for a resolution result @@ -75,25 +111,58 @@ typedef void (*GetAuthorityResultProcessor) (void *cls, const char* name); * @param cls the closure * @param rh the resolution handle * @param rd_count number of results - * @param rd result data + * @param rd result data (array of 'rd_count' records) */ typedef void (*ResolutionResultProcessor) (void *cls, - struct ResolverHandle *rh, - uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd); + struct ResolverHandle *rh, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); /** * Resolution status indicator - * RSL_RECORD_EXISTS: the name to lookup exists - * RSL_RECORD_EXPIRED: the name in the record expired - * RSL_TIMED_OUT: resolution timed out */ enum ResolutionStatus { + /** + * the name to lookup exists + */ RSL_RECORD_EXISTS = 1, + + /** + * the name in the record expired + */ RSL_RECORD_EXPIRED = 2, - RSL_TIMED_OUT = 4 + + /** + * resolution timed out + */ + RSL_TIMED_OUT = 4, + + /** + * Found VPN delegation + */ + RSL_DELEGATE_VPN = 8, + + /** + * Found NS delegation + */ + RSL_DELEGATE_NS = 16, + + /** + * Found PKEY delegation + */ + RSL_DELEGATE_PKEY = 32, + + /** + * Found CNAME record + */ + RSL_CNAME_FOUND = 64, + + /** + * Found PKEY has been revoked + */ + RSL_PKEY_REVOKED = 128 }; /** @@ -108,49 +177,150 @@ enum ResolutionStatus */ struct ResolverHandle { - /* The name to resolve */ - char name[MAX_DNS_NAME_LENGTH]; - /* has this query been answered? how many matches */ + /** + * DLL + */ + struct ResolverHandle *next; + + /** + * DLL + */ + struct ResolverHandle *prev; + + /** + * Last record data found + */ + struct GNUNET_NAMESTORE_RecordData rd; + + /** + * Number of last record data found + */ + unsigned int rd_count; + + /** + * The name to resolve + */ + char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + + /** + * has this query been answered? how many matches + */ int answered; - /* the authoritative zone to query */ + /** + * Use only cache + */ + int only_cached; + + /** + * the authoritative zone to query + */ struct GNUNET_CRYPTO_ShortHashCode authority; - /* the name of the authoritative zone to query */ - char authority_name[MAX_DNS_LABEL_LENGTH]; + /** + * the name of the authoritative zone to query + */ + char authority_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; - /* a handle for dht lookups. should be NULL if no lookups are in progress */ + /** + * a handle for dht lookups. should be NULL if no lookups are in progress + */ struct GNUNET_DHT_GetHandle *get_handle; - /* timeout set for this lookup task */ + /** + * timeout set for this lookup task + */ struct GNUNET_TIME_Relative timeout; - /* timeout task for the lookup */ + /** + * a handle to a vpn request + */ + struct GNUNET_VPN_RedirectionRequest *vpn_handle; + + /** + * a socket for a dns request + */ + struct GNUNET_NETWORK_Handle *dns_sock; + + /** + * a synthesized dns name + */ + char dns_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + + /** + * the authoritative dns zone + */ + char dns_zone[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + + /** + * the address of the DNS server FIXME not needed? + */ + struct sockaddr_in dns_addr; + + /** + * handle to the local stub resolver request + */ + struct GNUNET_RESOLVER_RequestHandle *dns_resolver_handle; + + /** + * select task for DNS + */ + GNUNET_SCHEDULER_TaskIdentifier dns_read_task; + + /** + * pointer to raw dns query payload FIXME needs to be freed/NULL + */ + char *dns_raw_packet; + + /** + * size of the raw dns query + */ + size_t dns_raw_packet_size; + + /** + * timeout task for the lookup + */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; - /* continuation to call on timeout */ + /** + * continuation to call on timeout + */ GNUNET_SCHEDULER_Task timeout_cont; - /* closure for timeout cont */ + /** + * closure for timeout cont + */ void* timeout_cont_cls; - /* called when resolution phase finishes */ + /** + * called when resolution phase finishes + */ ResolutionResultProcessor proc; - /* closure passed to proc */ + /** + * closure passed to proc + */ void* proc_cls; - /* DLL to store the authority chain */ + /** + * DLL to store the authority chain + */ struct AuthorityChain *authority_chain_head; - /* DLL to store the authority chain */ + /** + * DLL to store the authority chain + */ struct AuthorityChain *authority_chain_tail; - /* status of the resolution result */ + /** + * status of the resolution result + */ enum ResolutionStatus status; - /* The provate local zone of this request */ + /** + * The provate local zone of this request + */ struct GNUNET_CRYPTO_ShortHashCode private_local_zone; /** @@ -170,6 +340,11 @@ struct ResolverHandle */ unsigned long long id; + /** + * Pending Namestore task + */ + struct GNUNET_NAMESTORE_QueueEntry *namestore_task; + }; @@ -178,16 +353,24 @@ struct ResolverHandle */ struct RecordLookupHandle { - /* the record type to look up */ + /** + * the record type to look up + */ enum GNUNET_GNS_RecordType record_type; - /* the name to look up */ - char name[MAX_DNS_NAME_LENGTH]; + /** + * the name to look up + */ + char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - /* Method to call on record resolution result */ + /** + * Method to call on record resolution result + */ RecordLookupProcessor proc; - /* closure to pass to proc */ + /** + * closure to pass to proc + */ void* proc_cls; }; @@ -198,55 +381,150 @@ struct RecordLookupHandle */ struct NameShortenHandle { - /* Method to call on shorten result */ + /** + * Method to call on shorten result + */ ShortenResultProcessor proc; - /* closure to pass to proc */ + /** + * closure to pass to proc + */ void* proc_cls; + + /** + * result of shorten + */ + char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + + /** + * root zone + */ + struct GNUNET_CRYPTO_ShortHashCode *root_zone; + + /** + * private zone + */ + struct GNUNET_CRYPTO_ShortHashCode *private_zone; + + /** + * name of private zone + */ + char private_zone_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; + + /** + * shorten zone + */ + struct GNUNET_CRYPTO_ShortHashCode *shorten_zone; + + /** + * name of shorten zone + */ + char shorten_zone_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; + }; + /** * Handle to a get authority context */ struct GetNameAuthorityHandle { - /* the name to look up authority for */ - char name[MAX_DNS_NAME_LENGTH]; + /** + * the name to look up authority for + */ + char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + + /** + * the result + */ + char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - /* Method to call on result */ + /** + * Method to call on result + */ GetAuthorityResultProcessor proc; - /* closure to pass to proc */ + /** + * closure to pass to proc + */ void* proc_cls; }; + /** * Handle to a pseu lookup */ struct GetPseuAuthorityHandle { - /* the name given from delegation */ - char name[MAX_DNS_LABEL_LENGTH]; + /** + * DLL + */ + struct GetPseuAuthorityHandle *next; - /* name to store the pseu under */ - char new_name[MAX_DNS_LABEL_LENGTH]; - - /* the zone of discovered authority */ - struct GNUNET_CRYPTO_ShortHashCode new_zone; + /** + * DLL + */ + struct GetPseuAuthorityHandle *prev; - /* the zone of our authority */ - struct GNUNET_CRYPTO_ShortHashCode zone; + /** + * the name to store the zone under + */ + char name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; - /* the private key of the zone to store the pseu in */ + /** + * test name to store the zone under + */ + char test_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; + + /** + * the zone of our authority + */ + struct GNUNET_CRYPTO_ShortHashCode our_zone; + + /** + * the private key of the zone to store the pseu in + */ struct GNUNET_CRYPTO_RsaPrivateKey *key; - /* a handle for dht lookups. should be NULL if no lookups are in progress */ + /** + * a handle for dht lookups. should be NULL if no lookups are in progress + */ struct GNUNET_DHT_GetHandle *get_handle; - /* timeout task for lookup */ + /** + * timeout task for lookup + */ GNUNET_SCHEDULER_TaskIdentifier timeout; + + /** + * Authority to shorten + */ + struct AuthorityChain *auth; + + /** + * handle to namestore request + */ + struct GNUNET_NAMESTORE_QueueEntry* namestore_task; +}; + + +/** + * Namestore queue entries in background + */ +struct NamestoreBGTask +{ + /** + * node in heap + */ + struct GNUNET_CONTAINER_HeapNode *node; + + /** + * queue entry + */ + struct GNUNET_NAMESTORE_QueueEntry *qe; }; + /** * Initialize the resolver * MUST be called before other gns_resolver_* methods @@ -254,25 +532,27 @@ struct GetPseuAuthorityHandle * @param nh handle to the namestore * @param dh handle to the dht * @param lz the local zone + * @param c configuration handle * @param max_bg_queries maximum amount of background queries * @param ignore_pending ignore records that still require user confirmation * on lookup * @returns GNUNET_OK on success */ int -gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh, - struct GNUNET_DHT_Handle *dh, - struct GNUNET_CRYPTO_ShortHashCode lz, - unsigned long long max_bg_queries, - int ignore_pending); +gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, + struct GNUNET_DHT_Handle *dh, + struct GNUNET_CRYPTO_ShortHashCode lz, + const struct GNUNET_CONFIGURATION_Handle *c, + unsigned long long max_bg_queries, + int ignore_pending); + /** * Cleanup resolver: Terminate pending lookups - * - * @param cont continuation to call when finished */ void -gns_resolver_cleanup(ResolverCleanupContinuation cont); +gns_resolver_cleanup (void); + /** * Lookup of a record in a specific zone @@ -284,18 +564,21 @@ gns_resolver_cleanup(ResolverCleanupContinuation cont); * @param name the name to look up * @param key optional private key for authority caching * @param timeout timeout for the resolution + * @param only_cached GNUNET_NO to only check locally not DHT for performance * @param proc the processor to call * @param cls the closure to pass to proc */ void -gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_ShortHashCode pzone, - uint32_t record_type, - const char* name, - struct GNUNET_CRYPTO_RsaPrivateKey *key, - struct GNUNET_TIME_Relative timeout, - RecordLookupProcessor proc, - void* cls); +gns_resolver_lookup_record (struct GNUNET_CRYPTO_ShortHashCode zone, + struct GNUNET_CRYPTO_ShortHashCode pzone, + uint32_t record_type, + const char* name, + struct GNUNET_CRYPTO_RsaPrivateKey *key, + struct GNUNET_TIME_Relative timeout, + int only_cached, + RecordLookupProcessor proc, + void* cls); + /** * Shortens a name if possible. If the shortening fails @@ -304,20 +587,25 @@ gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone, * There is no guarantee that the shortened name will * actually be canonical/short etc. * - * @param zone the zone to perform the operation in - * @param pzone the private local zone + * @param zone the root zone to use + * @param pzone the private zone to use + * @param szone the shorten zone to use * @param name name to shorten - * @param key optional private key for background lookups and PSEU import + * @param private_zone_name name of the private zone + * @param shorten_zone_name name of the shorten zone * @param proc the processor to call on shorten result * @param proc_cls the closure to pass to proc */ void -gns_resolver_shorten_name(struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_ShortHashCode pzone, - const char* name, - struct GNUNET_CRYPTO_RsaPrivateKey *key, - ShortenResultProcessor proc, - void* proc_cls); +gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone, + struct GNUNET_CRYPTO_ShortHashCode *pzone, + struct GNUNET_CRYPTO_ShortHashCode *szone, + const char* name, + const char* private_zone_name, + const char* shorten_zone_name, + ShortenResultProcessor proc, + void* proc_cls); + /** * Tries to resolve the authority for name @@ -330,11 +618,11 @@ gns_resolver_shorten_name(struct GNUNET_CRYPTO_ShortHashCode zone, * @param proc_cls the closure to pass to the processor */ void -gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_ShortHashCode pzone, - const char* name, - GetAuthorityResultProcessor proc, - void* proc_cls); +gns_resolver_get_authority (struct GNUNET_CRYPTO_ShortHashCode zone, + struct GNUNET_CRYPTO_ShortHashCode pzone, + const char* name, + GetAuthorityResultProcessor proc, + void* proc_cls); /** * Generic function to check for TLDs @@ -344,12 +632,14 @@ gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone, * @return GNUNET_YES or GNUNET_NO */ int -is_tld(const char* name, const char* tld); +is_tld (const char* name, + const char* tld); + /** - * Checks for gnunet/zkey + * Checks for gads/zkey */ -#define is_gnunet_tld(name) is_tld(name, GNUNET_GNS_TLD) +#define is_gads_tld(name) is_tld(name, GNUNET_GNS_TLD) #define is_zkey_tld(name) is_tld(name, GNUNET_GNS_TLD_ZKEY) diff --git a/src/gns/nss/Makefile.am b/src/gns/nss/Makefile.am index 5e8ab5a..64bc813 100644 --- a/src/gns/nss/Makefile.am +++ b/src/gns/nss/Makefile.am @@ -3,8 +3,8 @@ # This file taken and modified from nss-gns. # # nss-gns is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 2 of the +# under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the # License, or (at your option) any later version. # # nss-gns is distributed in the hope that it will be useful, but @@ -17,24 +17,24 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = map-file +EXTRA_DIST = map-file \ + install-nss-plugin.sh \ + uninstall-nss-plugin.sh AM_LDFLAGS=-avoid-version -module -export-dynamic -if HAVE_SUDO -nssdir = /lib/ -else -nssdir = $(libdir) -endif +nssdir = $(NSS_DIR) LIBTOOL = $(SUDO_BINARY) $(SHELL) $(top_builddir)/libtool if !MINGW +if INSTALL_NSS nss_LTLIBRARIES = \ libnss_gns.la \ libnss_gns4.la \ libnss_gns6.la endif +endif sources = nss_gns_query.h nss_gns_query.c @@ -51,9 +51,12 @@ libnss_gns6_la_SOURCES=$(libnss_gns_la_SOURCES) libnss_gns6_la_CFLAGS=$(libnss_gns_la_CFLAGS) -DNSS_IPV6_ONLY=1 libnss_gns6_la_LDFLAGS=$(libnss_gns_la_LDFLAGS) +if !MINGW install-data-hook: - $(SUDO_BINARY) $(SHELL) $(top_builddir)/libtool --finish $(nssdir) - $(SUDO_BINARY) rm -f $(nssdir)/libnss_gns.la $(nssdir)/libnss_gns4.la $(nssdir)/libnss_gns6.la + $(top_srcdir)/src/gns/nss/install-nss-plugin.sh $(SHELL) $(top_builddir) $(nssdir) $(SUDO_BINARY) uninstall-hook: - $(SUDO_BINARY) rm -f $(nssdir)/libnss_gns.so.2 $(nssdir)/libnss_gns4.so.2 $(nssdir)/libnss_gns6.so.2 + $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns.so.2" $(SUDO_BINARY) + $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns4.so.2" $(SUDO_BINARY) + $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns6.so.2" $(SUDO_BINARY) +endif diff --git a/src/gns/nss/Makefile.in b/src/gns/nss/Makefile.in index 6b3b3df..9352442 100644 --- a/src/gns/nss/Makefile.in +++ b/src/gns/nss/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -20,8 +20,8 @@ # This file taken and modified from nss-gns. # # nss-gns is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 2 of the +# under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the # License, or (at your option) any later version. # # nss-gns is distributed in the hope that it will be useful, but @@ -35,6 +35,23 @@ # USA. VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -59,14 +76,15 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/argz.m4 \ - $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libcurl.m4 \ - $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/libunistring.m4 $(top_srcdir)/m4/ltdl.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glib-2.0.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libcurl.m4 $(top_srcdir)/m4/libgcrypt.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ + $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -96,19 +114,26 @@ am__nobase_list = $(am__nobase_strip_setup); \ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } am__installdirs = "$(DESTDIR)$(nssdir)" LTLIBRARIES = $(nss_LTLIBRARIES) libnss_gns_la_LIBADD = am__objects_1 = libnss_gns_la-nss_gns_query.lo am_libnss_gns_la_OBJECTS = $(am__objects_1) libnss_gns_la-nss_gns.lo libnss_gns_la_OBJECTS = $(am_libnss_gns_la_OBJECTS) -AM_V_lt = $(am__v_lt_$(V)) -am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent libnss_gns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libnss_gns_la_CFLAGS) \ $(CFLAGS) $(libnss_gns_la_LDFLAGS) $(LDFLAGS) -o $@ -@MINGW_FALSE@am_libnss_gns_la_rpath = -rpath $(nssdir) +@INSTALL_NSS_TRUE@@MINGW_FALSE@am_libnss_gns_la_rpath = -rpath \ +@INSTALL_NSS_TRUE@@MINGW_FALSE@ $(nssdir) libnss_gns4_la_LIBADD = am__objects_2 = libnss_gns4_la-nss_gns_query.lo am__objects_3 = $(am__objects_2) libnss_gns4_la-nss_gns.lo @@ -118,7 +143,8 @@ libnss_gns4_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libnss_gns4_la_CFLAGS) $(CFLAGS) $(libnss_gns4_la_LDFLAGS) \ $(LDFLAGS) -o $@ -@MINGW_FALSE@am_libnss_gns4_la_rpath = -rpath $(nssdir) +@INSTALL_NSS_TRUE@@MINGW_FALSE@am_libnss_gns4_la_rpath = -rpath \ +@INSTALL_NSS_TRUE@@MINGW_FALSE@ $(nssdir) libnss_gns6_la_LIBADD = am__objects_4 = libnss_gns6_la-nss_gns_query.lo am__objects_5 = $(am__objects_4) libnss_gns6_la-nss_gns.lo @@ -128,7 +154,8 @@ libnss_gns6_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libnss_gns6_la_CFLAGS) $(CFLAGS) $(libnss_gns6_la_LDFLAGS) \ $(LDFLAGS) -o $@ -@MINGW_FALSE@am_libnss_gns6_la_rpath = -rpath $(nssdir) +@INSTALL_NSS_TRUE@@MINGW_FALSE@am_libnss_gns6_la_rpath = -rpath \ +@INSTALL_NSS_TRUE@@MINGW_FALSE@ $(nssdir) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -139,26 +166,31 @@ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_$(V)) -am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_$(V)) -am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libnss_gns_la_SOURCES) $(libnss_gns4_la_SOURCES) \ $(libnss_gns6_la_SOURCES) DIST_SOURCES = $(libnss_gns_la_SOURCES) $(libnss_gns4_la_SOURCES) \ $(libnss_gns6_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -197,6 +229,10 @@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ @@ -207,6 +243,7 @@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GN_USER_HOME_DIR = @GN_USER_HOME_DIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ GREP = @GREP@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INCLTDL = @INCLTDL@ @@ -229,6 +266,8 @@ LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBGTOP_CFLAGS = @LIBGTOP_CFLAGS@ +LIBGTOP_LIBS = @LIBGTOP_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBLTDL = @LIBLTDL@ @@ -250,6 +289,7 @@ LT_CONFIG_H = @LT_CONFIG_H@ LT_DLLOADERS = @LT_DLLOADERS@ LT_DLPREOPEN = @LT_DLPREOPEN@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ @@ -259,6 +299,7 @@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ +NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ @@ -274,6 +315,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ @@ -305,6 +347,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ @@ -327,6 +370,7 @@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -340,7 +384,6 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ ltdl_LIBOBJS = @ltdl_LIBOBJS@ ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@ mandir = @mandir@ @@ -358,6 +401,7 @@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ +svnversioncommand = @svnversioncommand@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ @@ -368,14 +412,16 @@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -EXTRA_DIST = map-file +EXTRA_DIST = map-file \ + install-nss-plugin.sh \ + uninstall-nss-plugin.sh + AM_LDFLAGS = -avoid-version -module -export-dynamic -@HAVE_SUDO_FALSE@nssdir = $(libdir) -@HAVE_SUDO_TRUE@nssdir = /lib/ -@MINGW_FALSE@nss_LTLIBRARIES = \ -@MINGW_FALSE@ libnss_gns.la \ -@MINGW_FALSE@ libnss_gns4.la \ -@MINGW_FALSE@ libnss_gns6.la +nssdir = $(NSS_DIR) +@INSTALL_NSS_TRUE@@MINGW_FALSE@nss_LTLIBRARIES = \ +@INSTALL_NSS_TRUE@@MINGW_FALSE@ libnss_gns.la \ +@INSTALL_NSS_TRUE@@MINGW_FALSE@ libnss_gns4.la \ +@INSTALL_NSS_TRUE@@MINGW_FALSE@ libnss_gns6.la sources = nss_gns_query.h nss_gns_query.c @@ -425,7 +471,6 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): install-nssLTLIBRARIES: $(nss_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(nssdir)" || $(MKDIR_P) "$(DESTDIR)$(nssdir)" @list='$(nss_LTLIBRARIES)'; test -n "$(nssdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ @@ -433,6 +478,8 @@ install-nssLTLIBRARIES: $(nss_LTLIBRARIES) else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(nssdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(nssdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(nssdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(nssdir)"; \ } @@ -454,11 +501,11 @@ clean-nssLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libnss_gns.la: $(libnss_gns_la_OBJECTS) $(libnss_gns_la_DEPENDENCIES) +libnss_gns.la: $(libnss_gns_la_OBJECTS) $(libnss_gns_la_DEPENDENCIES) $(EXTRA_libnss_gns_la_DEPENDENCIES) $(AM_V_CCLD)$(libnss_gns_la_LINK) $(am_libnss_gns_la_rpath) $(libnss_gns_la_OBJECTS) $(libnss_gns_la_LIBADD) $(LIBS) -libnss_gns4.la: $(libnss_gns4_la_OBJECTS) $(libnss_gns4_la_DEPENDENCIES) +libnss_gns4.la: $(libnss_gns4_la_OBJECTS) $(libnss_gns4_la_DEPENDENCIES) $(EXTRA_libnss_gns4_la_DEPENDENCIES) $(AM_V_CCLD)$(libnss_gns4_la_LINK) $(am_libnss_gns4_la_rpath) $(libnss_gns4_la_OBJECTS) $(libnss_gns4_la_LIBADD) $(LIBS) -libnss_gns6.la: $(libnss_gns6_la_OBJECTS) $(libnss_gns6_la_DEPENDENCIES) +libnss_gns6.la: $(libnss_gns6_la_OBJECTS) $(libnss_gns6_la_DEPENDENCIES) $(EXTRA_libnss_gns6_la_DEPENDENCIES) $(AM_V_CCLD)$(libnss_gns6_la_LINK) $(am_libnss_gns6_la_rpath) $(libnss_gns6_la_OBJECTS) $(libnss_gns6_la_LIBADD) $(LIBS) mostlyclean-compile: @@ -477,74 +524,65 @@ distclean-compile: .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libnss_gns_la-nss_gns_query.lo: nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -MT libnss_gns_la-nss_gns_query.lo -MD -MP -MF $(DEPDIR)/libnss_gns_la-nss_gns_query.Tpo -c -o libnss_gns_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns_la-nss_gns_query.Tpo $(DEPDIR)/libnss_gns_la-nss_gns_query.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns_query.c' object='libnss_gns_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns_query.c' object='libnss_gns_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -c -o libnss_gns_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -c -o libnss_gns_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c libnss_gns_la-nss_gns.lo: nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -MT libnss_gns_la-nss_gns.lo -MD -MP -MF $(DEPDIR)/libnss_gns_la-nss_gns.Tpo -c -o libnss_gns_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns_la-nss_gns.Tpo $(DEPDIR)/libnss_gns_la-nss_gns.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns.c' object='libnss_gns_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns.c' object='libnss_gns_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -c -o libnss_gns_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -c -o libnss_gns_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c libnss_gns4_la-nss_gns_query.lo: nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -MT libnss_gns4_la-nss_gns_query.lo -MD -MP -MF $(DEPDIR)/libnss_gns4_la-nss_gns_query.Tpo -c -o libnss_gns4_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns4_la-nss_gns_query.Tpo $(DEPDIR)/libnss_gns4_la-nss_gns_query.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns_query.c' object='libnss_gns4_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns_query.c' object='libnss_gns4_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -c -o libnss_gns4_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -c -o libnss_gns4_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c libnss_gns4_la-nss_gns.lo: nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -MT libnss_gns4_la-nss_gns.lo -MD -MP -MF $(DEPDIR)/libnss_gns4_la-nss_gns.Tpo -c -o libnss_gns4_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns4_la-nss_gns.Tpo $(DEPDIR)/libnss_gns4_la-nss_gns.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns.c' object='libnss_gns4_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns.c' object='libnss_gns4_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -c -o libnss_gns4_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -c -o libnss_gns4_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c libnss_gns6_la-nss_gns_query.lo: nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -MT libnss_gns6_la-nss_gns_query.lo -MD -MP -MF $(DEPDIR)/libnss_gns6_la-nss_gns_query.Tpo -c -o libnss_gns6_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns6_la-nss_gns_query.Tpo $(DEPDIR)/libnss_gns6_la-nss_gns_query.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns_query.c' object='libnss_gns6_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns_query.c' object='libnss_gns6_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -c -o libnss_gns6_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -c -o libnss_gns6_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c libnss_gns6_la-nss_gns.lo: nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -MT libnss_gns6_la-nss_gns.lo -MD -MP -MF $(DEPDIR)/libnss_gns6_la-nss_gns.Tpo -c -o libnss_gns6_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns6_la-nss_gns.Tpo $(DEPDIR)/libnss_gns6_la-nss_gns.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns.c' object='libnss_gns6_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns.c' object='libnss_gns6_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -c -o libnss_gns6_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -c -o libnss_gns6_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c mostlyclean-libtool: -rm -f *.lo @@ -651,10 +689,15 @@ install-am: all-am installcheck: installcheck-am install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: @@ -666,6 +709,8 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." +@MINGW_TRUE@install-data-hook: +@MINGW_TRUE@uninstall-hook: clean: clean-am clean-am: clean-generic clean-libtool clean-nssLTLIBRARIES \ @@ -757,12 +802,13 @@ uninstall-am: uninstall-nssLTLIBRARIES uninstall-nssLTLIBRARIES -install-data-hook: - $(SUDO_BINARY) $(SHELL) $(top_builddir)/libtool --finish $(nssdir) - $(SUDO_BINARY) rm -f $(nssdir)/libnss_gns.la $(nssdir)/libnss_gns4.la $(nssdir)/libnss_gns6.la +@MINGW_FALSE@install-data-hook: +@MINGW_FALSE@ $(top_srcdir)/src/gns/nss/install-nss-plugin.sh $(SHELL) $(top_builddir) $(nssdir) $(SUDO_BINARY) -uninstall-hook: - $(SUDO_BINARY) rm -f $(nssdir)/libnss_gns.so.2 $(nssdir)/libnss_gns4.so.2 $(nssdir)/libnss_gns6.so.2 +@MINGW_FALSE@uninstall-hook: +@MINGW_FALSE@ $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns.so.2" $(SUDO_BINARY) +@MINGW_FALSE@ $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns4.so.2" $(SUDO_BINARY) +@MINGW_FALSE@ $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns6.so.2" $(SUDO_BINARY) # 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/gns/nss/install-nss-plugin.sh b/src/gns/nss/install-nss-plugin.sh new file mode 100755 index 0000000..c87db76 --- /dev/null +++ b/src/gns/nss/install-nss-plugin.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# $1 - shell +# $2 - top_builddir +# $3 - nssdir +# $4 - sudo binary (empty if root) +$4 $1 $2/libtool --mode=finish $3 +echo LTINST: $4 $1 $2/libtool --mode=finish $3 +$4 rm -f $3/libnss_gns.la $3/libnss_gns4.la $3/libnss_gns6.la diff --git a/src/gns/nss/nss_gns.c b/src/gns/nss/nss_gns.c index 3bb45a1..ce9dcf3 100644 --- a/src/gns/nss/nss_gns.c +++ b/src/gns/nss/nss_gns.c @@ -4,8 +4,8 @@ Parts taken from: nss.c in nss-mdns nss-mdns is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. nss-mdns is distributed in the hope that it will be useful, but1 @@ -61,13 +61,13 @@ static int ends_with(const char *name, const char* suffix) { /** - * Check if name is inside .gnunet or .zkey TLD + * Check if name is inside .gads or .zkey TLD * * @param name name to check * @return 1 if true */ static int verify_name_allowed(const char *name) { - return ends_with(name, ".gnunet") || ends_with(name, ".zkey"); + return ends_with(name, ".gads") || ends_with(name, ".zkey"); } /** @@ -140,13 +140,19 @@ enum nss_status _nss_gns_gethostbyname2_r( if (!gns_resolve_name(af, name, &u) == 0) { status = NSS_STATUS_NOTFOUND; + goto finish; } } + else + { + status = NSS_STATUS_UNAVAIL; + goto finish; + } if (u.count == 0) { *errnop = ETIMEDOUT; *h_errnop = HOST_NOT_FOUND; - printf("not found\n"); + status = NSS_STATUS_NOTFOUND; goto finish; } diff --git a/src/gns/nss/nss_gns_query.c b/src/gns/nss/nss_gns_query.c index ab88d22..33a71f7 100644 --- a/src/gns/nss/nss_gns_query.c +++ b/src/gns/nss/nss_gns_query.c @@ -1,3 +1,22 @@ +/* + 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. +*/ #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -14,52 +33,74 @@ * @param u the userdata (result struct) * @return -1 on error else 0 */ -int gns_resolve_name(int af, const char *name, struct userdata *u) +int +gns_resolve_name (int af, + const char *name, + struct userdata *u) { FILE *p; char *cmd; char line[128]; - if (af == AF_INET6) + if (AF_INET6 == af) { - if (-1 == asprintf(&cmd, "%s -t AAAA -u %s\n", "gnunet-gns -r", name)) + if (-1 == asprintf (&cmd, + "%s -t AAAA -u %s\n", + "gnunet-gns -r", name)) return -1; } else { - if (-1 == asprintf(&cmd, "%s %s\n", "gnunet-gns -r -u", name)) + if (-1 == asprintf (&cmd, + "%s %s\n", + "gnunet-gns -r -u", name)) return -1; } - - p = popen(cmd,"r"); - - if (p != NULL ) + if (NULL == (p = popen (cmd, "r"))) + { + free (cmd); + return -1; + } + while (NULL != fgets (line, sizeof(line), p)) { - while (fgets( line, sizeof(line), p ) != NULL) + if (u->count >= MAX_ENTRIES) + break; + if (line[strlen(line)-1] == '\n') { - - if (u->count >= MAX_ENTRIES) - break; - - if (line[strlen(line)-1] == '\n') + line[strlen(line)-1] = '\0'; + if (AF_INET == af) + { + if (inet_pton(af, line, &(u->data.ipv4[u->count]))) + { + u->count++; + u->data_len += sizeof(ipv4_address_t); + } + else + { + pclose (p); + free (cmd); + return -1; + } + } + else if (AF_INET6 == af) { - line[strlen(line)-1] = '\0'; - if (af == AF_INET) + if (inet_pton(af, line, &(u->data.ipv6[u->count]))) { - inet_pton(af, line, &(u->data.ipv4[u->count++])); - u->data_len += sizeof(ipv4_address_t); - } - else if ((af == AF_INET6)) + u->count++; + u->data_len += sizeof(ipv6_address_t); + } + else { - inet_pton(af, line, &(u->data.ipv6[u->count++])); - u->data_len += sizeof(ipv6_address_t); - } + pclose (p); + free (cmd); + return -1; + } } } } - fclose(p); - free(cmd); - + pclose (p); + free (cmd); return 0; - } + +/* end of nss_gns_query.c */ diff --git a/src/gns/nss/nss_gns_query.h b/src/gns/nss/nss_gns_query.h index 0b4dae5..65b0311 100644 --- a/src/gns/nss/nss_gns_query.h +++ b/src/gns/nss/nss_gns_query.h @@ -1,31 +1,28 @@ +/* + 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. +*/ #ifndef NSS_GNS_QUERY_H #define NSS_GNS_QUERY_H /** - * Parts taken from nss-mdns. Original license statement follows + * Parts taken from nss-mdns */ - -/* $Id$ */ - -/*** - This file is part of nss-mdns. - - nss-mdns is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - nss-mdns 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 Lesser General Public - License along with nss-mdns; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - #include <inttypes.h> /* Maximum number of entries to return */ diff --git a/src/gns/nss/uninstall-nss-plugin.sh b/src/gns/nss/uninstall-nss-plugin.sh new file mode 100755 index 0000000..61c8eff --- /dev/null +++ b/src/gns/nss/uninstall-nss-plugin.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# $1 - shell +# $2 - top_builddir +# $3 - nssdir+path of library to remove +# $4 - sudo binary (empty if root) +$4 $1 $2/libtool --mode=uninstall $3 + + diff --git a/src/gns/plugin_block_gns.c b/src/gns/plugin_block_gns.c index 5d986ce..50ad012 100644 --- a/src/gns/plugin_block_gns.c +++ b/src/gns/plugin_block_gns.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet - (C) 2010 Christian Grothoff (and other contributing authors) + (C) 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 @@ -29,6 +29,7 @@ #include "gnunet_namestore_service.h" #include "block_gns.h" #include "gnunet_signatures.h" +#include "gns_common.h" /** * Number of bits we set per entry in the bloomfilter. @@ -56,24 +57,25 @@ */ static enum GNUNET_BLOCK_EvaluationResult block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type, - const GNUNET_HashCode * query, + const struct GNUNET_HashCode * query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size) { - char* name; - GNUNET_HashCode pkey_hash_double; - GNUNET_HashCode query_key; - GNUNET_HashCode name_hash_double; - GNUNET_HashCode mhash; - GNUNET_HashCode chash; + const struct GNSNameRecordBlock *nrb; + const char* name; + const char *name_end; + const char *rd_data; + struct GNUNET_HashCode query_key; + struct GNUNET_HashCode mhash; + struct GNUNET_HashCode chash; struct GNUNET_CRYPTO_ShortHashCode pkey_hash; - struct GNUNET_CRYPTO_ShortHashCode name_hash; - struct GNSNameRecordBlock *nrb; + struct GNUNET_CRYPTO_HashAsciiEncoded xor_exp; + struct GNUNET_CRYPTO_HashAsciiEncoded xor_got; uint32_t rd_count; - char* rd_data = NULL; - int rd_len; + size_t rd_len; + size_t name_len; uint32_t record_xquery; unsigned int record_match; @@ -97,21 +99,20 @@ block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type, /* this is a reply */ - nrb = (struct GNSNameRecordBlock *)reply_block; - name = (char*)&nrb[1]; - GNUNET_CRYPTO_short_hash(&nrb->public_key, - sizeof(nrb->public_key), - &pkey_hash); - - GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash); - - GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double); - GNUNET_CRYPTO_short_hash_double(&pkey_hash, &pkey_hash_double); - - GNUNET_CRYPTO_hash_xor(&pkey_hash_double, &name_hash_double, &query_key); + nrb = (const struct GNSNameRecordBlock *)reply_block; + name = (const char*) &nrb[1]; + name_end = memchr (name, 0, reply_block_size - sizeof (struct GNSNameRecordBlock)); + if (NULL == name_end) + { + GNUNET_break_op (0); + return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; + } + name_len = (name_end - name) + 1; + GNUNET_CRYPTO_short_hash (&nrb->public_key, + sizeof(nrb->public_key), + &pkey_hash); + GNUNET_GNS_get_key_for_record (name, &pkey_hash, &query_key); - struct GNUNET_CRYPTO_HashAsciiEncoded xor_exp; - struct GNUNET_CRYPTO_HashAsciiEncoded xor_got; GNUNET_CRYPTO_hash_to_enc (&query_key, &xor_exp); GNUNET_CRYPTO_hash_to_enc (query, &xor_got); @@ -128,14 +129,14 @@ block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type, record_match = 0; rd_count = ntohl(nrb->rd_count); - rd_data = (char*)&nrb[1]; - rd_data += strlen(name) + 1; - rd_len = reply_block_size - (strlen(name) + 1 + rd_data = &name[name_len]; + rd_len = reply_block_size - (name_len + sizeof(struct GNSNameRecordBlock)); { struct GNUNET_NAMESTORE_RecordData rd[rd_count]; unsigned int i; - struct GNUNET_TIME_Absolute exp = GNUNET_TIME_UNIT_FOREVER_ABS; + uint64_t exp = UINT64_MAX; + struct GNUNET_TIME_Absolute et = GNUNET_TIME_UNIT_FOREVER_ABS; if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_len, rd_data, @@ -144,7 +145,6 @@ block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type, { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Data invalid (%d bytes, %d records)\n", rd_len, rd_count); - GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } @@ -154,32 +154,34 @@ block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type, record_xquery = ntohl(*((uint32_t*)xquery)); for (i=0; i<rd_count; i++) - { - - exp = GNUNET_TIME_absolute_min (exp, rd[i].expiration); - + { + GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)); + exp = GNUNET_MIN (exp, rd[i].expiration_time); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got record of size %d\n", rd[i].data_size); - + "Got record of size %d expiration %u\n", + rd[i].data_size, rd[i].expiration_time); if ((record_xquery != 0) && (rd[i].record_type == record_xquery)) { record_match++; } } + et.abs_value = exp; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Verifying signature of %d records for name %s\n", - rd_count, name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Verifying signature of %d records for name %s with expiration of %u\n", + rd_count, name, et.abs_value); - if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature (&nrb->public_key, - exp, - name, - rd_count, - rd, - &nrb->signature)) + if (GNUNET_OK != + GNUNET_NAMESTORE_verify_signature (&nrb->public_key, + et, + name, + rd_count, + rd, + &nrb->signature)) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Signature invalid for name %s\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Signature invalid for %s\n", name); GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } @@ -187,8 +189,8 @@ block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type, if (NULL != bf) { - GNUNET_CRYPTO_hash(reply_block, reply_block_size, &chash); - GNUNET_BLOCK_mingle_hash(&chash, bf_mutator, &mhash); + GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); + GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); if (NULL != *bf) { if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test(*bf, &mhash)) @@ -218,27 +220,26 @@ block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type, static int block_plugin_gns_get_key (void *cls, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, - GNUNET_HashCode * key) + struct GNUNET_HashCode * key) { - if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD) - return GNUNET_SYSERR; - struct GNUNET_CRYPTO_ShortHashCode name_hash; struct GNUNET_CRYPTO_ShortHashCode pkey_hash; - GNUNET_HashCode name_hash_double; - GNUNET_HashCode pkey_hash_double; - - struct GNSNameRecordBlock *nrb = (struct GNSNameRecordBlock *)block; - - GNUNET_CRYPTO_short_hash(&nrb[1], strlen((char*)&nrb[1]), &name_hash); - GNUNET_CRYPTO_short_hash(&nrb->public_key, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &pkey_hash); - - GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double); - GNUNET_CRYPTO_short_hash_double(&pkey_hash, &pkey_hash_double); + const struct GNSNameRecordBlock *nrb = block; + const char *name; - GNUNET_CRYPTO_hash_xor(&name_hash_double, &pkey_hash_double, key); - + if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD) + return GNUNET_SYSERR; + name = (const char *) &nrb[1]; + if (NULL == memchr (name, '\0', + block_size - sizeof (struct GNSNameRecordBlock))) + { + /* malformed, no 0-termination in name */ + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + GNUNET_CRYPTO_short_hash (&nrb->public_key, + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &pkey_hash); + GNUNET_GNS_get_key_for_record (name, &pkey_hash, key); return GNUNET_OK; } diff --git a/src/gns/test_gns_cname_lookup.c b/src/gns/test_gns_cname_lookup.c new file mode 100644 index 0000000..6870e89 --- /dev/null +++ b/src/gns/test_gns_cname_lookup.c @@ -0,0 +1,449 @@ +/* + 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 gns/test_gns_cname_lookup.c + * @brief base testcase for testing a local GNS record lookup + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_testing_lib.h" +#include "gnunet_core_service.h" +#include "block_dns.h" +#include "gnunet_signatures.h" +#include "gnunet_namestore_service.h" +#include "gnunet_dnsparser_lib.h" +#include "gnunet_gns_service.h" + + +/** + * Timeout for entire testcase + */ +#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) + +/* test records to resolve */ +#define TEST_DOMAIN_PLUS "www.gads" +#define TEST_DOMAIN_ZKEY "www2.gads" +#define TEST_DOMAIN_DNS "www3.gads" +#define TEST_IP_PLUS "127.0.0.1" +#define TEST_IP_ZKEY "127.0.0.2" +#define TEST_IP_DNS "131.159.74.67" +#define TEST_RECORD_CNAME_SERVER "server.gads" +#define TEST_RECORD_CNAME_PLUS "server.+" +#define TEST_RECORD_CNAME_ZKEY "www.188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey" +#define TEST_RECORD_CNAME_DNS "gnunet.org" +#define TEST_RECORD_NAME_SERVER "server" +#define TEST_RECORD_NAME_PLUS "www" +#define TEST_RECORD_NAME_ZKEY "www2" +#define TEST_RECORD_NAME_DNS "www3" + +#define KEYFILE_BOB "zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey" + + +/* Task handle to use to schedule test failure */ +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +/* Global return value (0 for success, anything else for failure) */ +static int ok; + +static struct GNUNET_NAMESTORE_Handle *namestore_handle; + +static struct GNUNET_GNS_Handle *gns_handle; + +static const struct GNUNET_CONFIGURATION_Handle *cfg; + + +/** + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. + */ +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != gns_handle) + { + GNUNET_GNS_disconnect (gns_handle); + gns_handle = NULL; + } + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + ok = 1; +} + + +static void +shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_GNS_disconnect (gns_handle); + gns_handle = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); +} + + +static void +on_lookup_result_cname (void *cls, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + uint32_t i; + + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + if (rd_count == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup failed, rp_filtering?\n"); + ok = 2; + } + else + { + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls); + for (i=0; i<rd_count; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); + if (rd[i].record_type == GNUNET_GNS_RECORD_CNAME) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CNAME: %s\n", rd[i].data); + if (0 == strcmp(rd[i].data, TEST_RECORD_CNAME_SERVER)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "%s correctly resolved to %s!\n", TEST_DOMAIN_PLUS, rd[i].data); + ok = 0; + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n"); + } + } + } + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); +} + + +static void +on_lookup_result_dns (void *cls, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct in_addr a; + uint32_t i; + char* addr; + + if (rd_count == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "CNAME to DNS delegation failed. System offline?\n"); + } + else + { + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls); + for (i=0; i<rd_count; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); + if (rd[i].record_type == GNUNET_GNS_RECORD_A) + { + memcpy(&a, rd[i].data, sizeof(a)); + addr = inet_ntoa(a); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr); + if (0 == strcmp(addr, TEST_IP_DNS)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "%s correctly resolved to %s!\n", TEST_DOMAIN_DNS, addr); + ok = 0; + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n"); + } + } + } + GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN_PLUS, GNUNET_GNS_RECORD_CNAME, + GNUNET_YES, + NULL, + &on_lookup_result_cname, TEST_DOMAIN_PLUS); +} + + +static void +on_lookup_result_zkey (void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct in_addr a; + uint32_t i; + char* addr; + + if (rd_count == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup failed, rp_filtering?\n"); + ok = 2; + GNUNET_SCHEDULER_shutdown (); + return; + } + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "name: %s\n", (char*)cls); + for (i=0; i<rd_count; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "type: %d\n", rd[i].record_type); + if (rd[i].record_type == GNUNET_GNS_RECORD_A) + { + memcpy (&a, rd[i].data, sizeof(a)); + addr = inet_ntoa(a); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "address: %s\n", addr); + if (0 == strcmp (addr, TEST_IP_ZKEY)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "%s correctly resolved to %s!\n", + TEST_DOMAIN_ZKEY, addr); + ok = 0; + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No resolution!\n"); + } + } + GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN_DNS, GNUNET_GNS_RECORD_A, + GNUNET_YES, + NULL, + &on_lookup_result_dns, TEST_DOMAIN_DNS); +} + + +static void +on_lookup_result_plus (void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct in_addr a; + uint32_t i; + char* addr; + + if (rd_count == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup failed, rp_filtering?\n"); + ok = 2; + GNUNET_SCHEDULER_shutdown (); + return; + } + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls); + for (i=0; i<rd_count; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); + if (rd[i].record_type == GNUNET_GNS_RECORD_A) + { + memcpy(&a, rd[i].data, sizeof(a)); + addr = inet_ntoa(a); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr); + if (0 == strcmp(addr, TEST_IP_PLUS)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "%s correctly resolved to %s!\n", TEST_DOMAIN_PLUS, addr); + ok = 0; + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n"); + } + } + GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN_ZKEY, GNUNET_GNS_RECORD_A, + GNUNET_YES, + NULL, + &on_lookup_result_zkey, TEST_DOMAIN_ZKEY); +} + + +/** + * Function scheduled to be run on the successful start of services + * tries to look up the dns record for TEST_DOMAIN + * + * @param cls closure + * @param success GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) + * GNUNET_NO if content was already there or not found + * GNUNET_YES (or other positive value) on success + * @param emsg NULL on success, otherwise an error message + */ +static void +commence_testing (void *cls, int32_t success, const char *emsg) +{ + if (NULL != emsg) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to store record in namestore: %s\n", + emsg); + GNUNET_SCHEDULER_shutdown (); + return; + } + gns_handle = GNUNET_GNS_connect(cfg); + if (NULL == gns_handle) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to GNS!\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN_PLUS, GNUNET_GNS_RECORD_A, + GNUNET_YES, + NULL, + &on_lookup_result_plus, TEST_DOMAIN_PLUS); +} + + +static void +do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) +{ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; + struct GNUNET_CRYPTO_RsaPrivateKey *alice_key; + struct GNUNET_CRYPTO_RsaPrivateKey *bob_key; + char* alice_keyfile; + struct GNUNET_NAMESTORE_RecordData rd; + const char* ip = TEST_IP_PLUS; + struct in_addr web; + + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + + /* put records into namestore */ + namestore_handle = GNUNET_NAMESTORE_connect(cfg); + if (NULL == namestore_handle) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to namestore\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", + &alice_keyfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to get key from cfg\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + + alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile); + GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey); + GNUNET_free(alice_keyfile); + + bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB); + + rd.expiration_time = UINT64_MAX; + GNUNET_assert(1 == inet_pton (AF_INET, ip, &web)); + rd.data_size = sizeof(struct in_addr); + rd.data = &web; + rd.record_type = GNUNET_DNSPARSER_TYPE_A; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + + GNUNET_NAMESTORE_record_create (namestore_handle, + alice_key, + TEST_RECORD_NAME_SERVER, + &rd, + NULL, + NULL); + + rd.data_size = strlen (TEST_RECORD_CNAME_PLUS); + rd.data = TEST_RECORD_CNAME_PLUS; + rd.record_type = GNUNET_GNS_RECORD_CNAME; + + GNUNET_NAMESTORE_record_create (namestore_handle, + alice_key, + TEST_RECORD_NAME_PLUS, + &rd, + NULL, + NULL); + + rd.data_size = strlen (TEST_RECORD_CNAME_ZKEY); + rd.data = TEST_RECORD_CNAME_ZKEY; + rd.record_type = GNUNET_GNS_RECORD_CNAME; + + GNUNET_NAMESTORE_record_create (namestore_handle, + alice_key, + TEST_RECORD_NAME_ZKEY, + &rd, + NULL, + NULL); + + rd.data_size = strlen (TEST_RECORD_CNAME_DNS); + rd.data = TEST_RECORD_CNAME_DNS; + rd.record_type = GNUNET_GNS_RECORD_CNAME; + + GNUNET_NAMESTORE_record_create (namestore_handle, + alice_key, + TEST_RECORD_NAME_DNS, + &rd, + NULL, + NULL); + + GNUNET_assert(1 == inet_pton (AF_INET, TEST_IP_ZKEY, &web)); + rd.data_size = sizeof(struct in_addr); + rd.data = &web; + rd.record_type = GNUNET_DNSPARSER_TYPE_A; + + GNUNET_NAMESTORE_record_create (namestore_handle, + bob_key, + TEST_RECORD_NAME_PLUS, + &rd, + &commence_testing, + NULL); + GNUNET_CRYPTO_rsa_key_free(alice_key); + GNUNET_CRYPTO_rsa_key_free(bob_key); +} + + +int +main (int argc, char *argv[]) +{ + ok = 1; + + GNUNET_log_setup ("test-gns-simple-cname-lookup", + "WARNING", + NULL); + GNUNET_TESTING_peer_run ("test-gns-simple-cname-lookup", "test_gns_simple_lookup.conf", &do_check, NULL); + return ok; +} + +/* end of test_gns_cname_lookup.c */ diff --git a/src/gns/test_gns_defaults.conf b/src/gns/test_gns_defaults.conf index b7e68ff..0fba7ca 100644 --- a/src/gns/test_gns_defaults.conf +++ b/src/gns/test_gns_defaults.conf @@ -1,6 +1,5 @@ [PATHS] SERVICEHOME = /tmp/test-gnunet-testing/ -DEFAULTCONFIG = test_testing_defaults.conf [resolver] PORT = 2564 @@ -30,7 +29,7 @@ PORT = 2570 NUM_PEERS = 5 WEAKRANDOM = YES F2F = YES -HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat +HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat [dht] AUTOSTART = NO @@ -67,3 +66,6 @@ AUTOSTART = NO [vpn] AUTOSTART = NO + +[consensus] +AUTOSTART = NO diff --git a/src/gns/test_gns_dht_default.conf b/src/gns/test_gns_dht_default.conf index 1b37373..a14588c 100644 --- a/src/gns/test_gns_dht_default.conf +++ b/src/gns/test_gns_dht_default.conf @@ -1,14 +1,12 @@ @INLINE@ test_gns_defaults.conf [PATHS] SERVICEHOME = /tmp/test-gnunet-gns-dht/ -DEFAULTCONFIG = test_gns_dht_default.conf [transport-tcp] PORT = 22568 [dht] UNIXPATH = /tmp/gnunet-service-dht.sock -DEBUG = NO AUTOSTART = YES ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; @@ -25,7 +23,7 @@ DATABASE = sqlite [arm] PORT = 22566 -DEFAULTSERVICES = core namestore dht gns +DEFAULTSERVICES = core dht namestore gns UNIXPATH = /tmp/gnunet-default-service-arm.sock [statistics] @@ -60,19 +58,17 @@ DNS_EXIT = 8.8.8.8 [gns] PORT = 22370 -#PREFIX = valgrind -v --leak-check=full --track-origins=yes. +#PREFIX = valgrind -v --leak-check=full --track-origins=yes AUTOSTART = YES BINARY = gnunet-service-gns -ZONEKEY = $SERVICEHOME/zonekey.zkey +ZONEKEY = $SERVICEHOME/.hostkey HIJACK_DNS = NO UNIXPATH = /tmp/gnunet-service-gns-default.sock HOME = $SERVICEHOME -CONFIG = $DEFAULTCONFIG AUTO_IMPORT_PKEY = NO MAX_PARALLEL_BACKGROUND_QUERIES = 10 -DEFAULT_LOOKUP_TIMEOUT = 60 -RECORD_PUT_INTERVAL = 1 -ZONE_PUT_INTERVAL = 5 +DEFAULT_LOOKUP_TIMEOUT = 10 s +RECORD_PUT_INTERVAL = 2 s [namestore] PORT = 22371 @@ -82,7 +78,6 @@ UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES HOSTNAME = localhost HOME = $SERVICEHOME -CONFIG = $DEFAULTCONFIG BINARY = gnunet-service-namestore ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; diff --git a/src/gns/test_gns_dht_delegated_lookup.c b/src/gns/test_gns_dht_delegated_lookup.c index 882bb7e..1eb77d8 100644 --- a/src/gns/test_gns_dht_delegated_lookup.c +++ b/src/gns/test_gns_dht_delegated_lookup.c @@ -33,17 +33,14 @@ #include "gnunet_dht_service.h" #include "gnunet_gns_service.h" -/* DEFINES */ -#define VERBOSE GNUNET_YES - /* Timeout for entire testcase */ #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) -/* If number of peers not in config file, use this number */ -#define DEFAULT_NUM_PEERS 2 +/* Timeout for entire testcase */ +#define DHT_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10) /* test records to resolve */ -#define TEST_DOMAIN "www.bob.gnunet" +#define TEST_DOMAIN "www.bob.gads" #define TEST_IP "127.0.0.1" #define TEST_RECORD_NAME "www" @@ -53,17 +50,9 @@ #define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey" -/* Globals */ - -/** - * Directory to store temp data in, defined in config file - */ -static char *test_directory; - -static struct GNUNET_TESTING_PeerGroup *pg; - /* Task handle to use to schedule test failure */ -GNUNET_SCHEDULER_TaskIdentifier die_task; +static GNUNET_SCHEDULER_TaskIdentifier die_task; +static GNUNET_SCHEDULER_TaskIdentifier wait_task; /* Global return value (0 for success, anything else for failure) */ static int ok; @@ -74,27 +63,67 @@ static struct GNUNET_GNS_Handle *gns_handle; static struct GNUNET_DHT_Handle *dht_handle; -const struct GNUNET_CONFIGURATION_Handle *cfg; +static const struct GNUNET_CONFIGURATION_Handle *cfg; + +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; +static struct GNUNET_CRYPTO_RsaPrivateKey *alice_key; +static struct GNUNET_CRYPTO_RsaPrivateKey *bob_key; -struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; -struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; -struct GNUNET_CRYPTO_RsaPrivateKey *alice_key; -struct GNUNET_CRYPTO_RsaPrivateKey *bob_key; /** - * Check whether peers successfully shut down. + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. */ -void -shutdown_callback (void *cls, const char *emsg) +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - if (emsg != NULL) + die_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != gns_handle) + { + GNUNET_GNS_disconnect (gns_handle); + gns_handle = NULL; + } + + if (NULL != dht_handle) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok); - if (ok == 0) - ok = 2; + GNUNET_DHT_disconnect (dht_handle); + dht_handle = NULL; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok); + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + ok = 1; +} + + +static void +end_badly_now () +{ + + if (GNUNET_SCHEDULER_NO_TASK != wait_task) + { + GNUNET_SCHEDULER_cancel (wait_task); + wait_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + + +static void +shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_GNS_disconnect(gns_handle); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); } @@ -106,6 +135,14 @@ on_lookup_result(void *cls, uint32_t rd_count, int i; char* addr; + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; if (rd_count == 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -119,7 +156,7 @@ on_lookup_result(void *cls, uint32_t rd_count, for (i=0; i<rd_count; i++) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); - if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A) + if (rd[i].record_type == GNUNET_GNS_RECORD_A) { memcpy(&a, rd[i].data, sizeof(a)); addr = inet_ntoa(a); @@ -137,11 +174,10 @@ on_lookup_result(void *cls, uint32_t rd_count, } } } - GNUNET_GNS_disconnect(gns_handle); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); - //GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &shutdown_callback, NULL, - // GNUNET_YES, GNUNET_NO); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); + GNUNET_DHT_disconnect (dht_handle); + dht_handle = NULL; + + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } @@ -152,48 +188,22 @@ on_lookup_result(void *cls, uint32_t rd_count, static void commence_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES); - gns_handle = GNUNET_GNS_connect(cfg); if (NULL == gns_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to GNS!\n"); + end_badly_now(); + return; } - GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A, + GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_A, + GNUNET_NO, + NULL, &on_lookup_result, TEST_DOMAIN); } -/** - * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut - * down the peers without freeing memory associated with GET request. - */ -static void -end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - - if (pg != NULL) { - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - } - GNUNET_SCHEDULER_cancel (die_task); -} - -/** - * Check if the get_handle is being used, if so stop the request. Either - * way, schedule the end_badly_cont function which actually shuts down the - * test. - */ -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n", - (char *) cls); - GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); - ok = 1; -} - static void put_dht(void *cls, int32_t success, const char *emsg) @@ -201,9 +211,9 @@ put_dht(void *cls, int32_t success, const char *emsg) struct GNSNameRecordBlock *nrb; struct GNUNET_CRYPTO_ShortHashCode name_hash; struct GNUNET_CRYPTO_ShortHashCode zone_hash; - GNUNET_HashCode xor_hash; - GNUNET_HashCode name_hash_double; - GNUNET_HashCode zone_hash_double; + struct GNUNET_HashCode xor_hash; + struct GNUNET_HashCode name_hash_double; + struct GNUNET_HashCode zone_hash_double; uint32_t rd_payload_length; char* nrb_data = NULL; struct GNUNET_CRYPTO_RsaSignature *sig; @@ -211,14 +221,22 @@ put_dht(void *cls, int32_t success, const char *emsg) char* ip = TEST_IP; struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr)); - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + rd.expiration_time = UINT64_MAX; GNUNET_assert(1 == inet_pton (AF_INET, ip, web)); rd.data_size = sizeof(struct in_addr); rd.data = web; rd.record_type = GNUNET_DNSPARSER_TYPE_A; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; sig = GNUNET_NAMESTORE_create_signature(bob_key, GNUNET_TIME_UNIT_FOREVER_ABS, TEST_RECORD_NAME, &rd, 1); + + GNUNET_assert (GNUNET_OK == GNUNET_NAMESTORE_verify_signature (&bob_pkey, + GNUNET_TIME_UNIT_FOREVER_ABS, + TEST_RECORD_NAME, + 1, + &rd, + sig)); rd_payload_length = GNUNET_NAMESTORE_records_get_size (1, &rd); nrb = GNUNET_malloc(rd_payload_length + strlen(TEST_RECORD_NAME) + 1 + sizeof(struct GNSNameRecordBlock)); @@ -238,6 +256,8 @@ put_dht(void *cls, int32_t success, const char *emsg) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n"); ok = 3; GNUNET_free (nrb); + GNUNET_free (web); + end_badly_now (); return; } GNUNET_CRYPTO_short_hash(TEST_RECORD_NAME, strlen(TEST_RECORD_NAME), &name_hash); @@ -252,38 +272,43 @@ put_dht(void *cls, int32_t success, const char *emsg) strlen(TEST_RECORD_NAME) + 1; GNUNET_DHT_put (dht_handle, &xor_hash, 0, - GNUNET_DHT_RO_NONE, + GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_BLOCK_TYPE_GNS_NAMERECORD, rd_payload_length, (char*)nrb, - rd.expiration, + GNUNET_TIME_UNIT_FOREVER_ABS, DHT_OPERATION_TIMEOUT, NULL, NULL); + GNUNET_free (web); GNUNET_free (nrb); - GNUNET_SCHEDULER_add_delayed(TIMEOUT, &commence_testing, NULL); + GNUNET_free (sig); + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + } + wait_task = GNUNET_SCHEDULER_add_delayed(DHT_DELAY, &commence_testing, NULL); } + static void -do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *_cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) +do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) { - - char* alice_keyfile; struct GNUNET_CRYPTO_ShortHashCode bob_hash; - cfg = _cfg; - - GNUNET_SCHEDULER_cancel (die_task); + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); /* put records into namestore */ namestore_handle = GNUNET_NAMESTORE_connect(cfg); if (NULL == namestore_handle) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); - ok = -1; + end_badly_now (); return; } @@ -292,7 +317,7 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, if (NULL == dht_handle) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to dht\n"); - ok = -1; + end_badly_now (); return; } @@ -301,7 +326,7 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, &alice_keyfile)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; + end_badly_now (); return; } @@ -315,10 +340,11 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash); struct GNUNET_NAMESTORE_RecordData rd; - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + rd.expiration_time = UINT64_MAX; rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); rd.data = &bob_hash; rd.record_type = GNUNET_GNS_RECORD_PKEY; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; GNUNET_NAMESTORE_record_create (namestore_handle, alice_key, @@ -326,86 +352,20 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, &rd, &put_dht, NULL); - - - -} - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - cfg = c; - /* Get path from configuration file */ - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - /* Start alice */ - //d1 = GNUNET_TESTING_daemon_start(cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0, - // NULL, NULL, NULL, &do_lookup, NULL); - pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT, - NULL, NULL, &do_lookup, NULL, NULL, NULL, NULL); } -static int -check () -{ - int ret; - - /* Arguments for GNUNET_PROGRAM_run */ - char *const argv[] = { "test-gns-dht-delegated-lookup", /* Name to give running binary */ - "-c", - "test_gns_simple_lookup.conf", /* Config file to use */ -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - /* Run the run function as a new program */ - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-gns-dht-delegated-lookup", "nohelp", options, &run, - &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-gns-dht-delegated-lookup': Failed with error code %d\n", ret); - } - return ok; -} int main (int argc, char *argv[]) { - int ret; + ok = 1; - GNUNET_log_setup ("test-gns-simple-lookup", -#if VERBOSE - "DEBUG", -#else + GNUNET_log_setup ("test-gns-dht-delegated-lookup", "WARNING", -#endif NULL); - ret = check (); - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - return ret; + GNUNET_TESTING_peer_run ("test-gns-dht-delegated-lookup", "test_gns_simple_lookup.conf", &do_check, NULL); + return ok; } -/* end of test_gns_twopeer.c */ + +/* end of test_gns_dht_delegated_lookup.c */ diff --git a/src/gns/test_gns_dht_three_peers.c b/src/gns/test_gns_dht_three_peers.c new file mode 100644 index 0000000..49c9457 --- /dev/null +++ b/src/gns/test_gns_dht_three_peers.c @@ -0,0 +1,660 @@ +/* + 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 gns/test_gns_dht_threepeer.c + * @brief tests dht lookup over 3 peers + * + * topology: + * alice <----> bob <-----> dave + * + * alice queries for www.buddy.bob.gads + * + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_disk_lib.h" +#include "gnunet_testing_lib.h" +#include "gnunet_testbed_service.h" +#include "gnunet_core_service.h" +#include "gnunet_dht_service.h" +#include "block_dns.h" +#include "gnunet_signatures.h" +#include "gnunet_namestore_service.h" +#include "gnunet_dnsparser_lib.h" +#include "gnunet_gns_service.h" + +#define ZONE_PUT_WAIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10) + +#define TEST_DOMAIN "www.buddy.bob.gads" +#define TEST_IP "1.1.1.1" +#define TEST_DAVE_PSEU "hagbard" + + +/* Timeout for entire testcase */ +#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 60) +#define SETUP_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 60) + +/* Global return value (0 for success, anything else for failure) */ +static int ok; + +/* Task handle to use to schedule test failure */ +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +static GNUNET_SCHEDULER_TaskIdentifier wait_task; + +static GNUNET_SCHEDULER_TaskIdentifier setup_task; + +static struct GNUNET_CRYPTO_ShortHashCode dave_hash; + +static struct GNUNET_CRYPTO_ShortHashCode bob_hash; + +static struct GNUNET_TESTBED_Peer **cpeers; + +static struct GNUNET_GNS_Handle *gh; +static struct GNUNET_GNS_LookupRequest *lookup_handle; + +static struct GNUNET_TESTBED_Operation *get_cfg_ops[3]; +static struct GNUNET_TESTBED_Operation *topology_op; +static struct GNUNET_CONFIGURATION_Handle *cfg_handles[3]; +static struct GNUNET_NAMESTORE_Handle *nh[3]; + +static int dave_is_setup; +static int bob_is_setup; +static int alice_is_setup; + +/** + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. + */ +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + int c; + + if (GNUNET_SCHEDULER_NO_TASK != wait_task) + { + GNUNET_SCHEDULER_cancel (wait_task); + wait_task = GNUNET_SCHEDULER_NO_TASK; + } + + for (c = 0; c < 3; c++) + { + if (NULL != nh[c]) + { + GNUNET_NAMESTORE_disconnect(nh[c]); + nh[c] = NULL; + } + + if (NULL != get_cfg_ops[c]) + { + GNUNET_TESTBED_operation_done(get_cfg_ops[c]); + get_cfg_ops[c] = NULL; + } + if (NULL != cfg_handles[c]) + { + GNUNET_CONFIGURATION_destroy (cfg_handles[c]); + cfg_handles[c] = NULL; + } + } + if (NULL != topology_op) + { + GNUNET_TESTBED_operation_done (topology_op); + topology_op = NULL; + } + if (NULL != lookup_handle) + { + GNUNET_GNS_cancel_lookup_request (lookup_handle); + lookup_handle = NULL; + } + if (NULL != gh) + { + GNUNET_GNS_disconnect(gh); + gh = NULL; + } + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test failed \n"); + GNUNET_SCHEDULER_shutdown (); + ok = 1; +} + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Finished\n"); + int c; + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + + for (c = 0; c < 3; c++) + { + if (NULL != nh[c]) + { + GNUNET_NAMESTORE_disconnect(nh[c]); + nh[c] = NULL; + } + if (NULL != cfg_handles[c]) + { + GNUNET_CONFIGURATION_destroy (cfg_handles[c]); + cfg_handles[c] = NULL; + } + } + + if (NULL != gh) + { + GNUNET_GNS_disconnect(gh); + gh = NULL; + } + + if (0 == ok) + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test ended successful\n"); + else + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test failed\n"); + GNUNET_SCHEDULER_shutdown (); +} + +static void +setup_end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + setup_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout during setup, test failed\n"); + + if (NULL != topology_op) + { + GNUNET_TESTBED_operation_done (topology_op); + topology_op = NULL; + } + GNUNET_SCHEDULER_shutdown (); + ok = GNUNET_SYSERR; +} + +static void +end_now () +{ + GNUNET_SCHEDULER_add_now (&end, NULL); +} + + +static void +disconnect_ns (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + + GNUNET_NAMESTORE_disconnect (cls); + if (cls == nh[0]) + nh[0] = NULL; + if (cls == nh[1]) + nh[1] = NULL; + if (cls == nh[2]) + nh[2] = NULL; +} + + +static void +cont_ns (void* cls, int32_t s, const char* emsg) +{ + GNUNET_SCHEDULER_add_now (&disconnect_ns, cls); +} + +static void +on_lookup_result(void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + int i; + char* string_val; + + if (rd_count == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup failed!\n"); + ok = 2; + } + else + { + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls); + for (i=0; i<rd_count; i++) + { + string_val = GNUNET_NAMESTORE_value_to_string(rd[i].record_type, + rd[i].data, + rd[i].data_size); + if (0 == strcmp(string_val, TEST_IP)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "%s correctly resolved to %s!\n", TEST_DOMAIN, string_val); + ok = 0; + } + GNUNET_free (string_val); + } + } + end_now (); +} + +static void +commence_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + static int wait = 0; + wait++; + if ((ZONE_PUT_WAIT_TIME.rel_value / 1000) == wait) + { + fprintf (stderr, "\n"); + wait_task = GNUNET_SCHEDULER_NO_TASK; + lookup_handle = GNUNET_GNS_lookup(gh, TEST_DOMAIN, GNUNET_GNS_RECORD_A, + GNUNET_NO, + NULL, + &on_lookup_result, TEST_DOMAIN); + if (GNUNET_SCHEDULER_NO_TASK != die_task) + GNUNET_SCHEDULER_cancel(die_task); + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from lookup"); + } + else + { + fprintf (stderr, "."); + wait_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &commence_testing, NULL); + } +} + +void +all_connected () +{ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Created all connections! Waiting for PUTs\n"); + if (GNUNET_SCHEDULER_NO_TASK != setup_task) + { + GNUNET_SCHEDULER_cancel (setup_task); + setup_task = GNUNET_SCHEDULER_NO_TASK; + } + wait_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &commence_testing, NULL); +} + + +static void connect_peers () +{ + static int started; + started ++; + if (3 == started) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers started\n"); + + topology_op = + GNUNET_TESTBED_overlay_configure_topology (NULL, 3, cpeers, NULL, + NULL, + NULL, + GNUNET_TESTBED_TOPOLOGY_RING, + GNUNET_TESTBED_TOPOLOGY_OPTION_END); + } +} + +static int +setup_dave (const struct GNUNET_CONFIGURATION_Handle * cfg) +{ + char* keyfile; + struct GNUNET_CRYPTO_RsaPrivateKey *key; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; + struct in_addr *web; + struct GNUNET_NAMESTORE_RecordData rd; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up dave\n"); + cfg_handles[0] = GNUNET_CONFIGURATION_dup (cfg); + GNUNET_assert (NULL != cfg_handles[0]); + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", + &keyfile)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); + return GNUNET_SYSERR; + } + + key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + if (NULL == key) + { + + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); + GNUNET_free (keyfile); + return GNUNET_SYSERR; + } + nh[0] = GNUNET_NAMESTORE_connect (cfg_handles[0]); + if (NULL == nh[0]) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); + GNUNET_CRYPTO_rsa_key_free (key); + GNUNET_free (keyfile); + return GNUNET_SYSERR; + } + + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); + GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &dave_hash); + + rd.expiration_time = UINT64_MAX; + + web = GNUNET_malloc(sizeof(struct in_addr)); + GNUNET_assert(1 == inet_pton (AF_INET, TEST_IP, web)); + rd.data_size = sizeof(struct in_addr); + rd.data = web; + rd.record_type = GNUNET_GNS_RECORD_A; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + + GNUNET_NAMESTORE_record_create (nh[0], key, "www", &rd, NULL, NULL); + + rd.data_size = strlen(TEST_DAVE_PSEU); + rd.data = TEST_DAVE_PSEU; + rd.record_type = GNUNET_GNS_RECORD_PSEU; + + + GNUNET_NAMESTORE_record_create (nh[0], key, GNUNET_GNS_MASTERZONE_STR, &rd, &cont_ns, nh[0]); + + GNUNET_CRYPTO_rsa_key_free(key); + GNUNET_free(keyfile); + GNUNET_free(web); + dave_is_setup = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up dave done\n"); + return GNUNET_OK; +} + +static int +setup_bob (const struct GNUNET_CONFIGURATION_Handle * cfg) +{ + char* keyfile; + struct GNUNET_CRYPTO_RsaPrivateKey *key; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; + struct GNUNET_NAMESTORE_RecordData rd; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up bob\n"); + cfg_handles[1] = GNUNET_CONFIGURATION_dup (cfg); + GNUNET_assert (NULL != cfg_handles[1]); + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", + &keyfile)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); + return GNUNET_SYSERR; + } + + key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + if (NULL == key) + { + + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); + GNUNET_free (keyfile); + return GNUNET_SYSERR; + } + + nh[1] = GNUNET_NAMESTORE_connect (cfg_handles[1]); + if (NULL == nh[1]) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); + GNUNET_CRYPTO_rsa_key_free (key); + GNUNET_free (keyfile); + return GNUNET_SYSERR; + } + + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); + GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &bob_hash); + + rd.expiration_time = UINT64_MAX; + rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); + rd.data = &dave_hash; + rd.record_type = GNUNET_GNS_RECORD_PKEY; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + + GNUNET_NAMESTORE_record_create (nh[1], key, "buddy", &rd, &cont_ns, nh[1]); + + GNUNET_CRYPTO_rsa_key_free(key); + GNUNET_free(keyfile); + bob_is_setup = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up bob done\n"); + return GNUNET_OK; +} + +static int +setup_alice (const struct GNUNET_CONFIGURATION_Handle * cfg) +{ + char* keyfile; + struct GNUNET_CRYPTO_RsaPrivateKey *key; + struct GNUNET_NAMESTORE_RecordData rd; + + cfg_handles[2] = GNUNET_CONFIGURATION_dup (cfg); + GNUNET_assert (NULL != cfg); + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", + &keyfile)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); + return GNUNET_SYSERR; + } + + key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + if (NULL == key) + { + + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); + GNUNET_free (keyfile); + return GNUNET_SYSERR; + } + + nh[2] = GNUNET_NAMESTORE_connect (cfg_handles[2]); + if (NULL == nh[2]) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); + GNUNET_CRYPTO_rsa_key_free (key); + GNUNET_free (keyfile); + return GNUNET_SYSERR; + } + + rd.expiration_time = UINT64_MAX; + rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); + rd.data = &bob_hash; + rd.record_type = GNUNET_GNS_RECORD_PKEY; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + + GNUNET_NAMESTORE_record_create (nh[2], key, "bob", &rd, &cont_ns, nh[2]); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up alice gns\n"); + gh = GNUNET_GNS_connect (cfg_handles[2]); + if (NULL == gh) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to gns\n"); + GNUNET_CRYPTO_rsa_key_free (key); + GNUNET_free (keyfile); + return GNUNET_SYSERR; + } + + GNUNET_CRYPTO_rsa_key_free (key); + GNUNET_free (keyfile); + alice_is_setup = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up alice done\n"); + return GNUNET_OK; +} + +static void +end_badly_now () +{ + if (GNUNET_SCHEDULER_NO_TASK != die_task) + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + + +/** + * Callback to be called when the requested peer information is available + * + * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information() + * @param op the operation this callback corresponds to + * @param pinfo the result; will be NULL if the operation has failed + * @param emsg error message if the operation has failed; will be NULL if the + * operation is successfull + */ +static void +peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op, + const struct GNUNET_TESTBED_PeerInformation *pinfo, + const char *emsg) +{ + int res; + GNUNET_assert (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit); + if (GNUNET_NO == dave_is_setup) + res = setup_dave (pinfo->result.cfg); + else if (GNUNET_NO == bob_is_setup) + res = setup_bob (pinfo->result.cfg); + else + res = setup_alice (pinfo->result.cfg); + + if (get_cfg_ops[0] == op) + get_cfg_ops[0] = NULL; + else if (get_cfg_ops[1] == op) + get_cfg_ops[1] = NULL; + else + get_cfg_ops[2] = NULL; + GNUNET_TESTBED_operation_done (op); + op = NULL; + if (GNUNET_SYSERR == res) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup peer \n"); + end_badly_now(); + } + else + connect_peers (); + /*if (get_cfg_ops[0] == op) + { + GNUNET_assert (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit); + res = setup_dave (pinfo->result.cfg); + GNUNET_TESTBED_operation_done (get_cfg_ops[0]); + get_cfg_ops[0] = NULL; + if (GNUNET_SYSERR == res) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n"); + end_badly_now(); + } + else + { + connect_peers (); + } + } + else if (get_cfg_ops[1] == op) + { + GNUNET_assert (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit); + res = setup_bob (pinfo->result.cfg); + GNUNET_TESTBED_operation_done (get_cfg_ops[1]); + get_cfg_ops[1] = NULL; + if (GNUNET_SYSERR == res) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n"); + end_badly_now(); + } + else + { + connect_peers (); + } + } + else if (get_cfg_ops[2] == op) + { + GNUNET_assert (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit); + res = setup_alice (pinfo->result.cfg); + GNUNET_TESTBED_operation_done (get_cfg_ops[2]); + get_cfg_ops[2] = NULL; + if (GNUNET_SYSERR == res) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n"); + end_badly_now(); + } + else + { + connect_peers (); + } + }*/ +} + + +void testbed_master (void *cls, + unsigned int num_peers, + struct GNUNET_TESTBED_Peer **peers) +{ + GNUNET_assert (NULL != peers); + cpeers = peers; + + setup_task = GNUNET_SCHEDULER_add_delayed (SETUP_TIMEOUT, &setup_end_badly, NULL); + + /* peer 0: dave */ + GNUNET_assert (NULL != peers[0]); + get_cfg_ops[0] = GNUNET_TESTBED_peer_get_information (peers[0], + GNUNET_TESTBED_PIT_CONFIGURATION, + &peerinfo_cb, NULL); + + /* peer 1: bob */ + GNUNET_assert (NULL != peers[1]); + get_cfg_ops[1] = GNUNET_TESTBED_peer_get_information (peers[1], + GNUNET_TESTBED_PIT_CONFIGURATION, + &peerinfo_cb, NULL ); + + /* peer 2: alice */ + GNUNET_assert (NULL != peers[2]); + get_cfg_ops[2] = GNUNET_TESTBED_peer_get_information (peers[2], + GNUNET_TESTBED_PIT_CONFIGURATION, + &peerinfo_cb, NULL); + +} + +void testbed_controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) +{ + static int connections = 0; + + switch (event->type) + { + case GNUNET_TESTBED_ET_OPERATION_FINISHED: + /* This part will still be called when + GNUNET_TESTBED_peer_get_information() succeeds. However, the code is + now more relevant in operation completion callback */ + break; + case GNUNET_TESTBED_ET_CONNECT: + connections ++; + if (connections == 3) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers connected\n"); + GNUNET_TESTBED_operation_done (topology_op); + topology_op = NULL; + all_connected (); + } + break; + default: + /* whatever ... */ + break; + } +} + +int +main (int argc, char *argv[]) +{ + uint64_t event_mask; + ok = 0; + event_mask = 0; + event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); + event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); + (void) GNUNET_TESTBED_test_run ("test_gns_dht_three_peers", "test_gns_dht_default.conf", + 3, event_mask, + &testbed_controller_cb, NULL, + &testbed_master, NULL); + if (GNUNET_SYSERR == ok) + return 1; + return 0; +} + +/* end of test_gns_dht_three_peers.c */ + diff --git a/src/gns/test_gns_dht_threepeer.c b/src/gns/test_gns_dht_threepeer.c deleted file mode 100644 index ed9600f..0000000 --- a/src/gns/test_gns_dht_threepeer.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - 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 gns/test_gns_dht_threepeer.c - * @brief tests dht lookup over 3 peers - * - * topology: - * alice <----> bob <-----> dave - * - * alice queries for www.buddy.bob.gnunet - * - */ -#include "platform.h" -#include "gnunet_disk_lib.h" -#include "gnunet_testing_lib.h" -#include "gnunet_core_service.h" -#include "gnunet_dht_service.h" -#include "block_dns.h" -#include "gnunet_signatures.h" -#include "gnunet_namestore_service.h" -#include "gnunet_dnsparser_lib.h" -#include "gnunet_gns_service.h" - -/* DEFINES */ -#define VERBOSE GNUNET_YES - -/* Timeout for entire testcase */ -#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 180) -#define ZONE_PUT_WAIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30) - -/* If number of peers not in config file, use this number */ -#define DEFAULT_NUM_PEERS 2 - -#define TEST_DOMAIN "www.buddy.bob.gnunet" -#define TEST_IP "1.1.1.1" -#define TEST_DAVE_PSEU "hagbard" -#define TEST_NUM_PEERS 3 -#define TEST_NUM_CON 3 - -/* Globals */ - -/** - * Directory to store temp data in, defined in config file - */ -static char *test_directory; - -/** - * Variable used to store the number of connections we should wait for. - */ -static unsigned int expected_connections; - -/** - * Variable used to keep track of how many peers aren't yet started. - */ -static unsigned long long peers_left; - -struct GNUNET_TESTING_Daemon *d1; -struct GNUNET_TESTING_Daemon *d2; -struct GNUNET_TESTING_Daemon *d3; - - -/** - * Total number of peers to run, set based on config file. - */ -static unsigned long long num_peers; - -/** - * Global used to count how many connections we have currently - * been notified about (how many times has topology_callback been called - * with success?) - */ -static unsigned int total_connections; - -/** - * Global used to count how many failed connections we have - * been notified about (how many times has topology_callback - * been called with failure?) - */ -static unsigned int failed_connections; - -/* Task handle to use to schedule test failure */ -GNUNET_SCHEDULER_TaskIdentifier die_task; - -GNUNET_SCHEDULER_TaskIdentifier bob_task; - -/* Global return value (0 for success, anything else for failure) */ -static int ok; - -int bob_online, alice_online, dave_online; - -const struct GNUNET_CONFIGURATION_Handle *alice_cfg; -struct GNUNET_CONFIGURATION_Handle *cfg_bob; -struct GNUNET_CONFIGURATION_Handle *cfg_dave; - -struct GNUNET_CRYPTO_ShortHashCode bob_hash; -struct GNUNET_CRYPTO_ShortHashCode dave_hash; -struct GNUNET_TESTING_Daemon *alice_daemon; -struct GNUNET_TESTING_Daemon *bob_daemon; -struct GNUNET_TESTING_Daemon *dave_daemon; - -struct GNUNET_TESTING_PeerGroup *pg; -struct GNUNET_GNS_Handle *gh; - -/** - * Function scheduled to be run on the successful completion of this - * testcase. Specifically, called when our get request completes. - */ -static void -finish_testing (void *cls, const char *emsg) -{ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test finished! (ret=%d)\n", ok); -} - -/** - * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut - * down the peers without freeing memory associated with GET request. - */ -static void -end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - die_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &finish_testing, NULL); -} - -/** - * Check if the get_handle is being used, if so stop the request. Either - * way, schedule the end_badly_cont function which actually shuts down the - * test. - */ -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - die_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Failing test with error: `%s'!\n", - (char *) cls); - die_task = GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); - ok = 1; -} - - -static void -on_lookup_result(void *cls, uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - int i; - char* string_val; - const char* typename; - - if (rd_count == 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Lookup failed!\n"); - ok = 2; - } - else - { - ok = 1; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls); - for (i=0; i<rd_count; i++) - { - typename = GNUNET_NAMESTORE_number_to_typename (rd[i].record_type); - string_val = GNUNET_NAMESTORE_value_to_string(rd[i].record_type, - rd[i].data, - rd[i].data_size); - printf("Got %s record: %s\n", typename, string_val); - if (0 == strcmp(string_val, TEST_IP)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "%s correctly resolved to %s!\n", TEST_DOMAIN, string_val); - ok = 0; - } - } - } - GNUNET_GNS_disconnect(gh); - GNUNET_SCHEDULER_cancel(die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &finish_testing, NULL); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down!\n"); - -} - -static void -commence_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - - - gh = GNUNET_GNS_connect(alice_cfg); - - GNUNET_GNS_lookup(gh, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A, - &on_lookup_result, TEST_DOMAIN); - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from lookup"); -} - - -/** - * This function is called whenever a connection attempt is finished between two of - * the started peers (started with GNUNET_TESTING_daemons_start). The total - * number of times this function is called should equal the number returned - * from the GNUNET_TESTING_connect_topology call. - * - * The emsg variable is NULL on success (peers connected), and non-NULL on - * failure (peers failed to connect). - */ -void -daemon_connected (void *cls, const struct GNUNET_PeerIdentity *first, - const struct GNUNET_PeerIdentity *second, uint32_t distance, - const struct GNUNET_CONFIGURATION_Handle *first_cfg, - const struct GNUNET_CONFIGURATION_Handle *second_cfg, - struct GNUNET_TESTING_Daemon *first_daemon, - struct GNUNET_TESTING_Daemon *second_daemon, - const char *emsg) -{ - if (emsg == NULL) - { - total_connections++; -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "connected peer %s to peer %s, distance %u\n", - first_daemon->shortname, second_daemon->shortname, distance); -#endif - } -#if VERBOSE - else - { - failed_connections++; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Failed to connect peer %s to peer %s with error :\n%s\n", - first_daemon->shortname, second_daemon->shortname, emsg); - } -#endif - - if (total_connections == expected_connections) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Created %d total connections, which is our target number! Starting next phase of testing.\n", - total_connections); -#endif - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - //die_task = - // GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from connect"); - - //commence_testing(); - - } - else if (total_connections + failed_connections == expected_connections) - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = - GNUNET_SCHEDULER_add_now (&end_badly, - "from topology_callback (too many failed connections)"); - } -} - -void -all_connected(void *cls, const char *emsg) -{ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Created all connections! Starting next phase of testing.\n"); - GNUNET_SCHEDULER_add_delayed (ZONE_PUT_WAIT_TIME, &commence_testing, NULL); -} - -void -ns_create_cont(void *cls, int32_t s, const char *emsg) -{ - GNUNET_NAMESTORE_disconnect((struct GNUNET_NAMESTORE_Handle *)cls, 0); -} - -static void -daemon_started (void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - struct GNUNET_NAMESTORE_Handle *ns; - char* keyfile; - struct GNUNET_CRYPTO_RsaPrivateKey *key; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; - struct in_addr *web; - struct GNUNET_NAMESTORE_RecordData rd; - - rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE; - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; - - if (NULL == dave_daemon) - { - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", - "ZONEKEY", - &keyfile)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; - return; - } - dave_daemon = d; - - key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is now dave\n"); - ns = GNUNET_NAMESTORE_connect(cfg); - - GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); - GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &dave_hash); - - web = GNUNET_malloc(sizeof(struct in_addr)); - GNUNET_assert(1 == inet_pton (AF_INET, TEST_IP, web)); - rd.data_size = sizeof(struct in_addr); - rd.data = web; - rd.record_type = GNUNET_GNS_RECORD_TYPE_A; - - GNUNET_NAMESTORE_record_create (ns, key, "www", &rd, NULL, NULL); - - rd.data_size = strlen(TEST_DAVE_PSEU); - rd.data = TEST_DAVE_PSEU; - rd.record_type = GNUNET_GNS_RECORD_PSEU; - - GNUNET_NAMESTORE_record_create (ns, key, "+", &rd, ns_create_cont, ns); - - GNUNET_CRYPTO_rsa_key_free(key); - GNUNET_free(keyfile); - GNUNET_free(web); - - return; - } - - - if (NULL == bob_daemon) - { - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", - "ZONEKEY", - &keyfile)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; - return; - } - bob_daemon = d; - - key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is now bob\n"); - ns = GNUNET_NAMESTORE_connect(cfg); - - GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); - GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &bob_hash); - - rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); - rd.data = &dave_hash; - rd.record_type = GNUNET_GNS_RECORD_PKEY; - - GNUNET_NAMESTORE_record_create (ns, key, "buddy", &rd, ns_create_cont, ns); - - GNUNET_CRYPTO_rsa_key_free(key); - GNUNET_free(keyfile); - - return; - } - - - - if (NULL == alice_daemon) - { - - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", - "ZONEKEY", - &keyfile)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; - return; - } - alice_daemon = d; - alice_cfg = cfg; - - key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is now alice\n"); - ns = GNUNET_NAMESTORE_connect(cfg); - - rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); - rd.data = &bob_hash; - rd.record_type = GNUNET_GNS_RECORD_PKEY; - - GNUNET_NAMESTORE_record_create (ns, key, "bob", &rd, ns_create_cont, ns); - - GNUNET_CRYPTO_rsa_key_free(key); - GNUNET_free(keyfile); - - GNUNET_TESTING_connect_topology (pg, GNUNET_TESTING_TOPOLOGY_CLIQUE, - GNUNET_TESTING_TOPOLOGY_OPTION_ALL, - 0, - TIMEOUT, - 3, - &all_connected, NULL); - return; - - } - - - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is a random guy\n"); -} - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - - /* Get path from configuration file */ - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "starting\n"); - - /* Get number of peers to start from configuration (should be two) */ - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", - &num_peers)) - num_peers = DEFAULT_NUM_PEERS; - - /* Set peers_left so we know when all peers started */ - peers_left = num_peers; - - bob_daemon = NULL; - dave_daemon = NULL; - alice_daemon = NULL; - - pg = GNUNET_TESTING_daemons_start (cfg, TEST_NUM_PEERS, TEST_NUM_CON, - TEST_NUM_CON, TIMEOUT, NULL, NULL, &daemon_started, NULL, - &daemon_connected, NULL, NULL); - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - alice_online = 0; - bob_online = 0; - dave_online = 0; - expected_connections = 2; - - /* Start alice */ - //d1 = GNUNET_TESTING_daemon_start(cfg_alice, TIMEOUT, GNUNET_NO, NULL, NULL, 0, - // NULL, NULL, NULL, &alice_started, NULL); - - - - -} - -static int -check () -{ - int ret; - - /* Arguments for GNUNET_PROGRAM_run */ - char *const argv[] = { "test-gns-twopeer", /* Name to give running binary */ - "-c", - "test_gns_dht_default.conf", /* Config file to use */ -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - /* Run the run function as a new program */ - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-gns-threepeer", "nohelp", options, &run, - &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-gns-threepeer': Failed with error code %d\n", ret); - } - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-gns-threepeer", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret = check (); - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - return ret; -} - -/* end of test_gns_threepeer.c */ diff --git a/src/gns/test_gns_max_queries.c b/src/gns/test_gns_max_queries.c index ad1743c..00caf83 100644 --- a/src/gns/test_gns_max_queries.c +++ b/src/gns/test_gns_max_queries.c @@ -32,18 +32,13 @@ #include "gnunet_dnsparser_lib.h" #include "gnunet_gns_service.h" -/* DEFINES */ -#define VERBOSE GNUNET_YES /* Timeout for entire testcase */ #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) -/* If number of peers not in config file, use this number */ -#define DEFAULT_NUM_PEERS 2 - /* test records to resolve */ -#define TEST_DOMAIN "www.gnunet" -#define TEST_DOMAIN_NACK "doesnotexist.bob.gnunet" +#define TEST_DOMAIN "www.gads" +#define TEST_DOMAIN_NACK "doesnotexist.bob.gads" #define TEST_IP "127.0.0.1" #define TEST_RECORD_NAME "www" #define TEST_ADDITIONAL_LOOKUPS 5 @@ -51,17 +46,8 @@ #define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey" -/* Globals */ - -/** - * Directory to store temp data in, defined in config file - */ -static char *test_directory; - -static struct GNUNET_TESTING_PeerGroup *pg; - /* Task handle to use to schedule test failure */ -GNUNET_SCHEDULER_TaskIdentifier die_task; +static GNUNET_SCHEDULER_TaskIdentifier die_task; /* Global return value (0 for success, anything else for failure) */ static int ok; @@ -70,30 +56,89 @@ static struct GNUNET_NAMESTORE_Handle *namestore_handle; static struct GNUNET_GNS_Handle *gns_handle; -const struct GNUNET_CONFIGURATION_Handle *cfg; +static const struct GNUNET_CONFIGURATION_Handle *cfg; static unsigned long long max_parallel_lookups; +static struct GNUNET_GNS_LookupRequest **requests; + +static unsigned int num_requests; + + /** - * Check whether peers successfully shut down. + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. */ -void -shutdown_callback (void *cls, const char *emsg) +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - if (emsg != NULL) + unsigned int i; + + for (i=0;i<num_requests;i++) + if (NULL != requests[i]) + GNUNET_GNS_cancel_lookup_request (requests[i]); + die_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != gns_handle) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok); - if (ok == 0) - ok = 2; + GNUNET_GNS_disconnect(gns_handle); + gns_handle = NULL; } + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + GNUNET_free (requests); + ok = 1; +} - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok); + +static void +shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + unsigned int i; + + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + for (i=0;i<num_requests;i++) + if (NULL != requests[i]) + GNUNET_GNS_cancel_lookup_request (requests[i]); + if (NULL != gns_handle) + { + GNUNET_GNS_disconnect (gns_handle); + gns_handle = NULL; + } + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); + GNUNET_free (requests); } + static void -on_lookup_result_dummy(void *cls, uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +on_lookup_result_dummy (void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { + struct GNUNET_GNS_LookupRequest **request = cls; + static int replies = 0; + + *request = NULL; + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + } if (rd_count != 0) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, @@ -101,16 +146,29 @@ on_lookup_result_dummy(void *cls, uint32_t rd_count, rd_count); ok = -1; } + replies++; + fprintf (stderr, "."); } + static void -on_lookup_result(void *cls, uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +on_lookup_result (void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { struct in_addr a; int i; char* addr; + requests[max_parallel_lookups + TEST_ADDITIONAL_LOOKUPS] = NULL; + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + fprintf (stderr, "\n"); if (rd_count == 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -124,7 +182,7 @@ on_lookup_result(void *cls, uint32_t rd_count, for (i=0; i<rd_count; i++) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); - if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A) + if (rd[i].record_type == GNUNET_GNS_RECORD_A) { memcpy(&a, rd[i].data, sizeof(a)); addr = inet_ntoa(a); @@ -142,11 +200,7 @@ on_lookup_result(void *cls, uint32_t rd_count, } } } - GNUNET_GNS_disconnect(gns_handle); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); - //GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &shutdown_callback, NULL, - // GNUNET_YES, GNUNET_NO); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } @@ -158,9 +212,8 @@ static void commence_testing (void *cls, int32_t success, const char *emsg) { int i; - char lookup_name[MAX_DNS_NAME_LENGTH]; - - GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES); + char lookup_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + struct GNUNET_GNS_LookupRequest *lr; gns_handle = GNUNET_GNS_connect(cfg); @@ -176,48 +229,28 @@ commence_testing (void *cls, int32_t success, const char *emsg) for (i=0; i<max_parallel_lookups+TEST_ADDITIONAL_LOOKUPS; i++) { GNUNET_snprintf(lookup_name, - MAX_DNS_NAME_LENGTH, - "www.doesnotexist-%d.bob.gnunet", i); - GNUNET_GNS_lookup(gns_handle, lookup_name, GNUNET_GNS_RECORD_TYPE_A, - &on_lookup_result_dummy, NULL); + GNUNET_DNSPARSER_MAX_NAME_LENGTH, + "www.doesnotexist-%d.bob.gads", i); + lr = GNUNET_GNS_lookup (gns_handle, lookup_name, GNUNET_GNS_RECORD_A, + GNUNET_NO, + NULL, + &on_lookup_result_dummy, &requests[num_requests]); + requests[num_requests++] = lr; } - - GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A, - &on_lookup_result, TEST_DOMAIN); + lr = GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_A, + GNUNET_NO, + NULL, + &on_lookup_result, TEST_DOMAIN); + requests[num_requests++] = lr; + GNUNET_assert (num_requests == max_parallel_lookups + TEST_ADDITIONAL_LOOKUPS + 1); } -/** - * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut - * down the peers without freeing memory associated with GET request. - */ -static void -end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - - if (pg != NULL) - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - GNUNET_SCHEDULER_cancel (die_task); -} -/** - * Check if the get_handle is being used, if so stop the request. Either - * way, schedule the end_badly_cont function which actually shuts down the - * test. - */ static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n", - (char *) cls); - GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); - ok = 1; -} - -static void -do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *_cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) +do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) { struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; @@ -226,16 +259,16 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, char* alice_keyfile; struct GNUNET_CRYPTO_ShortHashCode bob_hash; - cfg = _cfg; + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); - GNUNET_SCHEDULER_cancel (die_task); /* put records into namestore */ namestore_handle = GNUNET_NAMESTORE_connect(cfg); if (NULL == namestore_handle) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); - ok = -1; + GNUNET_SCHEDULER_shutdown (); return; } @@ -244,20 +277,21 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, &alice_keyfile)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; + GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "gns", - "MAX_PARALLEL_BACKGROUND_QUERIES", - &max_parallel_lookups)) + "MAX_PARALLEL_BACKGROUND_QUERIES", + &max_parallel_lookups)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get max queries from cfg\n"); - ok = -1; + GNUNET_SCHEDULER_shutdown (); GNUNET_free (alice_keyfile); return; } - + requests = GNUNET_malloc ((max_parallel_lookups + TEST_ADDITIONAL_LOOKUPS + 1) * + sizeof (struct GNUNET_GNS_LookupRequest *)); alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile); bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB); @@ -269,11 +303,12 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, struct GNUNET_NAMESTORE_RecordData rd; char* ip = TEST_IP; struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr)); - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + rd.expiration_time = UINT64_MAX; GNUNET_assert(1 == inet_pton (AF_INET, ip, web)); rd.data_size = sizeof(struct in_addr); rd.data = web; rd.record_type = GNUNET_DNSPARSER_TYPE_A; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; GNUNET_NAMESTORE_record_create (namestore_handle, alice_key, @@ -300,82 +335,18 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, } -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - cfg = c; - /* Get path from configuration file */ - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - /* Start alice */ - //d1 = GNUNET_TESTING_daemon_start(cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0, - // NULL, NULL, NULL, &do_lookup, NULL); - pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT, - NULL, NULL, &do_lookup, NULL, - NULL, NULL, NULL); -} - -static int -check () -{ - int ret; - - /* Arguments for GNUNET_PROGRAM_run */ - char *const argv[] = { "test-gns-max-queries", /* Name to give running binary */ - "-c", - "test_gns_simple_lookup.conf", /* Config file to use */ -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - /* Run the run function as a new program */ - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-gns-max-queries", "nohelp", options, &run, - &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-gns-simple-lookup': Failed with error code %d\n", ret); - } - return ok; -} int main (int argc, char *argv[]) { - int ret; + ok = 1; - GNUNET_log_setup ("test-gns-simple-lookup", -#if VERBOSE - "DEBUG", -#else + GNUNET_log_setup ("test-gns-max-queries", "WARNING", -#endif NULL); - ret = check (); - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - return ret; + GNUNET_TESTING_peer_run ("test-gns-max-queries", "test_gns_simple_lookup.conf", &do_check, NULL); + return ok; } -/* end of test_gns_twopeer.c */ + +/* end of test_gns_simple_zkey_lookup.c */ diff --git a/src/gns/test_gns_ns_lookup.c b/src/gns/test_gns_ns_lookup.c new file mode 100644 index 0000000..42d8f68 --- /dev/null +++ b/src/gns/test_gns_ns_lookup.c @@ -0,0 +1,446 @@ +/* + 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 gns/test_gns_ns_lookup.c + * @brief base testcase for testing a local GNS record lookup through NS + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_testing_lib.h" +#include "gnunet_core_service.h" +#include "block_dns.h" +#include "gnunet_signatures.h" +#include "gnunet_namestore_service.h" +#include "gnunet_resolver_service.h" +#include "gnunet_dnsparser_lib.h" +#include "gnunet_gns_service.h" + +/* Timeout for entire testcase */ +#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) + +/* test records to resolve */ +#define TEST_DOMAIN "www.homepage.gads" +#define TEST_DOMAIN_ALT "homepage.gads" +#define TEST_DOMAIN_ALT2 "uk.homepage.gads" +#define TEST_IP_ALT2 "81.187.252.184" +#define TEST_IP "131.159.74.67" +#define TEST_IP_NS "216.69.185.1" //ns01.domaincontrol.com +#define TEST_RECORD_NAME "homepage" +#define TEST_RECORD_NS "gnunet.org" + +/* Task handle to use to schedule test failure */ +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +/* Global return value (0 for success, anything else for failure) */ +static int ok; + +static int resolver_working; + +static struct GNUNET_NAMESTORE_Handle *namestore_handle; + +static struct GNUNET_GNS_Handle *gns_handle; + +static struct GNUNET_RESOLVER_RequestHandle *resolver_handle; + +static const struct GNUNET_CONFIGURATION_Handle *cfg; + +static struct GNUNET_GNS_LookupRequest *lr; + + +/** + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. + */ +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test failed, shutting down...\n"); + if (NULL != lr) + { + GNUNET_GNS_cancel_lookup_request (lr); + lr = NULL; + } + if (NULL != resolver_handle) + { + GNUNET_RESOLVER_request_cancel (resolver_handle); + resolver_handle = NULL; + } + if (NULL != gns_handle) + { + GNUNET_GNS_disconnect(gns_handle); + gns_handle = NULL; + } + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + ok = 1; +} + + +static void +end_badly_now () +{ + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + + +static void +end_now (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Test successful, shutting down...\n"); + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + if (NULL != resolver_handle) + { + GNUNET_RESOLVER_request_cancel (resolver_handle); + resolver_handle = NULL; + } + if (NULL != gns_handle) + { + GNUNET_GNS_disconnect(gns_handle); + gns_handle = NULL; + } + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); +} + + +static void +on_lookup_result_alt2 (void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct in_addr a; + uint32_t i; + char* addr; + + lr = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received alternative results 2\n"); + if (rd_count == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup failed\n"); + ok = 2; + } + else + { + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls); + for (i=0; i<rd_count; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); + if (rd[i].record_type == GNUNET_GNS_RECORD_A) + { + memcpy(&a, rd[i].data, sizeof(a)); + addr = inet_ntoa(a); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr); + if (0 == strcmp(addr, TEST_IP_ALT2)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "%s correctly resolved to %s!\n", TEST_DOMAIN, addr); + ok = 0; + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n"); + } + } + } + GNUNET_SCHEDULER_add_now (&end_now, NULL); +} + + +static void +on_lookup_result_alt (void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct in_addr a; + uint32_t i; + char* addr; + + lr = NULL; + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received alternative results\n"); + if (rd_count == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup failed\n"); + ok = 2; + } + else + { + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls); + for (i=0; i<rd_count; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); + if (rd[i].record_type == GNUNET_GNS_RECORD_A) + { + memcpy(&a, rd[i].data, sizeof(a)); + addr = inet_ntoa(a); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr); + if (0 == strcmp(addr, TEST_IP)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "%s correctly resolved to %s!\n", TEST_DOMAIN, addr); + ok = 0; + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n"); + } + } + } + + lr = GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN_ALT2, GNUNET_GNS_RECORD_A, + GNUNET_YES, + NULL, + &on_lookup_result_alt2, TEST_DOMAIN_ALT2); +} + + +static void +on_lookup_result(void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct in_addr a; + uint32_t i; + char* addr; + + lr = NULL; + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received results\n"); + if (rd_count == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup failed\n"); + ok = 2; + } + else + { + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls); + for (i=0; i<rd_count; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); + if (rd[i].record_type == GNUNET_GNS_RECORD_A) + { + memcpy(&a, rd[i].data, sizeof(a)); + addr = inet_ntoa(a); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr); + if (0 == strcmp(addr, TEST_IP)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "%s correctly resolved to %s!\n", TEST_DOMAIN, addr); + ok = 0; + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n"); + } + } + } + + lr = GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN_ALT, GNUNET_GNS_RECORD_A, + GNUNET_YES, + NULL, + &on_lookup_result_alt, TEST_DOMAIN_ALT); +} + + +static void +start_lookup () +{ + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + + gns_handle = GNUNET_GNS_connect (cfg); + if (NULL == gns_handle) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to GNS!\n"); + end_badly_now (); + return; + } + + lr = GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_A, + GNUNET_YES, + NULL, + &on_lookup_result, TEST_DOMAIN); +} + + +static void +handle_dns_test (void *cls, + const struct sockaddr *addr, + socklen_t addrlen) +{ + struct sockaddr_in* sai; + + resolver_handle = NULL; + if (NULL == addr) + { + /* end of results */ + if (GNUNET_YES != resolver_working) + { + ok = 0; + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "System resolver not working. Test inconclusive!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); + GNUNET_SCHEDULER_add_now (&end_now, NULL); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting lookup \n"); + start_lookup (); + return; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received DNS response\n"); + if (addrlen == sizeof (struct sockaddr_in)) + { + sai = (struct sockaddr_in*) addr; + if (0 == strcmp (TEST_IP, inet_ntoa (sai->sin_addr))) + { + resolver_working = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Resolver is working\n"); + } + } +} + + +/** + * Function scheduled to be run on the successful start of services + * tries to look up the dns record for TEST_DOMAIN + */ +static void +commence_testing (void *cls, int32_t success, const char *emsg) +{ + resolver_working = GNUNET_NO; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Resolving NS record\n"); + GNUNET_RESOLVER_connect (cfg); + resolver_handle = GNUNET_RESOLVER_ip_get (TEST_RECORD_NS, + AF_INET, + TIMEOUT, + &handle_dns_test, + NULL); +} + + +static void +do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) +{ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; + struct GNUNET_CRYPTO_RsaPrivateKey *alice_key; + char* alice_keyfile; + struct GNUNET_NAMESTORE_RecordData rd; + const char* ip = TEST_IP_NS; + struct in_addr ns; + + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + + /* put records into namestore */ + namestore_handle = GNUNET_NAMESTORE_connect(cfg); + if (NULL == namestore_handle) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to namestore\n"); + end_badly_now (); + return; + } + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", + &alice_keyfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to get key from cfg\n"); + end_badly_now (); + return; + } + + alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile); + GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey); + GNUNET_free(alice_keyfile); + + rd.expiration_time = UINT64_MAX; + GNUNET_assert(1 == inet_pton (AF_INET, ip, &ns)); + rd.data_size = sizeof(struct in_addr); + rd.data = &ns; + rd.record_type = GNUNET_DNSPARSER_TYPE_A; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Creating records\n"); + GNUNET_NAMESTORE_record_create (namestore_handle, + alice_key, + TEST_RECORD_NAME, + &rd, + NULL, + NULL); + rd.data_size = strlen (TEST_RECORD_NS); + rd.data = TEST_RECORD_NS; + rd.record_type = GNUNET_GNS_RECORD_NS; + GNUNET_NAMESTORE_record_create (namestore_handle, + alice_key, + TEST_RECORD_NAME, + &rd, + &commence_testing, + NULL); + GNUNET_CRYPTO_rsa_key_free(alice_key); +} + + +int +main (int argc, char *argv[]) +{ + ok = 1; + GNUNET_log_setup ("test-gns-simple-ns-lookup", + "WARNING", + NULL); + GNUNET_TESTING_peer_run ("test-gns-simple-ns-lookup", "test_gns_simple_lookup.conf", + &do_check, NULL); + return ok; +} + +/* end of test_gns_ns_lookup.c */ diff --git a/src/gns/test_gns_pseu_shorten.c b/src/gns/test_gns_pseu_shorten.c index 3c2d204..5e2f1fc 100644 --- a/src/gns/test_gns_pseu_shorten.c +++ b/src/gns/test_gns_pseu_shorten.c @@ -33,44 +33,33 @@ #include "gnunet_dht_service.h" #include "gnunet_gns_service.h" -/* DEFINES */ -#define VERBOSE GNUNET_YES - /* Timeout for entire testcase */ -#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5) - -/* If number of peers not in config file, use this number */ -#define DEFAULT_NUM_PEERS 2 +#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30) /* test records to resolve */ -#define TEST_DOMAIN "www.alice.bob.gnunet" +#define TEST_DOMAIN "www.alicewonderland.bobbuilder.gads" #define TEST_IP "127.0.0.1" #define TEST_RECORD_NAME "www" -#define TEST_AUTHORITY_BOB "bob" -#define TEST_AUTHORITY_ALICE "alice" +#define TEST_PRIVATE_ZONE "private" +#define TEST_SHORTEN_ZONE "short" +#define TEST_AUTHORITY_BOB "bobbuilder" +#define TEST_AUTHORITY_ALICE "alicewonderland" #define TEST_PSEU_ALICE "carol" -#define TEST_EXPECTED_RESULT "www.carol.gnunet" +#define TEST_EXPECTED_RESULT "www.carol.short.private.gads" #define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) +#define KEYFILE_SHORTEN = "zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey" +#define KEYFILE_PRIVATE = "zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey" #define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey" #define KEYFILE_ALICE "../namestore/zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey" /* Globals */ -/** - * Directory to store temp data in, defined in config file - */ -static char *test_directory; - -static struct GNUNET_TESTING_PeerGroup *pg; - /* Task handle to use to schedule test failure */ static GNUNET_SCHEDULER_TaskIdentifier die_task; -static GNUNET_SCHEDULER_TaskIdentifier disco_task; - /* Global return value (0 for success, anything else for failure) */ static int ok; @@ -80,47 +69,73 @@ static struct GNUNET_GNS_Handle *gns_handle; static struct GNUNET_DHT_Handle *dht_handle; -const struct GNUNET_CONFIGURATION_Handle *cfg; +static const struct GNUNET_CONFIGURATION_Handle *cfg; + +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded our_pkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded priv_pkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded short_pkey; +static struct GNUNET_CRYPTO_RsaPrivateKey *alice_key; +static struct GNUNET_CRYPTO_RsaPrivateKey *bob_key; +static struct GNUNET_CRYPTO_RsaPrivateKey *our_key; +static struct GNUNET_CRYPTO_RsaPrivateKey *priv_key; +static struct GNUNET_CRYPTO_RsaPrivateKey *short_key; +static struct GNUNET_CRYPTO_ShortHashCode alice_hash; +static struct GNUNET_CRYPTO_ShortHashCode bob_hash; +static struct GNUNET_CRYPTO_ShortHashCode our_zone; +static struct GNUNET_CRYPTO_ShortHashCode priv_zone; +static struct GNUNET_CRYPTO_ShortHashCode short_zone; -struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; -struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; -struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded our_pkey; -struct GNUNET_CRYPTO_RsaPrivateKey *alice_key; -struct GNUNET_CRYPTO_RsaPrivateKey *bob_key; -struct GNUNET_CRYPTO_RsaPrivateKey *our_key; -struct GNUNET_CRYPTO_ShortHashCode alice_hash; -struct GNUNET_CRYPTO_ShortHashCode bob_hash; /** - * Check whether peers successfully shut down. + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. */ -void -shutdown_callback (void *cls, const char *emsg) +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - if (disco_task != GNUNET_SCHEDULER_NO_TASK) + die_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != gns_handle) { - disco_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_SCHEDULER_cancel(disco_task); - GNUNET_DHT_disconnect(dht_handle); - dht_handle = NULL; + GNUNET_GNS_disconnect(gns_handle); + gns_handle = NULL; + } + + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; } - if (emsg != NULL) + if (NULL != dht_handle) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok); - if (ok == 0) - ok = 2; + GNUNET_DHT_disconnect (dht_handle); + dht_handle = NULL; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok); + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + ok = 1; } + static void -disco_dht(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +end_badly_now () +{ + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + + +static void +shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { - disco_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_DHT_disconnect(dht_handle); - dht_handle = NULL; + GNUNET_GNS_disconnect(gns_handle); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); } /** @@ -129,9 +144,18 @@ disco_dht(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void process_shorten_result(void* cls, const char* sname) { - GNUNET_GNS_disconnect(gns_handle); - //GNUNET_SCHEDULER_add_now(disco_dht, NULL); - ok = 0; + + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (NULL != dht_handle) + { + GNUNET_DHT_disconnect (dht_handle); + dht_handle = NULL; + } if (sname == NULL) { @@ -147,23 +171,15 @@ process_shorten_result(void* cls, const char* sname) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "shorten test failed! (wanted: %s got: %s\n", - (char*)cls, sname); + TEST_EXPECTED_RESULT, sname); ok = 1; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shorten test succeeded!\n"); } - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } -static void -do_shorten(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_GNS_shorten(gns_handle, TEST_DOMAIN, &process_shorten_result, -TEST_DOMAIN); -} static void on_lookup_result(void *cls, uint32_t rd_count, @@ -186,7 +202,7 @@ on_lookup_result(void *cls, uint32_t rd_count, for (i=0; i<rd_count; i++) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); - if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A) + if (rd[i].record_type == GNUNET_GNS_RECORD_A) { memcpy(&a, rd[i].data, sizeof(a)); addr = inet_ntoa(a); @@ -204,8 +220,12 @@ on_lookup_result(void *cls, uint32_t rd_count, } } } - - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &do_shorten, NULL); + GNUNET_GNS_shorten_zone (gns_handle, TEST_DOMAIN, + &priv_zone, + &short_zone, + &our_zone, + &process_shorten_result, + TEST_DOMAIN); } @@ -216,81 +236,70 @@ on_lookup_result(void *cls, uint32_t rd_count, static void commence_testing (void *cls, int success) { - GNUNET_SCHEDULER_add_now(disco_dht, NULL); - //GNUNET_DHT_disconnect(dht_handle); - GNUNET_CRYPTO_rsa_key_free(our_key); GNUNET_CRYPTO_rsa_key_free(bob_key); GNUNET_CRYPTO_rsa_key_free(alice_key); - + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; gns_handle = GNUNET_GNS_connect(cfg); - if (NULL == gns_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to GNS!\n"); } - - GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A, - &on_lookup_result, TEST_DOMAIN); + GNUNET_GNS_lookup_zone (gns_handle, TEST_DOMAIN, + &our_zone, + GNUNET_GNS_RECORD_A, + GNUNET_NO, + short_key, + &on_lookup_result, TEST_DOMAIN); } -/** - * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut - * down the peers without freeing memory associated with GET request. - */ -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n", - (char *) cls); - ok = 1; - - if (disco_task != GNUNET_SCHEDULER_NO_TASK) - { - disco_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_SCHEDULER_cancel(disco_task); - GNUNET_DHT_disconnect(dht_handle); - dht_handle = NULL; - } - if (pg != NULL) - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - GNUNET_SCHEDULER_cancel (die_task); -} static void -put_pseu_dht(void *cls, int success) +put_pseu_dht (void *cls, int success) { struct GNSNameRecordBlock *nrb; struct GNUNET_CRYPTO_ShortHashCode name_hash; struct GNUNET_CRYPTO_ShortHashCode zone_hash; - GNUNET_HashCode xor_hash; - GNUNET_HashCode name_hash_double; - GNUNET_HashCode zone_hash_double; + struct GNUNET_HashCode xor_hash; + struct GNUNET_HashCode name_hash_double; + struct GNUNET_HashCode zone_hash_double; uint32_t rd_payload_length; char* nrb_data = NULL; struct GNUNET_CRYPTO_RsaSignature *sig; struct GNUNET_NAMESTORE_RecordData rd; - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + memset (&rd, 0, sizeof (struct GNUNET_NAMESTORE_RecordData)); + rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value; rd.data_size = strlen(TEST_PSEU_ALICE)+1; rd.data = TEST_PSEU_ALICE; rd.record_type = GNUNET_GNS_RECORD_PSEU; + rd.flags = 0; sig = GNUNET_NAMESTORE_create_signature(alice_key, - GNUNET_TIME_UNIT_FOREVER_ABS, - "+", - &rd, 1); + GNUNET_TIME_UNIT_FOREVER_ABS, + GNUNET_GNS_MASTERZONE_STR, + &rd, 1); + + GNUNET_assert (NULL != sig); + + GNUNET_break (GNUNET_OK == GNUNET_NAMESTORE_verify_signature (&alice_pkey, + GNUNET_TIME_UNIT_FOREVER_ABS, + GNUNET_GNS_MASTERZONE_STR, + 1, + &rd, + sig)); rd_payload_length = GNUNET_NAMESTORE_records_get_size (1, &rd); - nrb = GNUNET_malloc(rd_payload_length + strlen("+") + 1 + nrb = GNUNET_malloc(rd_payload_length + strlen(GNUNET_GNS_MASTERZONE_STR) + 1 + sizeof(struct GNSNameRecordBlock)); nrb->signature = *sig; nrb->public_key = alice_pkey; nrb->rd_count = htonl(1); - memset(&nrb[1], 0, strlen("+") + 1); - strcpy((char*)&nrb[1], "+"); + memset(&nrb[1], 0, strlen(GNUNET_GNS_MASTERZONE_STR) + 1); + strcpy((char*)&nrb[1], GNUNET_GNS_MASTERZONE_STR); nrb_data = (char*)&nrb[1]; - nrb_data += strlen("+") + 1; + nrb_data += strlen(GNUNET_GNS_MASTERZONE_STR) + 1; if (-1 == GNUNET_NAMESTORE_records_serialize (1, &rd, @@ -299,17 +308,15 @@ put_pseu_dht(void *cls, int success) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n"); ok = 3; - GNUNET_DHT_disconnect(dht_handle); - - GNUNET_CRYPTO_rsa_key_free(our_key); GNUNET_CRYPTO_rsa_key_free(bob_key); GNUNET_CRYPTO_rsa_key_free(alice_key); GNUNET_free(sig); GNUNET_free (nrb); + end_badly_now (); return; } - GNUNET_CRYPTO_short_hash("+", strlen("+"), &name_hash); + GNUNET_CRYPTO_short_hash(GNUNET_GNS_MASTERZONE_STR, strlen(GNUNET_GNS_MASTERZONE_STR), &name_hash); GNUNET_CRYPTO_short_hash(&alice_pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_hash); @@ -319,15 +326,15 @@ put_pseu_dht(void *cls, int success) GNUNET_CRYPTO_hash_xor(&zone_hash_double, &name_hash_double, &xor_hash); rd_payload_length += sizeof(struct GNSNameRecordBlock) + - strlen("+") + 1; + strlen(GNUNET_GNS_MASTERZONE_STR) + 1; GNUNET_DHT_put (dht_handle, &xor_hash, 0, - GNUNET_DHT_RO_NONE, + GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_BLOCK_TYPE_GNS_NAMERECORD, rd_payload_length, (char*)nrb, - rd.expiration, + GNUNET_TIME_UNIT_FOREVER_ABS, DHT_OPERATION_TIMEOUT, &commence_testing, NULL); @@ -336,15 +343,16 @@ put_pseu_dht(void *cls, int success) GNUNET_free (nrb); } + static void put_www_dht(void *cls, int success) { struct GNSNameRecordBlock *nrb; struct GNUNET_CRYPTO_ShortHashCode name_hash; struct GNUNET_CRYPTO_ShortHashCode zone_hash; - GNUNET_HashCode xor_hash; - GNUNET_HashCode name_hash_double; - GNUNET_HashCode zone_hash_double; + struct GNUNET_HashCode xor_hash; + struct GNUNET_HashCode name_hash_double; + struct GNUNET_HashCode zone_hash_double; uint32_t rd_payload_length; char* nrb_data = NULL; struct GNUNET_CRYPTO_RsaSignature *sig; @@ -352,16 +360,24 @@ put_www_dht(void *cls, int success) char* ip = TEST_IP; struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr)); - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + rd.expiration_time = UINT64_MAX; GNUNET_assert(1 == inet_pton (AF_INET, ip, web)); rd.data_size = sizeof(struct in_addr); rd.data = web; rd.record_type = GNUNET_DNSPARSER_TYPE_A; - + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + sig = GNUNET_NAMESTORE_create_signature(alice_key, GNUNET_TIME_UNIT_FOREVER_ABS, TEST_RECORD_NAME, &rd, 1); + + GNUNET_break (GNUNET_OK == GNUNET_NAMESTORE_verify_signature (&alice_pkey, + GNUNET_TIME_UNIT_FOREVER_ABS, + TEST_RECORD_NAME, + 1, + &rd, + sig)); rd_payload_length = GNUNET_NAMESTORE_records_get_size (1, &rd); nrb = GNUNET_malloc(rd_payload_length + strlen(TEST_RECORD_NAME) + 1 + sizeof(struct GNSNameRecordBlock)); @@ -380,13 +396,13 @@ put_www_dht(void *cls, int success) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n"); ok = 3; - GNUNET_DHT_disconnect(dht_handle); - GNUNET_CRYPTO_rsa_key_free(our_key); GNUNET_CRYPTO_rsa_key_free(bob_key); GNUNET_CRYPTO_rsa_key_free(alice_key); + GNUNET_free (sig); GNUNET_free(web); GNUNET_free (nrb); + end_badly_now(); return; } GNUNET_CRYPTO_short_hash(TEST_RECORD_NAME, strlen(TEST_RECORD_NAME), &name_hash); @@ -402,16 +418,16 @@ put_www_dht(void *cls, int success) GNUNET_DHT_put (dht_handle, &xor_hash, 0, - GNUNET_DHT_RO_NONE, + GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_BLOCK_TYPE_GNS_NAMERECORD, rd_payload_length, (char*)nrb, - rd.expiration, + GNUNET_TIME_UNIT_FOREVER_ABS, DHT_OPERATION_TIMEOUT, &put_pseu_dht, NULL); - - GNUNET_free(web); + GNUNET_free (sig); + GNUNET_free (web); GNUNET_free (nrb); } @@ -422,19 +438,20 @@ put_pkey_dht(void *cls, int32_t success, const char *emsg) struct GNSNameRecordBlock *nrb; struct GNUNET_CRYPTO_ShortHashCode name_hash; struct GNUNET_CRYPTO_ShortHashCode zone_hash; - GNUNET_HashCode xor_hash; - GNUNET_HashCode name_hash_double; - GNUNET_HashCode zone_hash_double; + struct GNUNET_HashCode xor_hash; + struct GNUNET_HashCode name_hash_double; + struct GNUNET_HashCode zone_hash_double; uint32_t rd_payload_length; char* nrb_data = NULL; struct GNUNET_CRYPTO_RsaSignature *sig; struct GNUNET_NAMESTORE_RecordData rd; - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + rd.expiration_time = UINT64_MAX; rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); rd.data = &alice_hash; rd.record_type = GNUNET_GNS_RECORD_PKEY; - + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + sig = GNUNET_NAMESTORE_create_signature(bob_key, GNUNET_TIME_UNIT_FOREVER_ABS, TEST_AUTHORITY_ALICE, @@ -460,11 +477,12 @@ put_pkey_dht(void *cls, int32_t success, const char *emsg) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n"); ok = 3; - GNUNET_CRYPTO_rsa_key_free(our_key); - GNUNET_CRYPTO_rsa_key_free(bob_key); - GNUNET_CRYPTO_rsa_key_free(alice_key); - GNUNET_free(sig); + GNUNET_CRYPTO_rsa_key_free (our_key); + GNUNET_CRYPTO_rsa_key_free (bob_key); + GNUNET_CRYPTO_rsa_key_free (alice_key); + GNUNET_free (sig); GNUNET_free (nrb); + end_badly_now (); return; } @@ -482,37 +500,76 @@ put_pkey_dht(void *cls, int32_t success, const char *emsg) strlen(TEST_AUTHORITY_ALICE) + 1; GNUNET_DHT_put (dht_handle, &xor_hash, 0, - GNUNET_DHT_RO_NONE, + GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_BLOCK_TYPE_GNS_NAMERECORD, rd_payload_length, (char*)nrb, - rd.expiration, + GNUNET_TIME_UNIT_FOREVER_ABS, DHT_OPERATION_TIMEOUT, &put_www_dht, NULL); - GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_NO); + GNUNET_free (sig); GNUNET_free (nrb); } + static void -do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *_cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) +fin_init_zone (void *cls, int32_t success, const char *emsg) { + struct GNUNET_NAMESTORE_RecordData rd; + rd.expiration_time = UINT64_MAX; + rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); + rd.data = &bob_hash; + rd.record_type = GNUNET_GNS_RECORD_PKEY; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; - + GNUNET_NAMESTORE_record_create (namestore_handle, + our_key, + TEST_AUTHORITY_BOB, + &rd, + &put_pkey_dht, + NULL); + +} + +static void +cont_init_zone (void *cls, int32_t success, const char *emsg) +{ + + struct GNUNET_NAMESTORE_RecordData rd; + rd.expiration_time = UINT64_MAX; + rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); + rd.data = &short_zone; + rd.record_type = GNUNET_GNS_RECORD_PKEY; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + + GNUNET_NAMESTORE_record_create (namestore_handle, + priv_key, + TEST_SHORTEN_ZONE, + &rd, + &fin_init_zone, + NULL); +} + + +static void +do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) +{ + char* private_keyfile; + char* shorten_keyfile; char* our_keyfile; - cfg = _cfg; - - GNUNET_SCHEDULER_cancel (die_task); + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); /* put records into namestore */ namestore_handle = GNUNET_NAMESTORE_connect(cfg); if (NULL == namestore_handle) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); - ok = -1; + end_badly_now(); return; } @@ -521,7 +578,7 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, if (NULL == dht_handle) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to dht\n"); - ok = -1; + end_badly_now(); return; } @@ -530,114 +587,75 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, &our_keyfile)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; + end_badly_now(); + return; + } + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "SHORTEN_ZONEKEY", + &shorten_keyfile)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "Failed to get shorten zone key from cfg\n"); + end_badly_now(); + return; + } + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "PRIVATE_ZONEKEY", + &private_keyfile)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "Failed to get private zone key from cfg\n"); + end_badly_now(); return; } - our_key = GNUNET_CRYPTO_rsa_key_create_from_file (our_keyfile); + priv_key = GNUNET_CRYPTO_rsa_key_create_from_file (private_keyfile); + short_key = GNUNET_CRYPTO_rsa_key_create_from_file (shorten_keyfile); bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB); alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_ALICE); GNUNET_free(our_keyfile); + GNUNET_free(shorten_keyfile); + GNUNET_free(private_keyfile); GNUNET_CRYPTO_rsa_key_get_public (our_key, &our_pkey); + GNUNET_CRYPTO_rsa_key_get_public (priv_key, &priv_pkey); + GNUNET_CRYPTO_rsa_key_get_public (short_key, &short_pkey); GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey); GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey); GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash); GNUNET_CRYPTO_short_hash(&alice_pkey, sizeof(alice_pkey), &alice_hash); - + GNUNET_CRYPTO_short_hash(&our_pkey, sizeof(our_pkey), &our_zone); + GNUNET_CRYPTO_short_hash(&priv_pkey, sizeof(priv_pkey), &priv_zone); + GNUNET_CRYPTO_short_hash(&short_pkey, sizeof(short_pkey), &short_zone); + struct GNUNET_NAMESTORE_RecordData rd; - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + rd.expiration_time = UINT64_MAX; rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); - rd.data = &bob_hash; + rd.data = &priv_zone; rd.record_type = GNUNET_GNS_RECORD_PKEY; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; GNUNET_NAMESTORE_record_create (namestore_handle, our_key, - TEST_AUTHORITY_BOB, + TEST_PRIVATE_ZONE, &rd, - &put_pkey_dht, + &cont_init_zone, NULL); - - } -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - cfg = c; - /* Get path from configuration file */ - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - /* Start alice */ - //d1 = GNUNET_TESTING_daemon_start(cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0, - // NULL, NULL, NULL, &do_lookup, NULL); - pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT, - NULL, NULL, &do_lookup, NULL, - NULL, NULL, NULL); -} - -static int -check () -{ - int ret; - - /* Arguments for GNUNET_PROGRAM_run */ - char *const argv[] = { "test-gns-pseu-shorten", /* Name to give running binary */ - "-c", - "test_gns_simple_lookup.conf", /* Config file to use */ -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - /* Run the run function as a new program */ - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-gns-pseu-shorten", "nohelp", options, &run, - &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-gns-pseu-shorten': Failed with error code %d\n", ret); - } - return ok; -} int main (int argc, char *argv[]) { - int ret; - + ok = 1; GNUNET_log_setup ("test-gns-pseu-shorten", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); - ret = check (); - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - return ret; + GNUNET_TESTING_peer_run ("test-gns-pseu-shorten", "test_gns_simple_lookup.conf", &do_check, NULL); + return ok; } -/* end of test_gns_twopeer.c */ +/* end of test_gns_pseu_shorten.c */ diff --git a/src/gns/test_gns_revocation.c b/src/gns/test_gns_revocation.c new file mode 100644 index 0000000..8e67788 --- /dev/null +++ b/src/gns/test_gns_revocation.c @@ -0,0 +1,285 @@ +/* + 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 gns/test_gns_revovation.c + * @brief base testcase for testing zone revocation + * + */ +#include "platform.h" +#include "gnunet_testing_lib.h" +#include "gnunet_core_service.h" +#include "block_dns.h" +#include "gnunet_signatures.h" +#include "gnunet_namestore_service.h" +#include "../namestore/namestore.h" +#include "gnunet_dnsparser_lib.h" +#include "gnunet_gns_service.h" + +/* Timeout for entire testcase */ +#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) + +/* test records to resolve */ +#define TEST_DOMAIN "www.bob.gads" +#define TEST_IP "127.0.0.1" +#define TEST_RECORD_NAME "www" + +#define TEST_AUTHORITY_NAME "bob" + +#define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey" + +/* Task handle to use to schedule test failure */ +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +/* Global return value (0 for success, anything else for failure) */ +static int ok; + +static struct GNUNET_NAMESTORE_Handle *namestore_handle; + +static struct GNUNET_GNS_Handle *gns_handle; + +static const struct GNUNET_CONFIGURATION_Handle *cfg; + + +/** + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. + */ +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != gns_handle) + { + GNUNET_GNS_disconnect(gns_handle); + gns_handle = NULL; + } + + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + ok = 1; +} + + +static void +end_badly_now () +{ + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + + +static void +shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_GNS_disconnect(gns_handle); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); +} + + +static void +on_lookup_result(void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct in_addr a; + int i; + char* addr; + + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + if (rd_count == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Lookup failed, this is good!\n"); + ok = 0; + } + else + { + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "name: %s\n", (char*)cls); + for (i=0; i<rd_count; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "type: %d\n", rd[i].record_type); + if (rd[i].record_type == GNUNET_GNS_RECORD_A) + { + memcpy(&a, rd[i].data, sizeof(a)); + addr = inet_ntoa(a); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "address: %s\n", addr); + if (0 == strcmp(addr, TEST_IP)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "%s incorrectly resolved to %s!\n", TEST_DOMAIN, addr); + ok = 2; + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n"); + } + } + } + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); +} + + +/** + * Function scheduled to be run on the successful start of services + * tries to look up the dns record for TEST_DOMAIN + */ +static void +commence_testing (void *cls, int32_t success, const char *emsg) +{ + gns_handle = GNUNET_GNS_connect(cfg); + if (NULL == gns_handle) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to GNS!\n"); + end_badly_now (); + return; + } + + GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_A, + GNUNET_NO, + NULL, + &on_lookup_result, TEST_DOMAIN); +} + + +static void +do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) +{ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; + struct GNUNET_CRYPTO_RsaPrivateKey *alice_key; + struct GNUNET_CRYPTO_RsaPrivateKey *bob_key; + struct GNUNET_CRYPTO_ShortHashCode bob_hash; + struct GNUNET_CRYPTO_RsaSignature *sig; + char* alice_keyfile; + + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + + /* put records into namestore */ + namestore_handle = GNUNET_NAMESTORE_connect(cfg); + if (NULL == namestore_handle) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); + end_badly_now (); + return; + } + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", + &alice_keyfile)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); + end_badly_now (); + return; + } + + alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile); + bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB); + + GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey); + GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey); + + struct GNUNET_NAMESTORE_RecordData rd; + char* ip = TEST_IP; + struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr)); + rd.expiration_time = UINT64_MAX; + GNUNET_assert(1 == inet_pton (AF_INET, ip, web)); + + GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash); + + rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); + rd.data = &bob_hash; + rd.record_type = GNUNET_GNS_RECORD_PKEY; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + + GNUNET_NAMESTORE_record_create (namestore_handle, + alice_key, + TEST_AUTHORITY_NAME, + &rd, + NULL, + NULL); + + rd.data_size = sizeof(struct in_addr); + rd.data = web; + rd.record_type = GNUNET_DNSPARSER_TYPE_A; + sig = GNUNET_NAMESTORE_create_signature(bob_key, + GNUNET_TIME_UNIT_FOREVER_ABS, + TEST_RECORD_NAME, + &rd, 1); + + GNUNET_NAMESTORE_record_put (namestore_handle, + &bob_pkey, + TEST_RECORD_NAME, + GNUNET_TIME_UNIT_FOREVER_ABS, + 1, + &rd, + sig, + NULL, + NULL); + rd.data_size = 0; + rd.record_type = GNUNET_GNS_RECORD_REV; + + GNUNET_NAMESTORE_record_create (namestore_handle, + bob_key, + GNUNET_GNS_MASTERZONE_STR, + &rd, + &commence_testing, + NULL); + GNUNET_free (alice_keyfile); + GNUNET_free (web); + GNUNET_free (sig); + GNUNET_CRYPTO_rsa_key_free (bob_key); + GNUNET_CRYPTO_rsa_key_free (alice_key); +} + + +int +main (int argc, char *argv[]) +{ + ok = 1; + + GNUNET_log_setup ("test-gns-revocation", + "WARNING", + NULL); + GNUNET_TESTING_peer_run ("test-gns-revocation", "test_gns_simple_lookup.conf", &do_check, NULL); + return ok; +} + + +/* end of test_gns_revocation.c */ diff --git a/src/gns/test_gns_simple_delegated_lookup.c b/src/gns/test_gns_simple_delegated_lookup.c index 36fb969..393ddfb 100644 --- a/src/gns/test_gns_simple_delegated_lookup.c +++ b/src/gns/test_gns_simple_delegated_lookup.c @@ -18,7 +18,7 @@ Boston, MA 02111-1307, USA. */ /** - * @file gns/test_gns_twopeer.c + * @file gns/test_gns_simple_delegated_lookup.c * @brief base testcase for testing DHT service with * two running peers. * @@ -46,17 +46,11 @@ #include "gnunet_dnsparser_lib.h" #include "gnunet_gns_service.h" -/* DEFINES */ -#define VERBOSE GNUNET_YES - /* Timeout for entire testcase */ #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) -/* If number of peers not in config file, use this number */ -#define DEFAULT_NUM_PEERS 2 - /* test records to resolve */ -#define TEST_DOMAIN "www.bob.gnunet" +#define TEST_DOMAIN "www.bob.gads" #define TEST_IP "127.0.0.1" #define TEST_RECORD_NAME "www" @@ -64,17 +58,8 @@ #define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey" -/* Globals */ - -/** - * Directory to store temp data in, defined in config file - */ -static char *test_directory; - -static struct GNUNET_TESTING_PeerGroup *pg; - /* Task handle to use to schedule test failure */ -GNUNET_SCHEDULER_TaskIdentifier die_task; +static GNUNET_SCHEDULER_TaskIdentifier die_task; /* Global return value (0 for success, anything else for failure) */ static int ok; @@ -83,66 +68,89 @@ static struct GNUNET_NAMESTORE_Handle *namestore_handle; static struct GNUNET_GNS_Handle *gns_handle; -const struct GNUNET_CONFIGURATION_Handle *cfg; +static const struct GNUNET_CONFIGURATION_Handle *cfg; + /** - * Check whether peers successfully shut down. + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. */ -void -shutdown_callback (void *cls, const char *emsg) +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - if (emsg != NULL) + die_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != gns_handle) + { + GNUNET_GNS_disconnect(gns_handle); + gns_handle = NULL; + } + if (NULL != namestore_handle) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok); - if (ok == 0) - ok = 2; + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; } + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + ok = 1; +} + - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok); +static void +shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_GNS_disconnect (gns_handle); + gns_handle = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); } + static void -on_lookup_result(void *cls, uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +on_lookup_result (void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { + const char *name = cls; + uint32_t i; + const char* addr; struct in_addr a; - int i; - char* addr; - - if (rd_count == 0) + + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + if (0 == rd_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Lookup failed, rp_filtering?\n"); + "Lookup failed!\n"); ok = 2; + GNUNET_SCHEDULER_shutdown (); + return; } - else + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "name: %s\n", + name); + for (i=0; i<rd_count; i++) { - ok = 1; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls); - for (i=0; i<rd_count; i++) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); - if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A) - { - memcpy(&a, rd[i].data, sizeof(a)); - addr = inet_ntoa(a); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr); - if (0 == strcmp(addr, TEST_IP)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "%s correctly resolved to %s!\n", TEST_DOMAIN, addr); - ok = 0; - } - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n"); - } - } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); + if (rd[i].record_type != GNUNET_GNS_RECORD_A) + continue; + memcpy (&a, rd[i].data, sizeof (a)); + addr = inet_ntoa (a); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "address: %s\n", addr); + if (0 != strcmp (addr, TEST_IP)) + continue; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "%s correctly resolved to %s!\n", TEST_DOMAIN, addr); + ok = 0; } - GNUNET_GNS_disconnect(gns_handle); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } @@ -153,51 +161,33 @@ on_lookup_result(void *cls, uint32_t rd_count, static void commence_testing (void *cls, int32_t success, const char *emsg) { - GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES); - + if (NULL != emsg) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to store record in namestore: %s\n", + emsg); + GNUNET_SCHEDULER_shutdown (); + return; + } gns_handle = GNUNET_GNS_connect(cfg); - if (NULL == gns_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to GNS!\n"); + GNUNET_SCHEDULER_shutdown (); + return; } - - GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A, - &on_lookup_result, TEST_DOMAIN); + GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_A, + GNUNET_NO, + NULL, + &on_lookup_result, TEST_DOMAIN); } -/** - * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut - * down the peers without freeing memory associated with GET request. - */ -static void -end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - - if (pg != NULL) - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - GNUNET_SCHEDULER_cancel (die_task); -} -/** - * Check if the get_handle is being used, if so stop the request. Either - * way, schedule the end_badly_cont function which actually shuts down the - * test. - */ static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n", - (char *) cls); - GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); - ok = 1; -} - -static void -do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *_cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) +do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) { struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; @@ -206,150 +196,85 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, struct GNUNET_CRYPTO_ShortHashCode bob_hash; struct GNUNET_CRYPTO_RsaSignature *sig; char* alice_keyfile; + struct GNUNET_TIME_Absolute et; + struct GNUNET_NAMESTORE_RecordData rd; + const char* ip = TEST_IP; + struct in_addr web; - cfg = _cfg; - - GNUNET_SCHEDULER_cancel (die_task); + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); /* put records into namestore */ namestore_handle = GNUNET_NAMESTORE_connect(cfg); if (NULL == namestore_handle) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); - ok = -1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to namestore\n"); + GNUNET_SCHEDULER_shutdown (); return; } - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", - "ZONEKEY", - &alice_keyfile)) + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", + &alice_keyfile)) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); + GNUNET_SCHEDULER_shutdown (); return; } - alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile); bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB); - GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey); GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey); - - struct GNUNET_NAMESTORE_RecordData rd; - char* ip = TEST_IP; - struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr)); - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; - GNUNET_assert(1 == inet_pton (AF_INET, ip, web)); - - GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash); - + rd.expiration_time = UINT64_MAX; + GNUNET_assert (1 == inet_pton (AF_INET, ip, &web)); + GNUNET_CRYPTO_short_hash (&bob_pkey, sizeof(bob_pkey), &bob_hash); rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); rd.data = &bob_hash; rd.record_type = GNUNET_GNS_RECORD_PKEY; - + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; GNUNET_NAMESTORE_record_create (namestore_handle, alice_key, TEST_AUTHORITY_NAME, &rd, NULL, NULL); - rd.data_size = sizeof(struct in_addr); - rd.data = web; + rd.data = &web; rd.record_type = GNUNET_DNSPARSER_TYPE_A; - sig = GNUNET_NAMESTORE_create_signature(bob_key, - GNUNET_TIME_UNIT_FOREVER_ABS, - TEST_RECORD_NAME, - &rd, 1); - + sig = GNUNET_NAMESTORE_create_signature (bob_key, + GNUNET_TIME_UNIT_FOREVER_ABS, + TEST_RECORD_NAME, + &rd, 1); + et.abs_value = rd.expiration_time; GNUNET_NAMESTORE_record_put (namestore_handle, &bob_pkey, TEST_RECORD_NAME, - rd.expiration, + et, 1, &rd, sig, &commence_testing, NULL); - GNUNET_free(sig); - GNUNET_CRYPTO_rsa_key_free(bob_key); - GNUNET_CRYPTO_rsa_key_free(alice_key); + GNUNET_free (sig); + GNUNET_free (alice_keyfile); + GNUNET_CRYPTO_rsa_key_free (bob_key); + GNUNET_CRYPTO_rsa_key_free (alice_key); } -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - cfg = c; - /* Get path from configuration file */ - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - /* Start alice */ - pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT, - NULL, NULL, &do_lookup, NULL, - NULL, NULL, NULL); -} - -static int -check () -{ - int ret; - - /* Arguments for GNUNET_PROGRAM_run */ - char *const argv[] = { "test-gns-simple-delegated-lookup", /* Name to give running binary */ - "-c", - "test_gns_simple_lookup.conf", /* Config file to use */ -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - /* Run the run function as a new program */ - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-gns-simple-delegated-lookup", "nohelp", options, &run, - &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-gns-simple-delegated-lookup': Failed with error code %d\n", ret); - } - return ok; -} int main (int argc, char *argv[]) { - int ret; - - GNUNET_log_setup ("test-gns-simple-lookup", -#if VERBOSE - "DEBUG", -#else + ok = 1; + GNUNET_log_setup ("test-gns-simple-delegated-lookup", "WARNING", -#endif NULL); - ret = check (); - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - return ret; + GNUNET_TESTING_peer_run ("test-gns-simple-delegated-lookup", + "test_gns_simple_lookup.conf", + &do_check, NULL); + return ok; } -/* end of test_gns_twopeer.c */ +/* end of test_gns_simple_delegated_lookup.c */ diff --git a/src/gns/test_gns_simple_get_authority.c b/src/gns/test_gns_simple_get_authority.c index dbecb7d..111f8f1 100644 --- a/src/gns/test_gns_simple_get_authority.c +++ b/src/gns/test_gns_simple_get_authority.c @@ -18,7 +18,7 @@ Boston, MA 02111-1307, USA. */ /** - * @file gns/test_gns_simple_shorten.c + * @file gns/test_gns_simple_get_authority.c * @brief basic shorten test for gns api * */ @@ -32,37 +32,24 @@ #include "gnunet_dnsparser_lib.h" #include "gnunet_gns_service.h" -/* DEFINES */ -#define VERBOSE GNUNET_YES - /* Timeout for entire testcase */ #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) -/* If number of peers not in config file, use this number */ -#define DEFAULT_NUM_PEERS 2 - /* test records to resolve */ -#define TEST_DOMAIN "www.alice.bob.gnunet" +#define TEST_DOMAIN "www.alice.bob.gads" #define TEST_IP "127.0.0.1" #define TEST_RECORD_NAME "www" #define TEST_AUTHORITY_BOB "bob" #define TEST_AUTHORITY_ALICE "alice" #define TEST_ALICE_PSEU "carol" -#define TEST_EXPECTED_RESULT "alice.bob.gnunet" +#define TEST_EXPECTED_RESULT "alice.bob.gads" #define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey" #define KEYFILE_ALICE "../namestore/zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey" /* Globals */ -/** - * Directory to store temp data in, defined in config file - */ -static char *test_directory; - -static struct GNUNET_TESTING_PeerGroup *pg; - /* Task handle to use to schedule test failure */ GNUNET_SCHEDULER_TaskIdentifier die_task; @@ -75,20 +62,44 @@ static struct GNUNET_GNS_Handle *gns_handle; const struct GNUNET_CONFIGURATION_Handle *cfg; + /** - * Check whether peers successfully shut down. + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. */ static void -shutdown_callback (void *cls, const char *emsg) +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - if (emsg != NULL) + die_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != gns_handle) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok); - if (ok == 0) - ok = 2; + GNUNET_GNS_disconnect(gns_handle); + gns_handle = NULL; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok); + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + ok = 1; +} + +void end_badly_now () +{ + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + +static void shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_GNS_disconnect(gns_handle); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); } /** @@ -97,9 +108,16 @@ shutdown_callback (void *cls, const char *emsg) static void process_auth_result(void* cls, const char* aname) { - GNUNET_GNS_disconnect(gns_handle); - ok = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Disconnecting from namestore\n"); + GNUNET_NAMESTORE_disconnect (namestore_handle); + + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } if (aname == NULL) { @@ -118,15 +136,19 @@ process_auth_result(void* cls, const char* aname) TEST_EXPECTED_RESULT, aname); ok = 1; } + else + { + ok = 0; + } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "get_authority test finished!\n"); } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } + /** * Function scheduled to be run on the successful start of services * tries to shorten the name TEST_DOMAIN using gns @@ -134,61 +156,27 @@ process_auth_result(void* cls, const char* aname) static void commence_testing (void *cls, int32_t success, const char *emsg) { - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "disconnecting from namestore\n"); - GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "connecting to gns\n"); + "Connecting to gns\n"); gns_handle = GNUNET_GNS_connect(cfg); - if (NULL == gns_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "failed to connect to gns\n"); - ok = 1; + "Failed to connect to gns\n"); + end_badly_now(); return; } GNUNET_GNS_get_authority(gns_handle, TEST_DOMAIN, &process_auth_result, TEST_DOMAIN); - } -/** - * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut - * down the peers without freeing memory associated with GET request. - */ -static void -end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - if (pg != NULL) - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - GNUNET_SCHEDULER_cancel (die_task); -} -/** - * Check if the get_handle is being used, if so stop the request. Either - * way, schedule the end_badly_cont function which actually shuts down the - * test. - */ -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n", - (char *) cls); - GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); - ok = 1; -} - -static void -do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *_cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) +void do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) { struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded our_pkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; @@ -201,16 +189,16 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, struct GNUNET_CRYPTO_RsaSignature *sig; char* our_keyfile; - cfg = _cfg; - - GNUNET_SCHEDULER_cancel (die_task); + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running test\n"); /* put records into namestore */ namestore_handle = GNUNET_NAMESTORE_connect(cfg); if (NULL == namestore_handle) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); - ok = -1; + end_badly_now(); return; } @@ -219,7 +207,7 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, &our_keyfile)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; + end_badly_now(); return; } @@ -228,23 +216,24 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB); alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_ALICE); - + GNUNET_CRYPTO_rsa_key_get_public (our_key, &our_pkey); GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey); GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey); struct GNUNET_NAMESTORE_RecordData rd; char* ip = TEST_IP; - struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr)); - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; - GNUNET_assert(1 == inet_pton (AF_INET, ip, web)); - + struct in_addr *web = GNUNET_malloc (sizeof(struct in_addr)); + rd.expiration_time = UINT64_MAX; + GNUNET_assert (1 == inet_pton (AF_INET, ip, web)); + GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash); rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); rd.data = &bob_hash; rd.record_type = GNUNET_GNS_RECORD_PKEY; - + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + /* put bob into our zone */ GNUNET_NAMESTORE_record_create (namestore_handle, our_key, @@ -252,7 +241,7 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, &rd, NULL, NULL); - + /* put alice into bobs zone */ GNUNET_CRYPTO_short_hash(&alice_pkey, sizeof(alice_pkey), &alice_hash); rd.data = &alice_hash; @@ -269,6 +258,8 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, NULL, NULL); + GNUNET_free (sig); + /* put www A record and PSEU into alice's zone */ rd.data_size = sizeof(struct in_addr); @@ -305,84 +296,26 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, &commence_testing, NULL); - GNUNET_free(sig); - + GNUNET_free (web); + GNUNET_free (sig); + GNUNET_CRYPTO_rsa_key_free (alice_key); + GNUNET_CRYPTO_rsa_key_free (bob_key); + GNUNET_CRYPTO_rsa_key_free (our_key); } -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - cfg = c; - /* Get path from configuration file */ - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - /* Start alice */ - pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT, - NULL, NULL, &do_shorten, NULL, - NULL, NULL, NULL); -} - -static int -check () -{ - int ret; - - /* Arguments for GNUNET_PROGRAM_run */ - char *const argv[] = { "test-gns-simple-get-authority", /* Name to give running binary */ - "-c", - "test_gns_simple_lookup.conf", /* Config file to use */ -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - /* Run the run function as a new program */ - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-gns-simple-get-authority", "nohelp", options, &run, - &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-gns-simple-get-authority': Failed with error code %d\n", ret); - } - return ok; -} int main (int argc, char *argv[]) { - int ret; - - GNUNET_log_setup ("test-gns-simple-lookup", -#if VERBOSE - "DEBUG", -#else + ok = 1; + GNUNET_log_setup ("test-gns-simple-get-authority", "WARNING", -#endif NULL); - ret = check (); - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - return ret; + GNUNET_TESTING_peer_run ("test-gns-simple-get-authority", + "test_gns_simple_lookup.conf", + &do_check, NULL); + return ok; } -/* end of test_gns_twopeer.c */ +/* end of test-gns-simple-get-authority.c */ + diff --git a/src/gns/test_gns_simple_lookup.c b/src/gns/test_gns_simple_lookup.c index 89a9aef..96283df 100644 --- a/src/gns/test_gns_simple_lookup.c +++ b/src/gns/test_gns_simple_lookup.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009 Christian Grothoff (and other contributing authors) + (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 @@ -20,7 +20,7 @@ /** * @file gns/test_gns_simple_lookup.c * @brief base testcase for testing a local GNS record lookup - * + * @author Martin Schanzenbach */ #include "platform.h" #include "gnunet_testing_lib.h" @@ -31,66 +31,115 @@ #include "gnunet_dnsparser_lib.h" #include "gnunet_gns_service.h" -/* DEFINES */ -#define VERBOSE GNUNET_YES - -/* Timeout for entire testcase */ -#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) -/* If number of peers not in config file, use this number */ -#define DEFAULT_NUM_PEERS 2 +/** + * Timeout for entire testcase + */ +#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 120) /* test records to resolve */ -#define TEST_DOMAIN "www.gnunet" +#define TEST_DOMAIN "www.gads" #define TEST_IP "127.0.0.1" #define TEST_RECORD_NAME "www" -/* Globals */ - /** - * Directory to store temp data in, defined in config file + * Task handle to use to schedule test failure */ -static char *test_directory; - -static struct GNUNET_TESTING_PeerGroup *pg; +static GNUNET_SCHEDULER_TaskIdentifier die_task; -/* Task handle to use to schedule test failure */ -GNUNET_SCHEDULER_TaskIdentifier die_task; - -/* Global return value (0 for success, anything else for failure) */ +/** + * Global return value (0 for success, anything else for failure) + */ static int ok; static struct GNUNET_NAMESTORE_Handle *namestore_handle; static struct GNUNET_GNS_Handle *gns_handle; -const struct GNUNET_CONFIGURATION_Handle *cfg; +static const struct GNUNET_CONFIGURATION_Handle *cfg; + +static struct GNUNET_GNS_LookupRequest *lr; + +static struct GNUNET_NAMESTORE_QueueEntry *nsqe; + /** - * Check whether peers successfully shut down. + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. */ -void -shutdown_callback (void *cls, const char *emsg) +static void +end_badly (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { - if (emsg != NULL) + if (NULL != nsqe) + { + GNUNET_NAMESTORE_cancel (nsqe); + nsqe = NULL; + } + if (NULL != lr) + { + GNUNET_GNS_cancel_lookup_request (lr); + lr = NULL; + } + if (NULL != gns_handle) + { + GNUNET_GNS_disconnect (gns_handle); + gns_handle = NULL; + } + + if (NULL != namestore_handle) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok); - if (ok == 0) - ok = 2; + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; } + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + ok = 1; +} + + +static void +end_badly_now () +{ + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok); +static void +shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_GNS_disconnect (gns_handle); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); } +/** + * Function called on result for a GNS lookup + * + * @param cls closure, unused + * @param rd_count number of records + * @param rd the records in reply + */ static void on_lookup_result(void *cls, uint32_t rd_count, const struct GNUNET_NAMESTORE_RecordData *rd) { struct in_addr a; - int i; + uint32_t i; char* addr; - + + lr = NULL; + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; if (rd_count == 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -104,214 +153,134 @@ on_lookup_result(void *cls, uint32_t rd_count, for (i=0; i<rd_count; i++) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); - if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A) + if (rd[i].record_type == GNUNET_GNS_RECORD_A) { - memcpy(&a, rd[i].data, sizeof(a)); + memcpy (&a, rd[i].data, sizeof(a)); addr = inet_ntoa(a); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr); - if (0 == strcmp(addr, TEST_IP)) + if (0 == strcmp (addr, TEST_IP)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "%s correctly resolved to %s!\n", TEST_DOMAIN, addr); + "%s correctly resolved to %s!\n", + TEST_DOMAIN, addr); ok = 0; } } else { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No resolution!\n"); } } } - GNUNET_GNS_disconnect(gns_handle); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } /** * Function scheduled to be run on the successful start of services * tries to look up the dns record for TEST_DOMAIN + * + * @param cls closure + * @param success GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) + * GNUNET_NO if content was already there or not found + * GNUNET_YES (or other positive value) on success + * @param emsg NULL on success, otherwise an error message */ static void -commence_testing (void *cls, int32_t success, const char *emsg) +commence_testing (void *cls, + int32_t success, + const char *emsg) { - - - GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES); - - gns_handle = GNUNET_GNS_connect(cfg); - + nsqe = NULL; + if (NULL != emsg) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to store record in namestore: %s\n", + emsg); + end_badly_now (); + return; + } + gns_handle = GNUNET_GNS_connect (cfg); if (NULL == gns_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to GNS!\n"); - ok = 2; + end_badly_now (); + return; } - - GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A, - &on_lookup_result, TEST_DOMAIN); + lr = GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_A, + GNUNET_YES, + NULL, + &on_lookup_result, TEST_DOMAIN); } -/** - * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut - * down the peers without freeing memory associated with GET request. - */ static void -end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - - if (pg != NULL) - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - GNUNET_SCHEDULER_cancel (die_task); -} - -/** - * Check if the get_handle is being used, if so stop the request. Either - * way, schedule the end_badly_cont function which actually shuts down the - * test. - */ -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n", - (char *) cls); - GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); - ok = 1; -} - -static void -do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *_cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) +do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) { struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; struct GNUNET_CRYPTO_RsaPrivateKey *alice_key; + struct GNUNET_NAMESTORE_RecordData rd; char* alice_keyfile; - - cfg = _cfg; + char* ip = TEST_IP; + struct in_addr web; - GNUNET_SCHEDULER_cancel (die_task); + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); /* put records into namestore */ namestore_handle = GNUNET_NAMESTORE_connect(cfg); if (NULL == namestore_handle) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); - ok = -1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to namestore\n"); + end_badly_now (); return; } - - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", - "ZONEKEY", - &alice_keyfile)) + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", + &alice_keyfile)) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to get key from cfg\n"); + end_badly_now (); return; } alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile); - GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey); - - GNUNET_free(alice_keyfile); - - struct GNUNET_NAMESTORE_RecordData rd; - char* ip = TEST_IP; - struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr)); - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; - GNUNET_assert(1 == inet_pton (AF_INET, ip, web)); + GNUNET_free (alice_keyfile); + rd.expiration_time = UINT64_MAX; + GNUNET_assert (1 == inet_pton (AF_INET, ip, &web)); rd.data_size = sizeof(struct in_addr); - rd.data = web; + rd.data = &web; rd.record_type = GNUNET_DNSPARSER_TYPE_A; - - GNUNET_NAMESTORE_record_create (namestore_handle, - alice_key, - TEST_RECORD_NAME, - &rd, - &commence_testing, - NULL); - - GNUNET_CRYPTO_rsa_key_free(alice_key); - GNUNET_free(web); - + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + nsqe = GNUNET_NAMESTORE_record_create (namestore_handle, + alice_key, + TEST_RECORD_NAME, + &rd, + &commence_testing, + NULL); + GNUNET_CRYPTO_rsa_key_free (alice_key); } -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - cfg = c; - /* Get path from configuration file */ - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - /* Start alice */ - pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT, - NULL, NULL, &do_lookup, NULL, - NULL, NULL, NULL); -} - -static int -check () -{ - int ret; - - /* Arguments for GNUNET_PROGRAM_run */ - char *const argv[] = { "test-gns-simple-lookup", /* Name to give running binary */ - "-c", - "test_gns_simple_lookup.conf", /* Config file to use */ -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - /* Run the run function as a new program */ - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-gns-simple-lookup", "nohelp", options, &run, - &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-gns-simple-lookup': Failed with error code %d\n", ret); - } - return ok; -} int main (int argc, char *argv[]) { - int ret; - + ok = 1; GNUNET_log_setup ("test-gns-simple-lookup", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); - ret = check (); - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - return ret; + GNUNET_TESTING_peer_run ("test-gns-simple-lookup", + "test_gns_simple_lookup.conf", + &do_check, NULL); + return ok; } - -/* end of test_gns_twopeer.c */ + +/* end of test_gns_simple_lookup.c */ diff --git a/src/gns/test_gns_simple_lookup.conf b/src/gns/test_gns_simple_lookup.conf index 9a32fe5..f759ba4 100644 --- a/src/gns/test_gns_simple_lookup.conf +++ b/src/gns/test_gns_simple_lookup.conf @@ -3,11 +3,10 @@ AUTOSTART = NO [resolver] -AUTOSTART = NO +AUTOSTART = YES HOSTNAME = localhost [dht] -DEBUG = NO AUTOSTART = YES ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; @@ -24,7 +23,6 @@ DATABASE = sqlite [transport] PLUGINS = tcp -DEBUG = NO ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; NEIGHBOUR_LIMIT = 50 @@ -40,7 +38,6 @@ PORT = 12092 [arm] DEFAULTSERVICES = core dht namestore gns PORT = 12366 -DEBUG = NO [transport-tcp] TIMEOUT = 300 s @@ -51,10 +48,9 @@ BINDTO = 127.0.0.1 WEAKRANDOM = YES [gnunetd] -HOSTKEY = $SERVICEHOME/.hostkey +HOSTKEY = zonefiles/test_zonekey [PATHS] -DEFAULTCONFIG = test_gns_simple_lookup.conf SERVICEHOME = /tmp/test-gnunetd-gns-peer-1/ @@ -72,20 +68,22 @@ AUTOSTART = YES DNS_EXIT = 8.8.8.8 [gns] -#PREFIX = valgrind -v --leak-check=full --track-origins=yes +#PREFIX = valgrind --leak-check=full --track-origins=yes AUTOSTART = YES BINARY = gnunet-service-gns -ZONEKEY = $SERVICEHOME/.hostkey +ZONEKEY = zonefiles/test_zonekey +PRIVATE_ZONE = private +PRIVATE_ZONEKEY = zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey +SHORTEN_ZONE = short +SHORTEN_ZONEKEY = zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey #ZONEKEY = $SERVICEHOME/gns/zonekey.zkey HIJACK_DNS = NO UNIXPATH = /tmp/gnunet-service-gns.sock HOME = $SERVICEHOME -CONFIG = $DEFAULTCONFIG AUTO_IMPORT_PKEY = YES MAX_PARALLEL_BACKGROUND_QUERIES = 10 -DEFAULT_LOOKUP_TIMEOUT = 5 -RECORD_PUT_INTERVAL = 1 -ZONE_PUT_INTERVAL = 5 +DEFAULT_LOOKUP_TIMEOUT = 15 s +RECORD_PUT_INTERVAL = 1 h [nse] AUTOSTART = NO @@ -101,7 +99,6 @@ UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES HOSTNAME = localhost HOME = $SERVICEHOME -CONFIG = $DEFAULTCONFIG BINARY = gnunet-service-namestore ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; diff --git a/src/gns/test_gns_simple_mx_lookup.c b/src/gns/test_gns_simple_mx_lookup.c index fdc639a..cfaea67 100644 --- a/src/gns/test_gns_simple_mx_lookup.c +++ b/src/gns/test_gns_simple_mx_lookup.c @@ -32,37 +32,22 @@ #include "gnunet_dnsparser_lib.h" #include "gnunet_gns_service.h" -/* DEFINES */ -#define VERBOSE GNUNET_YES - /* Timeout for entire testcase */ #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) -/* If number of peers not in config file, use this number */ -#define DEFAULT_NUM_PEERS 2 - /* test records to resolve */ -#define TEST_DOMAIN "bob.gnunet" +#define TEST_DOMAIN "bob.gads" #define TEST_IP "127.0.0.1" #define TEST_RECORD_NAME "mail" #define TEST_MX_NAME "mail.+" -#define TEST_EXPECTED_MX "mail.bob.gnunet" +#define TEST_EXPECTED_MX "mail.bob.gads" #define TEST_AUTHORITY_NAME "bob" #define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey" -/* Globals */ - -/** - * Directory to store temp data in, defined in config file - */ -static char *test_directory; - -static struct GNUNET_TESTING_PeerGroup *pg; - /* Task handle to use to schedule test failure */ -GNUNET_SCHEDULER_TaskIdentifier die_task; +static GNUNET_SCHEDULER_TaskIdentifier die_task; /* Global return value (0 for success, anything else for failure) */ static int ok; @@ -71,36 +56,68 @@ static struct GNUNET_NAMESTORE_Handle *namestore_handle; static struct GNUNET_GNS_Handle *gns_handle; -const struct GNUNET_CONFIGURATION_Handle *cfg; +static const struct GNUNET_CONFIGURATION_Handle *cfg; + /** - * Check whether peers successfully shut down. + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. */ -void -shutdown_callback (void *cls, const char *emsg) +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - if (emsg != NULL) + die_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != gns_handle) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok); - if (ok == 0) - ok = 2; + GNUNET_GNS_disconnect(gns_handle); + gns_handle = NULL; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok); + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + ok = 1; } + +static void +end_badly_now () +{ + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + + +static void +shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_GNS_disconnect(gns_handle); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); +} + + static void on_lookup_result(void *cls, uint32_t rd_count, const struct GNUNET_NAMESTORE_RecordData *rd) { - struct in_addr a; int i; - char* addr; - int mx_found = 0; - int ip_found = 0; uint16_t mx_preference; char* mx; + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + + GNUNET_NAMESTORE_disconnect (namestore_handle); if (rd_count == 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -114,19 +131,7 @@ on_lookup_result(void *cls, uint32_t rd_count, for (i=0; i<rd_count; i++) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); - if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A) - { - memcpy(&a, rd[i].data, sizeof(a)); - addr = inet_ntoa(a); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr); - if (0 == strcmp(addr, TEST_IP)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "%s correctly resolved to %s!\n", TEST_DOMAIN, addr); - ip_found = 1; - } - } - else if (rd[i].record_type == GNUNET_GNS_RECORD_MX) + if (rd[i].record_type == GNUNET_GNS_RECORD_MX) { mx = (char*)rd[i].data+sizeof(uint16_t); mx_preference = *(uint16_t*)rd[i].data; @@ -137,29 +142,14 @@ on_lookup_result(void *cls, uint32_t rd_count, GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%s correctly resolved to %s!\n", TEST_DOMAIN, TEST_EXPECTED_MX); - mx_found = 1; + ok = 0; } } } } + + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); - if (ip_found && mx_found) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Test succeeded!\n"); - ok = 0; - } - - if (!ip_found && mx_found) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Test partially succeeded: A record not passed along!(NOT IMPLEMENTED)\n"); - ok = 0; - } - - GNUNET_GNS_disconnect(gns_handle); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); } @@ -170,51 +160,25 @@ on_lookup_result(void *cls, uint32_t rd_count, static void commence_testing (void *cls, int32_t success, const char *emsg) { - GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES); - gns_handle = GNUNET_GNS_connect(cfg); - if (NULL == gns_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to GNS!\n"); + end_badly_now(); + return; } - GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_MX, + GNUNET_NO, + NULL, &on_lookup_result, TEST_DOMAIN); } -/** - * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut - * down the peers without freeing memory associated with GET request. - */ -static void -end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - - if (pg != NULL) - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - GNUNET_SCHEDULER_cancel (die_task); -} - -/** - * Check if the get_handle is being used, if so stop the request. Either - * way, schedule the end_badly_cont function which actually shuts down the - * test. - */ -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n", - (char *) cls); - GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); - ok = 1; -} static void -do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *_cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) +do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) { struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; @@ -223,17 +187,17 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, struct GNUNET_CRYPTO_ShortHashCode bob_hash; struct GNUNET_CRYPTO_RsaSignature *sig; char* alice_keyfile; + struct GNUNET_TIME_Absolute et; - cfg = _cfg; - - GNUNET_SCHEDULER_cancel (die_task); + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); /* put records into namestore */ namestore_handle = GNUNET_NAMESTORE_connect(cfg); if (NULL == namestore_handle) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); - ok = -1; + end_badly_now(); return; } @@ -242,7 +206,7 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, &alice_keyfile)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; + end_badly_now(); return; } @@ -257,7 +221,7 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, struct in_addr *mail = GNUNET_malloc(sizeof(struct in_addr)); char *mx_record; uint16_t mx_preference = 1; - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + rd.expiration_time = UINT64_MAX; GNUNET_assert(1 == inet_pton (AF_INET, ip, mail)); GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash); @@ -265,6 +229,7 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); rd.data = &bob_hash; rd.record_type = GNUNET_GNS_RECORD_PKEY; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; GNUNET_NAMESTORE_record_create (namestore_handle, alice_key, @@ -280,117 +245,57 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, GNUNET_TIME_UNIT_FOREVER_ABS, TEST_RECORD_NAME, &rd, 1); - + et.abs_value = rd.expiration_time; GNUNET_NAMESTORE_record_put (namestore_handle, &bob_pkey, TEST_RECORD_NAME, - rd.expiration, + et, 1, &rd, sig, NULL, NULL); + GNUNET_free (sig); rd.data_size = sizeof(struct GNUNET_DNSPARSER_MxRecord)+strlen(TEST_MX_NAME)+1; - mx_record = GNUNET_malloc(sizeof(uint16_t)+strlen(TEST_MX_NAME)+1); + mx_record = GNUNET_malloc(sizeof(struct GNUNET_DNSPARSER_MxRecord)+strlen(TEST_MX_NAME)+1); memcpy(mx_record, &mx_preference, sizeof(uint16_t)); strcpy(mx_record+sizeof(uint16_t), TEST_MX_NAME); rd.data = mx_record; rd.record_type = GNUNET_GNS_RECORD_MX; sig = GNUNET_NAMESTORE_create_signature(bob_key, GNUNET_TIME_UNIT_FOREVER_ABS, - "+", + GNUNET_GNS_MASTERZONE_STR, &rd, 1); + et.abs_value = rd.expiration_time; GNUNET_NAMESTORE_record_put (namestore_handle, &bob_pkey, - "+", - rd.expiration, + GNUNET_GNS_MASTERZONE_STR, + et, 1, &rd, sig, &commence_testing, NULL); - GNUNET_free(mx_record); - GNUNET_free(mail); - GNUNET_free(sig); - GNUNET_CRYPTO_rsa_key_free(bob_key); - GNUNET_CRYPTO_rsa_key_free(alice_key); -} -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - cfg = c; - /* Get path from configuration file */ - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - /* Start alice */ - pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT, - NULL, NULL, &do_lookup, NULL, - NULL, NULL, NULL); + GNUNET_free (alice_keyfile); + GNUNET_free (mx_record); + GNUNET_free (mail); + GNUNET_free (sig); + GNUNET_CRYPTO_rsa_key_free (bob_key); + GNUNET_CRYPTO_rsa_key_free (alice_key); } -static int -check () -{ - int ret; - - /* Arguments for GNUNET_PROGRAM_run */ - char *const argv[] = { "test-gns-simple-delegated-lookup", /* Name to give running binary */ - "-c", - "test_gns_simple_lookup.conf", /* Config file to use */ -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - /* Run the run function as a new program */ - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-gns-simple-delegated-lookup", "nohelp", options, &run, - &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-gns-simple-delegated-lookup': Failed with error code %d\n", ret); - } - return ok; -} int main (int argc, char *argv[]) { - int ret; - - GNUNET_log_setup ("test-gns-simple-lookup", -#if VERBOSE - "DEBUG", -#else + ok = 1; + GNUNET_log_setup ("test-gns-simple-mx-lookup", "WARNING", -#endif NULL); - ret = check (); - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - return ret; + GNUNET_TESTING_peer_run ("test-gns-simple-mx-lookup", "test_gns_simple_lookup.conf", &do_check, NULL); + return ok; } -/* end of test_gns_twopeer.c */ +/* end of test_gns_simple_mx_lookup.c */ diff --git a/src/gns/test_gns_simple_shorten.c b/src/gns/test_gns_simple_shorten.c index 5371793..c6d49f8 100644 --- a/src/gns/test_gns_simple_shorten.c +++ b/src/gns/test_gns_simple_shorten.c @@ -32,36 +32,22 @@ #include "gnunet_dnsparser_lib.h" #include "gnunet_gns_service.h" -/* DEFINES */ -#define VERBOSE GNUNET_YES - /* Timeout for entire testcase */ #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) -/* If number of peers not in config file, use this number */ -#define DEFAULT_NUM_PEERS 2 - /* test records to resolve */ -#define TEST_DOMAIN "www.alice.bob.gnunet" +#define TEST_DOMAIN "www.alice.bob.gads" #define TEST_IP "127.0.0.1" #define TEST_RECORD_NAME "www" #define TEST_AUTHORITY_BOB "bob" #define TEST_AUTHORITY_ALICE "alice" #define TEST_ALICE_PSEU "carol" -#define TEST_EXPECTED_RESULT "www.carol.gnunet" +#define TEST_EXPECTED_RESULT "www.carol.gads" #define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey" #define KEYFILE_ALICE "../namestore/zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey" -/* Globals */ - -/** - * Directory to store temp data in, defined in config file - */ -static char *test_directory; - -static struct GNUNET_TESTING_PeerGroup *pg; /* Task handle to use to schedule test failure */ GNUNET_SCHEDULER_TaskIdentifier die_task; @@ -75,20 +61,40 @@ static struct GNUNET_GNS_Handle *gns_handle; const struct GNUNET_CONFIGURATION_Handle *cfg; +struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded priv_pkey; +struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded short_pkey; +struct GNUNET_CRYPTO_RsaPrivateKey *priv_key; +struct GNUNET_CRYPTO_RsaPrivateKey *short_key; + +struct GNUNET_CRYPTO_ShortHashCode priv_zone; +struct GNUNET_CRYPTO_ShortHashCode short_zone; + + /** - * Check whether peers successfully shut down. + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. */ static void -shutdown_callback (void *cls, const char *emsg) +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - if (emsg != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok); - if (ok == 0) - ok = 2; - } + die_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_SCHEDULER_shutdown (); + ok = 1; +} - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok); +void end_badly_now () +{ + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + +static void shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_GNS_disconnect(gns_handle); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); } /** @@ -97,14 +103,21 @@ shutdown_callback (void *cls, const char *emsg) static void process_shorten_result(void* cls, const char* sname) { - GNUNET_GNS_disconnect(gns_handle); - ok = 0; + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Disconnecting from namestore\n"); + GNUNET_NAMESTORE_disconnect (namestore_handle); if (sname == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "shorten test failed!\n"); + "Shorten test failed!\n"); ok = 1; } else @@ -114,17 +127,16 @@ process_shorten_result(void* cls, const char* sname) if (0 != strcmp(sname, TEST_EXPECTED_RESULT)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "shorten test failed! (wanted: %s got: %s\n", + "Shorten test failed! (wanted: %s got: %s\n", (char*)cls, sname); ok = 1; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shorten test succeeded!\n"); - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shorten test succeeded!\n"); + ok = 0; } - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); + + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } /** @@ -134,61 +146,29 @@ process_shorten_result(void* cls, const char* sname) static void commence_testing (void *cls, int32_t success, const char *emsg) { - - - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "disconnecting from namestore\n"); - GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "connecting to gns\n"); + "Connecting to gns\n"); gns_handle = GNUNET_GNS_connect(cfg); - if (NULL == gns_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "failed to connect to gns\n"); - ok = 1; + "Failed to connect to gns\n"); + end_badly_now (); return; } - GNUNET_GNS_shorten(gns_handle, TEST_DOMAIN, &process_shorten_result, - TEST_DOMAIN); - + GNUNET_assert (NULL != GNUNET_GNS_shorten (gns_handle, TEST_DOMAIN, + &priv_zone, + &short_zone, + &process_shorten_result, + TEST_DOMAIN)); } -/** - * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut - * down the peers without freeing memory associated with GET request. - */ -static void -end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - - if (pg != NULL) - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - GNUNET_SCHEDULER_cancel (die_task); -} -/** - * Check if the get_handle is being used, if so stop the request. Either - * way, schedule the end_badly_cont function which actually shuts down the - * test. - */ -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n", - (char *) cls); - GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); - ok = 1; -} -static void -do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *_cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) +void do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) { struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded our_pkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; @@ -200,17 +180,20 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, struct GNUNET_CRYPTO_ShortHashCode alice_hash; struct GNUNET_CRYPTO_RsaSignature *sig; char* our_keyfile; + char* private_keyfile; + char* shorten_keyfile; - cfg = _cfg; + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running test\n"); - GNUNET_SCHEDULER_cancel (die_task); /* put records into namestore */ namestore_handle = GNUNET_NAMESTORE_connect(cfg); if (NULL == namestore_handle) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); - ok = -1; + end_badly_now (); return; } @@ -219,7 +202,27 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, &our_keyfile)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; + end_badly_now (); + return; + } + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "SHORTEN_ZONEKEY", + &shorten_keyfile)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "Failed to get shorten zone key from cfg\n"); + end_badly_now (); + return; + } + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "PRIVATE_ZONEKEY", + &private_keyfile)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "Failed to get private zone key from cfg\n"); + end_badly_now (); return; } @@ -228,15 +231,25 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB); alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_ALICE); + priv_key = GNUNET_CRYPTO_rsa_key_create_from_file (private_keyfile); + short_key = GNUNET_CRYPTO_rsa_key_create_from_file (shorten_keyfile); + + GNUNET_free(shorten_keyfile); + GNUNET_free(private_keyfile); GNUNET_CRYPTO_rsa_key_get_public (our_key, &our_pkey); GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey); GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey); + GNUNET_CRYPTO_rsa_key_get_public (priv_key, &priv_pkey); + GNUNET_CRYPTO_rsa_key_get_public (short_key, &short_pkey); + + GNUNET_CRYPTO_short_hash(&priv_pkey, sizeof(priv_pkey), &priv_zone); + GNUNET_CRYPTO_short_hash(&short_pkey, sizeof(short_pkey), &short_zone); struct GNUNET_NAMESTORE_RecordData rd; char* ip = TEST_IP; struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr)); - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + rd.expiration_time = UINT64_MAX; GNUNET_assert(1 == inet_pton (AF_INET, ip, web)); GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash); @@ -244,6 +257,7 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); rd.data = &bob_hash; rd.record_type = GNUNET_GNS_RECORD_PKEY; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; /* put bob into our zone */ GNUNET_NAMESTORE_record_create (namestore_handle, @@ -307,82 +321,23 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, GNUNET_CRYPTO_rsa_key_free(our_key); GNUNET_CRYPTO_rsa_key_free(bob_key); GNUNET_CRYPTO_rsa_key_free(alice_key); -} + GNUNET_CRYPTO_rsa_key_free(priv_key); + GNUNET_CRYPTO_rsa_key_free(short_key); -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - cfg = c; - /* Get path from configuration file */ - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - /* Start alice */ - pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT, - NULL, NULL, &do_shorten, NULL, - NULL, NULL, NULL); } -static int -check () -{ - int ret; - - /* Arguments for GNUNET_PROGRAM_run */ - char *const argv[] = { "test-gns-simple-shorten", /* Name to give running binary */ - "-c", - "test_gns_simple_lookup.conf", /* Config file to use */ -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - /* Run the run function as a new program */ - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-gns-simple-shorten", "nohelp", options, &run, - &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-gns-simple-shorten': Failed with error code %d\n", ret); - } - return ok; -} int main (int argc, char *argv[]) { - int ret; - + ok = 1; GNUNET_log_setup ("test-gns-simple-shorten", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); - ret = check (); - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - return ret; + GNUNET_TESTING_peer_run ("test-gns-simple-shorten", + "test_gns_simple_lookup.conf", + &do_check, NULL); + return ok; } -/* end of test_gns_twopeer.c */ +/* end of test_gns_simple_shorten.c */ diff --git a/src/gns/test_gns_simple_srv_lookup.c b/src/gns/test_gns_simple_srv_lookup.c new file mode 100644 index 0000000..40e5aec --- /dev/null +++ b/src/gns/test_gns_simple_srv_lookup.c @@ -0,0 +1,308 @@ +/* + 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 gns/test_gns_simple_srv_lookup.c + * @brief base testcase for testing GNS SRV lookups + * + */ +#include "platform.h" +#include "gnunet_testing_lib.h" +#include "gnunet_core_service.h" +#include "block_dns.h" +#include "gnunet_signatures.h" +#include "gnunet_namestore_service.h" +#include "../namestore/namestore.h" +#include "gnunet_dnsparser_lib.h" +#include "gns_protocol.h" +#include "gnunet_gns_service.h" + +/* Timeout for entire testcase */ +#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) + +/* test records to resolve */ +#define TEST_DOMAIN "_sip._tcp.bob.gads" +#define TEST_IP "127.0.0.1" +#define TEST_RECORD_NAME "sipserver" +#define TEST_RECORD_NAME_SRV "_sip._tcp" +#define TEST_SRV_NAME "sipserver.+" +#define TEST_EXPECTED_SRV "sipserver.bob.gads" + +#define TEST_AUTHORITY_NAME "bob" + +#define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey" + +/* Globals */ + +/* Task handle to use to schedule test failure */ +GNUNET_SCHEDULER_TaskIdentifier die_task; + +/* Global return value (0 for success, anything else for failure) */ +static int ok; + +static struct GNUNET_NAMESTORE_Handle *namestore_handle; + +static struct GNUNET_GNS_Handle *gns_handle; + +const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. + */ +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != gns_handle) + { + GNUNET_GNS_disconnect(gns_handle); + gns_handle = NULL; + } + + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + ok = 1; +} + +static void +end_badly_now () +{ + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + +static void shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_GNS_disconnect(gns_handle); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); +} + +static void +on_lookup_result(void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + int i; + uint16_t *srv_data; + char* srv; + + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + + GNUNET_NAMESTORE_disconnect (namestore_handle); + if (rd_count == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup failed, rp_filtering?\n"); + ok = 2; + } + else + { + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls); + for (i=0; i<rd_count; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); + if (rd[i].record_type == GNUNET_GNS_RECORD_SRV) + { + srv_data = (uint16_t*)rd[i].data; + srv = (char*)&srv_data[3]; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got SRV %s with p=%d,w=%d,port=%d\n", + srv, srv_data, &srv_data[1], &srv_data[2]); + if (0 == strcmp(srv, TEST_EXPECTED_SRV)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "%s correctly resolved to %s!\n", TEST_DOMAIN, + TEST_EXPECTED_SRV); + ok = 0; + } + } + } + } + + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); + +} + + +/** + * Function scheduled to be run on the successful start of services + * tries to look up the dns record for TEST_DOMAIN + */ +static void +commence_testing (void *cls, int32_t success, const char *emsg) +{ + + gns_handle = GNUNET_GNS_connect(cfg); + if (NULL == gns_handle) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to GNS!\n"); + end_badly_now(); + return; + } + + GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_SRV, + GNUNET_NO, + NULL, + &on_lookup_result, TEST_DOMAIN); +} + + +static void +do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) +{ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; + struct GNUNET_CRYPTO_RsaPrivateKey *alice_key; + struct GNUNET_CRYPTO_RsaPrivateKey *bob_key; + struct GNUNET_CRYPTO_ShortHashCode bob_hash; + struct GNUNET_CRYPTO_RsaSignature *sig; + char* alice_keyfile; + struct srv_data *srv_data; + struct GNUNET_TIME_Absolute et; + + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + + /* put records into namestore */ + namestore_handle = GNUNET_NAMESTORE_connect(cfg); + if (NULL == namestore_handle) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); + end_badly_now(); + return; + } + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", + "ZONEKEY", + &alice_keyfile)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); + end_badly_now(); + return; + } + + alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile); + bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB); + + GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey); + GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey); + + struct GNUNET_NAMESTORE_RecordData rd; + char* ip = TEST_IP; + struct in_addr *sipserver = GNUNET_malloc (sizeof (struct in_addr)); + srv_data = GNUNET_malloc (sizeof (struct srv_data) + strlen (TEST_SRV_NAME) + 1); + uint16_t srv_weight = 60; + uint16_t srv_prio = 50; + uint16_t srv_port = 5060; + + rd.expiration_time = UINT64_MAX; + GNUNET_assert(1 == inet_pton (AF_INET, ip, sipserver)); + + GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash); + + rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); + rd.data = &bob_hash; + rd.record_type = GNUNET_GNS_RECORD_PKEY; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; + + GNUNET_NAMESTORE_record_create (namestore_handle, + alice_key, + TEST_AUTHORITY_NAME, + &rd, + NULL, + NULL); + + rd.data_size = sizeof (struct in_addr); + rd.data = sipserver; + rd.record_type = GNUNET_DNSPARSER_TYPE_A; + sig = GNUNET_NAMESTORE_create_signature(bob_key, + GNUNET_TIME_UNIT_FOREVER_ABS, + TEST_RECORD_NAME, + &rd, 1); + et.abs_value = rd.expiration_time; + GNUNET_NAMESTORE_record_put (namestore_handle, + &bob_pkey, + TEST_RECORD_NAME, + et, + 1, + &rd, + sig, + NULL, + NULL); + GNUNET_free (sig); + + rd.data_size = sizeof (struct srv_data)+strlen(TEST_SRV_NAME)+1; + srv_data->port = srv_port; + srv_data->prio = srv_prio; + srv_data->weight = srv_weight; + strcpy((char*)&srv_data[1], TEST_SRV_NAME); + rd.data = srv_data; + rd.record_type = GNUNET_GNS_RECORD_SRV; + sig = GNUNET_NAMESTORE_create_signature(bob_key, + GNUNET_TIME_UNIT_FOREVER_ABS, + TEST_RECORD_NAME_SRV, + &rd, 1); + et.abs_value = rd.expiration_time; + GNUNET_NAMESTORE_record_put (namestore_handle, + &bob_pkey, + TEST_RECORD_NAME_SRV, + et, + 1, + &rd, + sig, + &commence_testing, + NULL); + GNUNET_free (alice_keyfile); + GNUNET_free (srv_data); + GNUNET_free (sipserver); + GNUNET_free (sig); + GNUNET_CRYPTO_rsa_key_free (bob_key); + GNUNET_CRYPTO_rsa_key_free (alice_key); +} + + +int +main (int argc, char *argv[]) +{ + ok = 1; + GNUNET_log_setup ("test-gns-simple-srv-lookup", + "WARNING", + NULL); + GNUNET_TESTING_peer_run ("test-gns-simple-srv-lookup", "test_gns_simple_lookup.conf", &do_check, NULL); + GNUNET_DISK_directory_remove ("test-gns-simple-srv-lookup"); + return ok; +} + +/* end of test_gns_simple_srv_lookup.c */ diff --git a/src/gns/test_gns_simple_zkey_lookup.c b/src/gns/test_gns_simple_zkey_lookup.c index 8b9b78b..dd1a3f7 100644 --- a/src/gns/test_gns_simple_zkey_lookup.c +++ b/src/gns/test_gns_simple_zkey_lookup.c @@ -33,14 +33,8 @@ #include "gnunet_gns_service.h" #include "gns.h" -/* DEFINES */ -#define VERBOSE GNUNET_YES - /* Timeout for entire testcase */ -#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) - -/* If number of peers not in config file, use this number */ -#define DEFAULT_NUM_PEERS 2 +#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 40) /* test records to resolve */ #define TEST_IP "127.0.0.1" @@ -50,17 +44,8 @@ #define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey" -/* Globals */ - -/** - * Directory to store temp data in, defined in config file - */ -static char *test_directory; - -static struct GNUNET_TESTING_PeerGroup *pg; - /* Task handle to use to schedule test failure */ -GNUNET_SCHEDULER_TaskIdentifier die_task; +static GNUNET_SCHEDULER_TaskIdentifier die_task; /* Global return value (0 for success, anything else for failure) */ static int ok; @@ -69,26 +54,55 @@ static struct GNUNET_NAMESTORE_Handle *namestore_handle; static struct GNUNET_GNS_Handle *gns_handle; -const struct GNUNET_CONFIGURATION_Handle *cfg; +static const struct GNUNET_CONFIGURATION_Handle *cfg; + +static struct GNUNET_CRYPTO_ShortHashCode bob_hash; -struct GNUNET_CRYPTO_ShortHashCode bob_hash; /** - * Check whether peers successfully shut down. + * Check if the get_handle is being used, if so stop the request. Either + * way, schedule the end_badly_cont function which actually shuts down the + * test. */ -void -shutdown_callback (void *cls, const char *emsg) +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - if (emsg != NULL) + die_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != gns_handle) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok); - if (ok == 0) - ok = 2; + GNUNET_GNS_disconnect(gns_handle); + gns_handle = NULL; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok); + if (NULL != namestore_handle) + { + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; + } + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + ok = 1; +} + + +static void +end_badly_now () +{ + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + + +static void +shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_GNS_disconnect(gns_handle); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n"); + GNUNET_SCHEDULER_shutdown (); } + static void on_lookup_result(void *cls, uint32_t rd_count, const struct GNUNET_NAMESTORE_RecordData *rd) @@ -97,10 +111,18 @@ on_lookup_result(void *cls, uint32_t rd_count, int i; char* addr; + if (GNUNET_SCHEDULER_NO_TASK != die_task) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + + GNUNET_NAMESTORE_disconnect (namestore_handle); + namestore_handle = NULL; if (rd_count == 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Lookup failed, rp_filtering?\n"); + "Lookup failed\n"); ok = 2; } else @@ -110,7 +132,7 @@ on_lookup_result(void *cls, uint32_t rd_count, for (i=0; i<rd_count; i++) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type); - if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A) + if (rd[i].record_type == GNUNET_GNS_RECORD_A) { memcpy(&a, rd[i].data, sizeof(a)); addr = inet_ntoa(a); @@ -128,9 +150,8 @@ on_lookup_result(void *cls, uint32_t rd_count, } } } - GNUNET_GNS_disconnect(gns_handle); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); + + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } @@ -141,18 +162,17 @@ on_lookup_result(void *cls, uint32_t rd_count, static void commence_testing (void *cls, int32_t success, const char *emsg) { - char name[MAX_DNS_NAME_LENGTH]; + char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; char* pos; struct GNUNET_CRYPTO_ShortHashAsciiEncoded hash_str; - GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES); - gns_handle = GNUNET_GNS_connect(cfg); - if (NULL == gns_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to GNS!\n"); + end_badly_now (); + return; } pos = name; @@ -167,41 +187,17 @@ commence_testing (void *cls, int32_t success, const char *emsg) pos++; strcpy(pos, GNUNET_GNS_TLD_ZKEY); - GNUNET_GNS_lookup(gns_handle, name, GNUNET_GNS_RECORD_TYPE_A, + GNUNET_GNS_lookup(gns_handle, name, GNUNET_GNS_RECORD_A, + GNUNET_NO, + NULL, &on_lookup_result, NULL); } -/** - * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut - * down the peers without freeing memory associated with GET request. - */ -static void -end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - - if (pg != NULL) - GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); - GNUNET_SCHEDULER_cancel (die_task); -} -/** - * Check if the get_handle is being used, if so stop the request. Either - * way, schedule the end_badly_cont function which actually shuts down the - * test. - */ static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n", - (char *) cls); - GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); - ok = 1; -} - -static void -do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *_cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) +do_check (void *cls, + const struct GNUNET_CONFIGURATION_Handle *ccfg, + struct GNUNET_TESTING_Peer *peer) { struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; @@ -210,16 +206,15 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, struct GNUNET_CRYPTO_RsaSignature *sig; char* alice_keyfile; - cfg = _cfg; - - GNUNET_SCHEDULER_cancel (die_task); + cfg = ccfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); /* put records into namestore */ namestore_handle = GNUNET_NAMESTORE_connect(cfg); if (NULL == namestore_handle) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); - ok = -1; + end_badly_now (); return; } @@ -228,7 +223,7 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, &alice_keyfile)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; + end_badly_now (); return; } @@ -241,14 +236,15 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, struct GNUNET_NAMESTORE_RecordData rd; char* ip = TEST_IP; struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr)); - rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS; + rd.expiration_time = UINT64_MAX; GNUNET_assert(1 == inet_pton (AF_INET, ip, web)); - + GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash); rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode); rd.data = &bob_hash; rd.record_type = GNUNET_GNS_RECORD_PKEY; + rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; GNUNET_NAMESTORE_record_create (namestore_handle, alice_key, @@ -268,91 +264,33 @@ do_lookup(void *cls, const struct GNUNET_PeerIdentity *id, GNUNET_NAMESTORE_record_put (namestore_handle, &bob_pkey, TEST_RECORD_NAME, - rd.expiration, + GNUNET_TIME_UNIT_FOREVER_ABS, 1, &rd, sig, &commence_testing, NULL); - GNUNET_free(sig); - GNUNET_CRYPTO_rsa_key_free(bob_key); - GNUNET_CRYPTO_rsa_key_free(alice_key); -} - -static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - cfg = c; - /* Get path from configuration file */ - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", - &test_directory)) - { - ok = 404; - return; - } - - - /* Set up a task to end testing if peer start fails */ - die_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, - "didn't start all daemons in reasonable amount of time!!!"); - - /* Start alice */ - pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT, - NULL, NULL, &do_lookup, NULL, - NULL, NULL, NULL); + GNUNET_free (alice_keyfile); + GNUNET_free (web); + GNUNET_free (sig); + GNUNET_CRYPTO_rsa_key_free (bob_key); + GNUNET_CRYPTO_rsa_key_free (alice_key); } -static int -check () -{ - int ret; - - /* Arguments for GNUNET_PROGRAM_run */ - char *const argv[] = { "test-gns-simple-delegated-lookup", /* Name to give running binary */ - "-c", - "test_gns_simple_lookup.conf", /* Config file to use */ -#if VERBOSE - "-L", "DEBUG", -#endif - NULL - }; - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - /* Run the run function as a new program */ - ret = - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, - "test-gns-simple-delegated-lookup", "nohelp", options, &run, - &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-gns-simple-delegated-lookup': Failed with error code %d\n", ret); - } - return ok; -} int main (int argc, char *argv[]) { - int ret; + ok = 1; - GNUNET_log_setup ("test-gns-simple-lookup", -#if VERBOSE - "DEBUG", -#else + GNUNET_log_setup ("test-gns-simple-zkey-lookup", "WARNING", -#endif NULL); - ret = check (); - /** - * Need to remove base directory, subdirectories taken care - * of by the testing framework. - */ - return ret; + GNUNET_TESTING_peer_run ("test-gns-simple-zkey-lookup", + "test_gns_simple_lookup.conf", + &do_check, NULL); + return ok; } -/* end of test_gns_twopeer.c */ + +/* end of test_gns_simple_zkey_lookup.c */ diff --git a/src/gns/w32nsp-install.c b/src/gns/w32nsp-install.c new file mode 100644 index 0000000..dcdd16a --- /dev/null +++ b/src/gns/w32nsp-install.c @@ -0,0 +1,81 @@ +/*
+ 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 gns/w32nsp-install.c
+ * @brief W32 integration installer for GNS
+ * @author LRN
+ */
+
+#define INITGUID
+#include <windows.h>
+#include <nspapi.h>
+#include <ws2spi.h>
+#include "gnunet_w32nsp_lib.h"
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ int ret;
+ int r = 1;
+ WSADATA wsd;
+ GUID id = GNUNET_NAMESPACE_PROVIDER_DNS;
+ wchar_t *cmdl;
+ int wargc;
+ wchar_t **wargv;
+
+ if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
+ {
+ fprintf (stderr, "WSAStartup() failed: %lu\n", GetLastError());
+ return 5;
+ }
+
+ cmdl = GetCommandLineW ();
+ if (cmdl == NULL)
+ {
+ WSACleanup();
+ return 2;
+ }
+ wargv = CommandLineToArgvW (cmdl, &wargc);
+ if (wargv == NULL)
+ {
+ WSACleanup();
+ return 3;
+ }
+ r = 4;
+
+ if (wargc == 2)
+ {
+ ret = WSCInstallNameSpace (L"GNUnet DNS provider", wargv[1], NS_DNS, 1, &id);
+ if (ret == NO_ERROR)
+ {
+ r = 0;
+ }
+ else
+ {
+ r = 1;
+ fprintf (stderr,
+ "WSCInstallNameSpace(L\"GNUnet DNS provider\", \"%S\", %d, 0, %p) failed: %lu\n",
+ wargv[1], NS_DNS, &id, GetLastError ());
+ }
+ }
+ WSACleanup();
+ return r;
+}
diff --git a/src/gns/w32nsp-resolve.c b/src/gns/w32nsp-resolve.c new file mode 100644 index 0000000..3234a1e --- /dev/null +++ b/src/gns/w32nsp-resolve.c @@ -0,0 +1,369 @@ +/* + 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 gns/w32nsp-resolve.c + * @brief W32 integration for GNS + * @author LRN + */ +#define INITGUID +#include <windows.h> +#include <nspapi.h> +#include <ws2spi.h> +#include <nspapi.h> +#include <ws2tcpip.h> +#include "gnunet_w32nsp_lib.h" +#include <stdio.h> + +typedef int (WSPAPI *LPNSPSTARTUP) (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines); + +GUID host = {0x0002a800,0,0,{ 0xC0,0,0,0,0,0,0,0x46 }}; +GUID ip4 = {0x00090035,0,1,{ 0xc0,0,0,0,0,0,0,0x046}}; +GUID ip6 = {0x00090035,0,0x001c, { 0xc0,0,0,0,0,0,0,0x046}}; + +DEFINE_GUID(W32_DNS, 0x22059D40, 0x7E9E, 0x11CF, 0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B); + +#define DEFINE_DNS_GUID(a,x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46) +DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c); +DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021); +DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + +// +// Utility to turn a list of offsets into a list of addresses. Used +// to convert structures returned as BLOBs. +// + +VOID +FixList(PCHAR ** List, PCHAR Base) +{ + if(*List) + { + PCHAR * Addr; + + Addr = *List = (PCHAR *)( ((DWORD)*List + Base) ); + while(*Addr) + { + *Addr = (PCHAR)(((DWORD)*Addr + Base)); + Addr++; + } + } +} + + +// +// Routine to convert a hostent returned in a BLOB to one with +// usable pointers. The structure is converted in-place. +// +VOID +UnpackHostEnt(struct hostent * hostent) +{ + PCHAR pch; + + pch = (PCHAR)hostent; + + if(hostent->h_name) + { + hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch); + } + FixList(&hostent->h_aliases, pch); + FixList(&hostent->h_addr_list, pch); +} + + +static void +print_hostent (struct hostent *he) +{ + int i; + char **pAlias; + + printf("\tOfficial name: %s\n", he->h_name); + for (i=0, pAlias = he->h_aliases; *pAlias != 0; pAlias++) { + printf("\tAlternate name #%d: %s\n", ++i, *pAlias); + } + printf("\tAddress type: "); + switch (he->h_addrtype) { + case AF_INET: + printf("AF_INET\n"); + break; + case AF_INET6: + printf("AF_INET6\n"); + break; + case AF_NETBIOS: + printf("AF_NETBIOS\n"); + break; + default: + printf(" %d\n", he->h_addrtype); + break; + } + printf("\tAddress length: %d\n", he->h_length); + + if (he->h_addrtype == AF_INET) { + struct sockaddr_in addr; + memset (&addr, 0, sizeof (addr)); + addr.sin_family = AF_INET; + addr.sin_port = 0; + i = 0; + while (he->h_addr_list[i] != 0) { + char buf[1024]; + DWORD buflen = 1024; + addr.sin_addr = *(struct in_addr *) he->h_addr_list[i++]; + if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen)) + printf("\tIPv4 Address #%d: %s\n", i, buf); + else + printf("\tIPv4 Address #%d: Can't convert: %lu\n", i, GetLastError ()); + } + } else if (he->h_addrtype == AF_INET6) { + struct sockaddr_in6 addr; + memset (&addr, 0, sizeof (addr)); + addr.sin6_family = AF_INET6; + addr.sin6_port = 0; + i = 0; + while (he->h_addr_list[i] != 0) { + char buf[1024]; + DWORD buflen = 1024; + addr.sin6_addr = *(struct in6_addr *) he->h_addr_list[i++]; + if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen)) + printf("\tIPv6 Address #%d: %s\n", i, buf); + else + printf("\tIPv6 Address #%d: Can't convert: %lu\n", i, GetLastError ()); + } + } +} + + +int +main (int argc, char **argv) +{ + int ret; + int r = 1; + WSADATA wsd; + GUID *prov = NULL; + GUID *sc = NULL; + wchar_t *cmdl; + int wargc; + wchar_t **wargv; + + if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) + { + fprintf (stderr, "WSAStartup() failed: %lu\n", GetLastError()); + return 5; + } + + cmdl = GetCommandLineW (); + if (cmdl == NULL) + { + WSACleanup(); + return 2; + } + wargv = CommandLineToArgvW (cmdl, &wargc); + if (wargv == NULL) + { + WSACleanup(); + return 3; + } + r = 4; + + if (wargc == 5) + { + if (wcscmp (wargv[1], L"A") == 0) + sc = &SVCID_DNS_TYPE_A; + else if (wcscmp (wargv[1], L"AAAA") == 0) + sc = &SVCID_DNS_TYPE_AAAA; + else if (wcscmp (wargv[1], L"name") == 0) + sc = &SVCID_HOSTNAME; + else if (wcscmp (wargv[1], L"addr") == 0) + sc = &SVCID_INET_HOSTADDRBYNAME; + else + wargc -= 1; + if (wcscmp (wargv[4], L"mswdns") == 0) + prov = &W32_DNS; + else if (wcscmp (wargv[4], L"gnunetdns") == 0) + prov = &GNUNET_NAMESPACE_PROVIDER_DNS; + else + wargc -= 1; + } + + if (wargc == 5) + { + HMODULE nsp; + + nsp = LoadLibraryW (wargv[3]); + if (nsp == NULL) + { + fprintf (stderr, "Failed to load library `%S'\n", wargv[3]); + } + else + { + LPNSPSTARTUP startup = (LPNSPSTARTUP) GetProcAddress (nsp, "NSPStartup"); + if (startup != NULL) + { + NSP_ROUTINE api; + ret = startup (prov, &api); + if (NO_ERROR != ret) + fprintf (stderr, "startup failed\n"); + else + { + HANDLE lookup; + WSAQUERYSETW search; + char buf[4096]; + WSAQUERYSETW *result = (WSAQUERYSETW *) buf; + DWORD resultsize; + DWORD err; + memset (&search, 0, sizeof (search)); + search.dwSize = sizeof (search); + search.lpszServiceInstanceName = (wcscmp (wargv[2], L" ") == 0) ? NULL : wargv[2]; + search.lpServiceClassId = sc; + search.lpNSProviderId = prov; + search.dwNameSpace = NS_ALL; + ret = api.NSPLookupServiceBegin (prov, &search, NULL, LUP_RETURN_ALL, &lookup); + if (ret != NO_ERROR) + { + fprintf (stderr, "lookup start failed\n"); + } + else + { + resultsize = 4096; + ret = api.NSPLookupServiceNext (lookup, LUP_RETURN_ALL, &resultsize, result); + err = GetLastError (); + if (ret != NO_ERROR) + { + fprintf (stderr, "lookup next failed\n"); + } + else + { + int i; + printf ("Got result:\n"); + printf (" lpszServiceInstanceName: %S\n", result->lpszServiceInstanceName ? result->lpszServiceInstanceName : L"NULL"); + if (result->lpServiceClassId) + printf (" lpServiceClassId: { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n", + result->lpServiceClassId->Data1, result->lpServiceClassId->Data2, result->lpServiceClassId->Data3, result->lpServiceClassId->Data4[0], + result->lpServiceClassId->Data4[1], result->lpServiceClassId->Data4[2], result->lpServiceClassId->Data4[3], result->lpServiceClassId->Data4[4], + result->lpServiceClassId->Data4[5], result->lpServiceClassId->Data4[6], result->lpServiceClassId->Data4[7]); + else + printf (" lpServiceClassId: NULL\n"); + if (result->lpVersion) + printf (" lpVersion: 0x%08lX, %d\n", result->lpVersion->dwVersion, result->lpVersion->ecHow); + else + printf (" lpVersion: NULL\n"); + printf (" lpszComment: %S\n", result->lpszComment ? result->lpszComment : L"NULL"); + printf (" dwNameSpace: %lu\n", result->dwNameSpace); + if (result->lpNSProviderId) + printf (" lpNSProviderId: { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n", + result->lpNSProviderId->Data1, result->lpNSProviderId->Data2, result->lpNSProviderId->Data3, result->lpNSProviderId->Data4[0], + result->lpNSProviderId->Data4[1], result->lpNSProviderId->Data4[2], result->lpNSProviderId->Data4[3], result->lpNSProviderId->Data4[4], + result->lpNSProviderId->Data4[5], result->lpNSProviderId->Data4[6], result->lpNSProviderId->Data4[7]); + else + printf (" lpNSProviderId: NULL\n"); + printf (" lpszContext: %S\n", result->lpszContext ? result->lpszContext : L"NULL"); + printf (" dwNumberOfProtocols: %lu\n", result->dwNumberOfProtocols); + printf (" lpszQueryString: %S\n", result->lpszQueryString ? result->lpszQueryString : L"NULL"); + printf (" dwNumberOfCsAddrs: %lu\n", result->dwNumberOfCsAddrs); + for (i = 0; i < result->dwNumberOfCsAddrs; i++) + { + switch (result->lpcsaBuffer[i].iSocketType) + { + case SOCK_STREAM: + printf (" %d: iSocketType = SOCK_STREAM\n", i); + break; + case SOCK_DGRAM: + printf (" %d: iSocketType = SOCK_DGRAM\n", i); + break; + default: + printf (" %d: iSocketType = %d\n", i, result->lpcsaBuffer[i].iSocketType); + } + switch (result->lpcsaBuffer[i].iProtocol) + { + case IPPROTO_TCP: + printf (" %d: iProtocol = IPPROTO_TCP\n", i); + break; + case IPPROTO_UDP: + printf (" %d: iProtocol = IPPROTO_UDP\n", i); + break; + default: + printf (" %d: iProtocol = %d\n", i, result->lpcsaBuffer[i].iProtocol); + } + switch (result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family) + { + case AF_INET: + printf (" %d: loc family = AF_INET\n", i); + break; + case AF_INET6: + printf (" %d: loc family = AF_INET6\n", i); + break; + default: + printf (" %d: loc family = %hu\n", i, result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family); + } + switch (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family) + { + case AF_INET: + printf (" %d: rem family = AF_INET\n", i); + break; + case AF_INET6: + printf (" %d: rem family = AF_INET6\n", i); + break; + default: + printf (" %d: rem family = %hu\n", i, result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family); + } + char buf[1024]; + DWORD buflen = 1024; + if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].LocalAddr.lpSockaddr, result->lpcsaBuffer[i].LocalAddr.iSockaddrLength, NULL, buf, &buflen)) + printf("\tLocal Address #%d: %s\n", i, buf); + else + printf("\tLocal Address #%d: Can't convert: %lu\n", i, GetLastError ()); + buflen = 1024; + if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr, result->lpcsaBuffer[i].RemoteAddr.iSockaddrLength, NULL, buf, &buflen)) + printf("\tRemote Address #%d: %s\n", i, buf); + else + printf("\tRemote Address #%d: Can't convert: %lu\n", i, GetLastError ()); + } + printf (" dwOutputFlags: 0x%08lX\n", result->dwOutputFlags); + printf (" lpBlob: 0x%p\n", result->lpBlob); + if (result->lpBlob) + { + struct hostent *he = malloc (result->lpBlob->cbSize); + if (he != NULL) + { + memcpy (he, result->lpBlob->pBlobData, result->lpBlob->cbSize); + UnpackHostEnt (he); + print_hostent (he); + free (he); + } + } + } + ret = api.NSPLookupServiceEnd (lookup); + if (ret != NO_ERROR) + printf ("NSPLookupServiceEnd() failed: %lu\n", GetLastError ()); + } + api.NSPCleanup (prov); + } + } + FreeLibrary (nsp); + } + } + WSACleanup(); + return r; +} diff --git a/src/gns/w32nsp-uninstall.c b/src/gns/w32nsp-uninstall.c new file mode 100644 index 0000000..bb8db66 --- /dev/null +++ b/src/gns/w32nsp-uninstall.c @@ -0,0 +1,30 @@ +#define INITGUID
+#include <windows.h>
+#include <nspapi.h>
+#include <ws2spi.h>
+#include "gnunet_w32nsp_lib.h"
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ int ret;
+ GUID id = GNUNET_NAMESPACE_PROVIDER_DNS;
+ WSADATA wsd;
+
+ if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
+ {
+ fprintf (stderr, "WSAStartup() failed: %lu\n", GetLastError());
+ return 5;
+ }
+
+ ret = WSCUnInstallNameSpace (&id);
+ if (ret == NO_ERROR)
+ {
+ WSACleanup ();
+ return 0;
+ }
+ fprintf (stderr, "WSCUnInstallNameSpace() failed: %lu\n", GetLastError ());
+ WSACleanup ();
+ return 1;
+}
\ No newline at end of file diff --git a/src/gns/w32nsp.c b/src/gns/w32nsp.c new file mode 100644 index 0000000..6e58353 --- /dev/null +++ b/src/gns/w32nsp.c @@ -0,0 +1,705 @@ +/* + 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 gns/w32nsp.c + * @brief W32 integration for GNS + * @author LRN + */ +/* This code is partially based upon samples from the book + * "Network Programming For Microsoft Windows, 2Nd Edition". + */ + +#define INITGUID +#include <windows.h> +#include <nspapi.h> +#include <stdint.h> +#include <ws2tcpip.h> +#include <ws2spi.h> + +#if 1 +# define DEBUGLOG(s, ...) +#endif +#if 0 +# define DEBUGLOG(s, ...) printf (s, ##__VA_ARGS__) +#endif + +#define WINDOWS 1 +#define MINGW 1 +#ifndef __BYTE_ORDER +#ifdef _BYTE_ORDER +#define __BYTE_ORDER _BYTE_ORDER +#else +#ifdef BYTE_ORDER +#define __BYTE_ORDER BYTE_ORDER +#endif +#endif +#endif +#ifndef __BIG_ENDIAN +#ifdef _BIG_ENDIAN +#define __BIG_ENDIAN _BIG_ENDIAN +#else +#ifdef BIG_ENDIAN +#define __BIG_ENDIAN BIG_ENDIAN +#endif +#endif +#endif +#ifndef __LITTLE_ENDIAN +#ifdef _LITTLE_ENDIAN +#define __LITTLE_ENDIAN _LITTLE_ENDIAN +#else +#ifdef LITTLE_ENDIAN +#define __LITTLE_ENDIAN LITTLE_ENDIAN +#endif +#endif +#endif +#include "gnunet_w32nsp_lib.h" +#include "w32resolver.h" + +#define NSPAPI_VERSION_MAJOR 4 +#define NSPAPI_VERSION_MINOR 4 + +#define REPLY_LIFETIME 60*5 + +#define STATE_BEGIN 0x01 +#define STATE_END 0x02 +#define STATE_REPLY 0x04 +#define STATE_GHBN 0x08 + +uint64_t +GNUNET_htonll (uint64_t n) +{ +#if __BYTE_ORDER == __BIG_ENDIAN + return n; +#elif __BYTE_ORDER == __LITTLE_ENDIAN + return (((uint64_t) htonl (n)) << 32) + htonl (n >> 32); +#else + #error byteorder undefined +#endif +} + +CRITICAL_SECTION records_cs; + +struct record +{ + SOCKET s; + DWORD flags; + uint8_t state; + char *buf; + wchar_t *name; +}; + +static struct record *records = NULL; +static size_t records_len = 0; +static size_t records_size = 0; + +int +resize_records () +{ + size_t new_size = records_len > 0 ? records_len * 2 : 5; + struct record *new_records = malloc (new_size * sizeof (struct record)); + if (new_records == NULL) + { + SetLastError (WSA_NOT_ENOUGH_MEMORY); + return 0; + } + memcpy (new_records, records, records_len * sizeof (struct record)); + memset (&new_records[records_len], 0, sizeof (struct record) * (new_size - records_len)); + records_size = new_size; + free (records); + records = new_records; + return 1; +} + +int +add_record (SOCKET s, const wchar_t *name, DWORD flags) +{ + int res = 1; + int i; + int empty = -1; + //EnterCriticalSection (&records_cs); + for (i = 0; i < records_len; i++) + if (records[i].state == 0) + break; + empty = i; + if (i == records_len) + { + res = resize_records (); + if (res) + empty = records_len++; + } + if (res) + { + struct record r; + r.s = s; + r.flags = flags; + r.name = (wchar_t *) name; + r.state = 1; + r.buf = NULL; + if (name) + r.name = wcsdup (name); + records[empty] = r; + } + //LeaveCriticalSection (&records_cs); + return res; +} + +void +free_record (int i) +{ + if (records[i].name) + free (records[i].name); + records[i].state = 0; +} + +/* These are not defined by mingw.org headers at the moment*/ +typedef INT (WSPAPI *LPNSPIOCTL) (HANDLE,DWORD,LPVOID,DWORD,LPVOID,DWORD,LPDWORD,LPWSACOMPLETION,LPWSATHREADID); +typedef struct _NSP_ROUTINE_XP { + DWORD cbSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + LPNSPCLEANUP NSPCleanup; + LPNSPLOOKUPSERVICEBEGIN NSPLookupServiceBegin; + LPNSPLOOKUPSERVICENEXT NSPLookupServiceNext; + LPNSPLOOKUPSERVICEEND NSPLookupServiceEnd; + LPNSPSETSERVICE NSPSetService; + LPNSPINSTALLSERVICECLASS NSPInstallServiceClass; + LPNSPREMOVESERVICECLASS NSPRemoveServiceClass; + LPNSPGETSERVICECLASSINFO NSPGetServiceClassInfo; + LPNSPIOCTL NSPIoctl; +} NSP_ROUTINE_XP; + +static SOCKET +connect_to_dns_resolver () +{ + struct sockaddr_in addr; + SOCKET r; + int ret; + + r = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (INVALID_SOCKET == r) + { + SetLastError (16004); + return r; + } + + addr.sin_family = AF_INET; + addr.sin_port = htons (5353); /* TCP 5353 is not registered; UDP 5353 is */ + addr.sin_addr.s_addr = inet_addr ("127.0.0.1"); + + ret = connect (r, (struct sockaddr *) &addr, sizeof (addr)); + if (SOCKET_ERROR == ret) + { + DWORD err = GetLastError (); + closesocket (r); + SetLastError (err); + SetLastError (16005); + r = INVALID_SOCKET; + } + return r; +} + +static int +send_name_to_ip_request (LPWSAQUERYSETW lpqsRestrictions, + LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags, + SOCKET *resolver) +{ + struct GNUNET_W32RESOLVER_GetMessage *msg; + int af4 = 0; + int af6 = 0; + char *buf; + int ret = 1; + int i; + uint32_t id; + size_t size = sizeof (struct GNUNET_W32RESOLVER_GetMessage); + size_t namelen = 0; + if (lpqsRestrictions->lpszServiceInstanceName) + namelen = sizeof (wchar_t) * (wcslen (lpqsRestrictions->lpszServiceInstanceName) + 1); + size += namelen; + buf = malloc (size); + msg = (struct GNUNET_W32RESOLVER_GetMessage *) buf; + msg->header.size = htons (size); + msg->header.type = htons (GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST); + if (lpqsRestrictions->dwNumberOfProtocols > 0) + { + int i; + for (i = 0; i < lpqsRestrictions->dwNumberOfProtocols; i++) + { + if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET) + af4 = 1; + if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET6) + af6 = 1; + } + } + if (af4 && !af6) + msg->af = htonl (AF_INET); + else if (af6 && !af4) + msg->af = htonl (AF_INET6); + else + msg->af = htonl (AF_UNSPEC); + if (lpqsRestrictions->lpszServiceInstanceName) + memcpy (&msg[1], lpqsRestrictions->lpszServiceInstanceName, namelen); + msg->sc_data1 = htonl (lpqsRestrictions->lpServiceClassId->Data1); + msg->sc_data2 = htons (lpqsRestrictions->lpServiceClassId->Data2); + msg->sc_data3 = htons (lpqsRestrictions->lpServiceClassId->Data3); + msg->sc_data4 = 0; + for (i = 0; i < 8; i++) + msg->sc_data4 |= ((uint64_t) lpqsRestrictions->lpServiceClassId->Data4[i]) << ((7 - i) * 8); + msg->sc_data4 = GNUNET_htonll (msg->sc_data4); + *resolver = connect_to_dns_resolver (); + if (*resolver != INVALID_SOCKET) + { + if (size != send (*resolver, buf, size, 0)) + { + DWORD err = GetLastError (); + closesocket (*resolver); + *resolver = INVALID_SOCKET; + DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: failed to send request: %lu\n", err); + SetLastError (WSATRY_AGAIN); + ret = 0; + } + } + else + ret = 0; + free (buf); + return ret; +} + +int WSPAPI +NSPCleanup (LPGUID lpProviderId) +{ + DEBUGLOG ("NSPCleanup\n"); + if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS)) + { + return NO_ERROR; + } + SetLastError (WSAEINVALIDPROVIDER); + return SOCKET_ERROR; +} + +BOOL WINAPI +DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + if (!InitializeCriticalSectionAndSpinCount (&records_cs, 0x00000400)) + { + return FALSE; + } + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + DeleteCriticalSection (&records_cs); + break; + } + return TRUE; +} + + + + +int WSPAPI +GNUNET_W32NSP_LookupServiceBegin (LPGUID lpProviderId, LPWSAQUERYSETW lpqsRestrictions, + LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags, + LPHANDLE lphLookup) +{ + DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin\n"); + if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS)) + { + SOCKET s; + if (lpqsRestrictions->dwNameSpace != NS_DNS && lpqsRestrictions->dwNameSpace != NS_ALL) + { + DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: wrong namespace\n"); + SetLastError (WSANO_DATA); + return SOCKET_ERROR; + } + if (lpqsRestrictions->lpszServiceInstanceName != NULL) + { + wchar_t *s = lpqsRestrictions->lpszServiceInstanceName; + size_t len = wcslen (s); + if (len >= 4 && wcscmp (&s[len - 4], L"zkey") == 0) + { + } + else if (len >= 4 && wcscmp (&s[len - 4], L"gads") == 0) + { + } + else + { + DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: unsupported TLD\n"); + SetLastError (WSANO_DATA); + return SOCKET_ERROR; + } + } + + if (send_name_to_ip_request (lpqsRestrictions, + lpServiceClassInfo, dwControlFlags, &s)) + { + if (!(add_record (s, lpqsRestrictions->lpszServiceInstanceName, dwControlFlags))) + { + DWORD err = GetLastError (); + DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: failed to add a record\n"); + closesocket (s); + SetLastError (err); + return SOCKET_ERROR; + } + *lphLookup = (HANDLE) s; + DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: OK (%lu)\n", GetLastError ()); + return NO_ERROR; + } + return SOCKET_ERROR; + } + DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: wrong provider\n"); + SetLastError (WSAEINVALIDPROVIDER); + return SOCKET_ERROR; +} + +#define UnmarshallPtr(ptr, ptrtype, base) \ + if (ptr) \ + ptr = (ptrtype *) (base + (uintptr_t) ptr) + +void +UnmarshallWSAQUERYSETW (LPWSAQUERYSETW req) +{ + int i; + char *base = (char *) req; + UnmarshallPtr (req->lpszServiceInstanceName, wchar_t, base); + UnmarshallPtr (req->lpServiceClassId, GUID, base); + UnmarshallPtr (req->lpVersion, WSAVERSION, base); + UnmarshallPtr (req->lpszComment, wchar_t, base); + UnmarshallPtr (req->lpNSProviderId, GUID, base); + UnmarshallPtr (req->lpszContext, wchar_t, base); + UnmarshallPtr (req->lpafpProtocols, AFPROTOCOLS, base); + UnmarshallPtr (req->lpszQueryString, wchar_t, base); + UnmarshallPtr (req->lpcsaBuffer, CSADDR_INFO, base); + for (i = 0; i < req->dwNumberOfCsAddrs; i++) + { + UnmarshallPtr (req->lpcsaBuffer[i].LocalAddr.lpSockaddr, SOCKADDR, base); + UnmarshallPtr (req->lpcsaBuffer[i].RemoteAddr.lpSockaddr, SOCKADDR, base); + } + UnmarshallPtr (req->lpBlob, BLOB, base); + if (req->lpBlob) + UnmarshallPtr (req->lpBlob->pBlobData, BYTE, base); +} + +int WSAAPI +GNUNET_W32NSP_LookupServiceNext (HANDLE hLookup, DWORD dwControlFlags, + LPDWORD lpdwBufferLength, LPWSAQUERYSET lpqsResults) +{ + DWORD effective_flags; + int i; + struct GNUNET_MessageHeader header = {0, 0}; + int rec = -1; + int rc; + int to_receive; + int t; + char *buf; + + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext\n"); + //EnterCriticalSection (&records_cs); + for (i = 0; i < records_len; i++) + { + if (records[i].s == (SOCKET) hLookup) + { + rec = i; + break; + } + } + if (rec == -1) + { + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: invalid handle\n"); + SetLastError (WSA_INVALID_HANDLE); + //LeaveCriticalSection (&records_cs); + return SOCKET_ERROR; + } + if (records[rec].state & 4) + { + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: session is closed\n"); + SetLastError (WSA_E_NO_MORE); + //LeaveCriticalSection (&records_cs); + return SOCKET_ERROR; + } + effective_flags = dwControlFlags & records[rec].flags; + if (records[rec].buf) + { + header = *((struct GNUNET_MessageHeader *) records[rec].buf); + if (dwControlFlags & LUP_FLUSHCACHE) + { + free (records[rec].buf); + records[rec].buf = NULL; + } + else + { + if (*lpdwBufferLength < header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)) + { + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n"); + SetLastError (WSAEFAULT); + //LeaveCriticalSection (&records_cs); + return SOCKET_ERROR; + } + memcpy (lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)records[rec].buf)[1], header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)); + free (records[rec].buf); + records[rec].buf = NULL; + //LeaveCriticalSection (&records_cs); + UnmarshallWSAQUERYSETW ((LPWSAQUERYSETW) lpqsResults); + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: OK (from buffer)\n"); + return NO_ERROR; + } + } + records[rec].state |= 8; + //LeaveCriticalSection (&records_cs); + to_receive = sizeof (header); + rc = 0; + while (to_receive > 0) + { + t = recv ((SOCKET) hLookup, &((char *) &header)[rc], to_receive, 0); + if (t > 0) + { + rc += t; + to_receive -= t; + } + else + break; + } + //EnterCriticalSection (&records_cs); + records[rec].state &= ~8; + if (rc != sizeof (header)) + { + if (records[rec].state & 2) + { + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: call cancelled\n"); + SetLastError (WSA_E_CANCELLED); + } + else + { + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data\n"); + SetLastError (WSA_E_NO_MORE); + } + records[rec].state |= 4; + //LeaveCriticalSection (&records_cs); + return SOCKET_ERROR; + } + records[rec].state &= ~8; + header.type = ntohs (header.type); + header.size = ntohs (header.size); + if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE || + (header.type == GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE && + header.size == sizeof (header))) + { + records[rec].state |= 4; + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: header is wrong or type is wrong or no data\n"); + //LeaveCriticalSection (&records_cs); + SetLastError (WSA_E_NO_MORE); + return SOCKET_ERROR; + } + buf = malloc (header.size); + if (buf == NULL) + { + records[rec].state |= 4; + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: malloc() failed\n"); + //LeaveCriticalSection (&records_cs); + SetLastError (WSA_E_NO_MORE); + return SOCKET_ERROR; + } + records[rec].state |= 8; + //LeaveCriticalSection (&records_cs); + memcpy (buf, &header, sizeof (header)); + to_receive = header.size - sizeof (header); + rc = 0; + while (to_receive > 0) + { + t = recv ((SOCKET) hLookup, &((char *) &((struct GNUNET_MessageHeader *) buf)[1])[rc], to_receive, 0); + if (t > 0) + { + rc += t; + to_receive -= t; + } + else + break; + } + //EnterCriticalSection (&records_cs); + records[rec].state &= ~8; + if (rc != header.size - sizeof (header)) + { + free (buf); + if (records[rec].state & 2) + { + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: call cancelled\n"); + SetLastError (WSA_E_CANCELLED); + } + else + { + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data\n"); + SetLastError (WSA_E_NO_MORE); + } + records[rec].state |= 4; + //LeaveCriticalSection (&records_cs); + return SOCKET_ERROR; + } + if (*lpdwBufferLength < header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)) + { + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n"); + SetLastError (WSAEFAULT); + records[rec].buf = buf; + //LeaveCriticalSection (&records_cs); + return SOCKET_ERROR; + } + //LeaveCriticalSection (&records_cs); + memcpy (lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)buf)[1], header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)); + free (buf); + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: OK\n"); + UnmarshallWSAQUERYSETW ((LPWSAQUERYSETW) lpqsResults); + DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: returning (%lu)\n", GetLastError ()); + return NO_ERROR; +} + +int WSPAPI +GNUNET_W32NSP_LookupServiceEnd (HANDLE hLookup) +{ + DWORD effective_flags; + int i; + struct GNUNET_MessageHeader header = {0, 0}; + int rec = -1; + int rc; + char *buf; + + DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd\n"); + //EnterCriticalSection (&records_cs); + for (i = 0; i < records_len; i++) + { + if (records[i].s == (SOCKET) hLookup) + { + rec = i; + break; + } + } + if (rec == -1) + { + SetLastError (WSA_INVALID_HANDLE); + //LeaveCriticalSection (&records_cs); + DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: invalid handle\n"); + return SOCKET_ERROR; + } + records[rec].state |= 2; + closesocket (records[rec].s); + while (records[rec].state & 8) + { + //LeaveCriticalSection (&records_cs); + Sleep (10); + //EnterCriticalSection (&records_cs); + } + if (records[rec].buf) + free (records[rec].buf); + records[rec].buf = NULL; + records[rec].state = 0; + if (records[rec].name) + free (records[rec].name); + //LeaveCriticalSection (&records_cs); + DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: OK\n"); + return NO_ERROR; +} + +int WSAAPI +GNUNET_W32NSP_SetService (LPGUID lpProviderId, + LPWSASERVICECLASSINFOW lpServiceClassInfo, LPWSAQUERYSETW lpqsRegInfo, + WSAESETSERVICEOP essOperation, DWORD dwControlFlags) +{ + DEBUGLOG ("GNUNET_W32NSP_SetService\n"); + SetLastError (WSAEOPNOTSUPP); + return SOCKET_ERROR; +} + +int WSAAPI +GNUNET_W32NSP_InstallServiceClass (LPGUID lpProviderId, + LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + DEBUGLOG ("GNUNET_W32NSP_InstallServiceClass\n"); + SetLastError (WSAEOPNOTSUPP); + return SOCKET_ERROR; +} + + +int WSAAPI +GNUNET_W32NSP_RemoveServiceClass (LPGUID lpProviderId, LPGUID lpServiceClassId) +{ + DEBUGLOG ("GNUNET_W32NSP_RemoveServiceClass\n"); + SetLastError (WSAEOPNOTSUPP); + return SOCKET_ERROR; +} + +int WSAAPI +GNUNET_W32NSP_GetServiceClassInfo (LPGUID lpProviderId, LPDWORD lpdwBufSize, + LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + DEBUGLOG ("GNUNET_W32NSP_GetServiceClassInfo\n"); + SetLastError (WSAEOPNOTSUPP); + return SOCKET_ERROR; +} + +int WSAAPI +GNUNET_W32NSP_Ioctl (HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer, + DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, + LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion, + LPWSATHREADID lpThreadId) +{ + DEBUGLOG ("GNUNET_W32NSP_Ioctl\n"); + SetLastError (WSAEOPNOTSUPP); + return SOCKET_ERROR; +} + +/** + * This function is called by Winsock to hook up our provider. + * It is the only function that [should be/is] exported by the + * provider. All other routines are passed as pointers in lpnspRoutines. + */ +int WSPAPI +NSPStartup (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines) +{ + if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS)) + { + if (!connect_to_dns_resolver ()) + { + return SOCKET_ERROR; + } + /* This assumes that NSP_ROUTINE struct doesn't have a NSPIoctl member. + * If it does, you need to use FIELD_OFFSET() macro to get offset of NSPIoctl + * and use that offset as cbSize. + */ + lpnspRoutines->cbSize = sizeof(NSP_ROUTINE_XP); + + lpnspRoutines->dwMajorVersion = NSPAPI_VERSION_MAJOR; + lpnspRoutines->dwMinorVersion = NSPAPI_VERSION_MINOR; + lpnspRoutines->NSPCleanup = NSPCleanup; + lpnspRoutines->NSPLookupServiceBegin = GNUNET_W32NSP_LookupServiceBegin; + lpnspRoutines->NSPLookupServiceNext = GNUNET_W32NSP_LookupServiceNext; + lpnspRoutines->NSPLookupServiceEnd = GNUNET_W32NSP_LookupServiceEnd; + lpnspRoutines->NSPSetService = GNUNET_W32NSP_SetService; + lpnspRoutines->NSPInstallServiceClass = GNUNET_W32NSP_InstallServiceClass; + lpnspRoutines->NSPRemoveServiceClass = GNUNET_W32NSP_RemoveServiceClass; + lpnspRoutines->NSPGetServiceClassInfo = GNUNET_W32NSP_GetServiceClassInfo; + ((NSP_ROUTINE_XP *) lpnspRoutines)->NSPIoctl = GNUNET_W32NSP_Ioctl; + return NO_ERROR; + } + SetLastError (WSAEINVALIDPROVIDER); + return SOCKET_ERROR; +} + diff --git a/src/gns/zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey b/src/gns/zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey Binary files differnew file mode 100644 index 0000000..b0fae62 --- /dev/null +++ b/src/gns/zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey diff --git a/src/gns/zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey b/src/gns/zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey Binary files differnew file mode 100644 index 0000000..90da077 --- /dev/null +++ b/src/gns/zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey diff --git a/src/gns/zonefiles/test_zonekey b/src/gns/zonefiles/test_zonekey Binary files differnew file mode 100644 index 0000000..cfa7606 --- /dev/null +++ b/src/gns/zonefiles/test_zonekey |